1 /*
2  *  Single source autogenerated distributable for Duktape 2.6.0.
3  *
4  *  Git commit fffa346eff06a8764b02c31d4336f63a773a95c3 (v2.6.0).
5  *  Git branch HEAD.
6  *
7  *  See Duktape AUTHORS.rst and LICENSE.txt for copyright and
8  *  licensing information.
9  */
10 
11 /* LICENSE.txt */
12 /*
13 *  ===============
14 *  Duktape license
15 *  ===============
16 *
17 *  (http://opensource.org/licenses/MIT)
18 *
19 *  Copyright (c) 2013-2019 by Duktape authors (see AUTHORS.rst)
20 *
21 *  Permission is hereby granted, free of charge, to any person obtaining a copy
22 *  of this software and associated documentation files (the "Software"), to deal
23 *  in the Software without restriction, including without limitation the rights
24 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25 *  copies of the Software, and to permit persons to whom the Software is
26 *  furnished to do so, subject to the following conditions:
27 *
28 *  The above copyright notice and this permission notice shall be included in
29 *  all copies or substantial portions of the Software.
30 *
31 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
37 *  THE SOFTWARE.
38 */
39 
40 /* AUTHORS.rst */
41 /*
42 *  ===============
43 *  Duktape authors
44 *  ===============
45 *
46 *  Copyright
47 *  =========
48 *
49 *  Duktape copyrights are held by its authors.  Each author has a copyright
50 *  to their contribution, and agrees to irrevocably license the contribution
51 *  under the Duktape ``LICENSE.txt``.
52 *
53 *  Authors
54 *  =======
55 *
56 *  Please include an e-mail address, a link to your GitHub profile, or something
57 *  similar to allow your contribution to be identified accurately.
58 *
59 *  The following people have contributed code, website contents, or Wiki contents,
60 *  and agreed to irrevocably license their contributions under the Duktape
61 *  ``LICENSE.txt`` (in order of appearance):
62 *
63 *  * Sami Vaarala <sami.vaarala@iki.fi>
64 *  * Niki Dobrev
65 *  * Andreas \u00d6man <andreas@lonelycoder.com>
66 *  * L\u00e1szl\u00f3 Lang\u00f3 <llango.u-szeged@partner.samsung.com>
67 *  * Legimet <legimet.calc@gmail.com>
68 *  * Karl Skomski <karl@skomski.com>
69 *  * Bruce Pascoe <fatcerberus1@gmail.com>
70 *  * Ren\u00e9 Hollander <rene@rene8888.at>
71 *  * Julien Hamaide (https://github.com/crazyjul)
72 *  * Sebastian G\u00f6tte (https://github.com/jaseg)
73 *  * Tomasz Magulski (https://github.com/magul)
74 *  * \D. Bohdan (https://github.com/dbohdan)
75 *  * Ond\u0159ej Jirman (https://github.com/megous)
76 *  * Sa\u00fal Ibarra Corretg\u00e9 <saghul@gmail.com>
77 *  * Jeremy HU <huxingyi@msn.com>
78 *  * Ole Andr\u00e9 Vadla Ravn\u00e5s (https://github.com/oleavr)
79 *  * Harold Brenes (https://github.com/harold-b)
80 *  * Oliver Crow (https://github.com/ocrow)
81 *  * Jakub Ch\u0142api\u0144ski (https://github.com/jchlapinski)
82 *  * Brett Vickers (https://github.com/beevik)
83 *  * Dominik Okwieka (https://github.com/okitec)
84 *  * Remko Tron\u00e7on (https://el-tramo.be)
85 *  * Romero Malaquias (rbsm@ic.ufal.br)
86 *  * Michael Drake <michael.drake@codethink.co.uk>
87 *  * Steven Don (https://github.com/shdon)
88 *  * Simon Stone (https://github.com/sstone1)
89 *  * \J. McC. (https://github.com/jmhmccr)
90 *  * Jakub Nowakowski (https://github.com/jimvonmoon)
91 *  * Tommy Nguyen (https://github.com/tn0502)
92 *  * Fabrice Fontaine (https://github.com/ffontaine)
93 *  * Christopher Hiller (https://github.com/boneskull)
94 *  * Gonzalo Diethelm (https://github.com/gonzus)
95 *  * Michal Kasperek (https://github.com/michalkas)
96 *  * Andrew Janke (https://github.com/apjanke)
97 *  * Steve Fan (https://github.com/stevefan1999)
98 *  * Edward Betts (https://github.com/edwardbetts)
99 *  * Ozhan Duz (https://github.com/webfolderio)
100 *  * Akos Kiss (https://github.com/akosthekiss)
101 *  * TheBrokenRail (https://github.com/TheBrokenRail)
102 *  * Jesse Doyle (https://github.com/jessedoyle)
103 *  * Gero Kuehn (https://github.com/dc6jgk)
104 *  * James Swift (https://github.com/phraemer)
105 *  * Luis de Bethencourt (https://github.com/luisbg)
106 *  * Ian Whyman (https://github.com/v00d00)
107 *  * Rick Sayre (https://github.com/whorfin)
108 *
109 *  Other contributions
110 *  ===================
111 *
112 *  The following people have contributed something other than code (e.g. reported
113 *  bugs, provided ideas, etc; roughly in order of appearance):
114 *
115 *  * Greg Burns
116 *  * Anthony Rabine
117 *  * Carlos Costa
118 *  * Aur\u00e9lien Bouilland
119 *  * Preet Desai (Pris Matic)
120 *  * judofyr (http://www.reddit.com/user/judofyr)
121 *  * Jason Woofenden
122 *  * Micha\u0142 Przyby\u015b
123 *  * Anthony Howe
124 *  * Conrad Pankoff
125 *  * Jim Schimpf
126 *  * Rajaran Gaunker (https://github.com/zimbabao)
127 *  * Andreas \u00d6man
128 *  * Doug Sanden
129 *  * Josh Engebretson (https://github.com/JoshEngebretson)
130 *  * Remo Eichenberger (https://github.com/remoe)
131 *  * Mamod Mehyar (https://github.com/mamod)
132 *  * David Demelier (https://github.com/markand)
133 *  * Tim Caswell (https://github.com/creationix)
134 *  * Mitchell Blank Jr (https://github.com/mitchblank)
135 *  * https://github.com/yushli
136 *  * Seo Sanghyeon (https://github.com/sanxiyn)
137 *  * Han ChoongWoo (https://github.com/tunz)
138 *  * Joshua Peek (https://github.com/josh)
139 *  * Bruce E. Pascoe (https://github.com/fatcerberus)
140 *  * https://github.com/Kelledin
141 *  * https://github.com/sstruchtrup
142 *  * Michael Drake (https://github.com/tlsa)
143 *  * https://github.com/chris-y
144 *  * Laurent Zubiaur (https://github.com/lzubiaur)
145 *  * Neil Kolban (https://github.com/nkolban)
146 *  * Wilhelm Wanecek (https://github.com/wanecek)
147 *  * Andrew Janke (https://github.com/apjanke)
148 *  * Unamer (https://github.com/unamer)
149 *  * Karl Dahlke (eklhad@gmail.com)
150 *
151 *  If you are accidentally missing from this list, send me an e-mail
152 *  (``sami.vaarala@iki.fi``) and I'll fix the omission.
153 */
154 
155 /*
156  *  Replacements for missing platform functions.
157  *
158  *  Unlike the originals, fpclassify() and signbit() replacements don't
159  *  work on any floating point types, only doubles.  The C typing here
160  *  mimics the standard prototypes.
161  */
162 
163 /* #include duk_internal.h */
164 /*
165  *  Top-level include file to be used for all (internal) source files.
166  *
167  *  Source files should not include individual header files, as they
168  *  have not been designed to be individually included.
169  */
170 
171 #if !defined(DUK_INTERNAL_H_INCLUDED)
172 #define DUK_INTERNAL_H_INCLUDED
173 
174 /*
175  *  The 'duktape.h' header provides the public API, but also handles all
176  *  compiler and platform specific feature detection, Duktape feature
177  *  resolution, inclusion of system headers, etc.  These have been merged
178  *  because the public API is also dependent on e.g. detecting appropriate
179  *  C types which is quite platform/compiler specific especially for a non-C99
180  *  build.  The public API is also dependent on the resolved feature set.
181  *
182  *  Some actions taken by the merged header (such as including system headers)
183  *  are not appropriate for building a user application.  The define
184  *  DUK_COMPILING_DUKTAPE allows the merged header to skip/include some
185  *  sections depending on what is being built.
186  */
187 
188 #define DUK_COMPILING_DUKTAPE
189 #include "duktape.h"
190 
191 /*
192  *  Duktape includes (other than duk_features.h)
193  *
194  *  The header files expect to be included in an order which satisfies header
195  *  dependencies correctly (the headers themselves don't include any other
196  *  includes).  Forward declarations are used to break circular struct/typedef
197  *  dependencies.
198  */
199 
200 /* #include duk_dblunion.h */
201 /*
202  *  Union to access IEEE double memory representation, indexes for double
203  *  memory representation, and some macros for double manipulation.
204  *
205  *  Also used by packed duk_tval.  Use a union for bit manipulation to
206  *  minimize aliasing issues in practice.  The C99 standard does not
207  *  guarantee that this should work, but it's a very widely supported
208  *  practice for low level manipulation.
209  *
210  *  IEEE double format summary:
211  *
212  *    seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
213  *       A        B        C        D        E        F        G        H
214  *
215  *    s       sign bit
216  *    eee...  exponent field
217  *    fff...  fraction
218  *
219  *  See http://en.wikipedia.org/wiki/Double_precision_floating-point_format.
220  *
221  *  NaNs are represented as exponent 0x7ff and mantissa != 0.  The NaN is a
222  *  signaling NaN when the highest bit of the mantissa is zero, and a quiet
223  *  NaN when the highest bit is set.
224  *
225  *  At least three memory layouts are relevant here:
226  *
227  *    A B C D E F G H    Big endian (e.g. 68k)           DUK_USE_DOUBLE_BE
228  *    H G F E D C B A    Little endian (e.g. x86)        DUK_USE_DOUBLE_LE
229  *    D C B A H G F E    Mixed endian (e.g. ARM FPA)     DUK_USE_DOUBLE_ME
230  *
231  *  Legacy ARM (FPA) is a special case: ARM double values are in mixed
232  *  endian format while ARM duk_uint64_t values are in standard little endian
233  *  format (H G F E D C B A).  When a double is read as a duk_uint64_t
234  *  from memory, the register will contain the (logical) value
235  *  E F G H A B C D.  This requires some special handling below.
236  *  See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0056d/Bcfhgcgd.html.
237  *
238  *  Indexes of various types (8-bit, 16-bit, 32-bit) in memory relative to
239  *  the logical (big endian) order:
240  *
241  *  byte order      duk_uint8_t    duk_uint16_t     duk_uint32_t
242  *    BE             01234567         0123               01
243  *    LE             76543210         3210               10
244  *    ME (ARM)       32107654         1032               01
245  *
246  *  Some processors may alter NaN values in a floating point load+store.
247  *  For instance, on X86 a FLD + FSTP may convert a signaling NaN to a
248  *  quiet one.  This is catastrophic when NaN space is used in packed
249  *  duk_tval values.  See: misc/clang_aliasing.c.
250  */
251 
252 #if !defined(DUK_DBLUNION_H_INCLUDED)
253 #define DUK_DBLUNION_H_INCLUDED
254 
255 /*
256  *  Union for accessing double parts, also serves as packed duk_tval
257  */
258 
259 union duk_double_union {
260 	double d;
261 	float f[2];
262 #if defined(DUK_USE_64BIT_OPS)
263 	duk_uint64_t ull[1];
264 #endif
265 	duk_uint32_t ui[2];
266 	duk_uint16_t us[4];
267 	duk_uint8_t uc[8];
268 #if defined(DUK_USE_PACKED_TVAL)
269 	void *vp[2];  /* used by packed duk_tval, assumes sizeof(void *) == 4 */
270 #endif
271 };
272 
273 typedef union duk_double_union duk_double_union;
274 
275 /*
276  *  Indexes of various types with respect to big endian (logical) layout
277  */
278 
279 #if defined(DUK_USE_DOUBLE_LE)
280 #if defined(DUK_USE_64BIT_OPS)
281 #define DUK_DBL_IDX_ULL0   0
282 #endif
283 #define DUK_DBL_IDX_UI0    1
284 #define DUK_DBL_IDX_UI1    0
285 #define DUK_DBL_IDX_US0    3
286 #define DUK_DBL_IDX_US1    2
287 #define DUK_DBL_IDX_US2    1
288 #define DUK_DBL_IDX_US3    0
289 #define DUK_DBL_IDX_UC0    7
290 #define DUK_DBL_IDX_UC1    6
291 #define DUK_DBL_IDX_UC2    5
292 #define DUK_DBL_IDX_UC3    4
293 #define DUK_DBL_IDX_UC4    3
294 #define DUK_DBL_IDX_UC5    2
295 #define DUK_DBL_IDX_UC6    1
296 #define DUK_DBL_IDX_UC7    0
297 #define DUK_DBL_IDX_VP0    DUK_DBL_IDX_UI0  /* packed tval */
298 #define DUK_DBL_IDX_VP1    DUK_DBL_IDX_UI1  /* packed tval */
299 #elif defined(DUK_USE_DOUBLE_BE)
300 #if defined(DUK_USE_64BIT_OPS)
301 #define DUK_DBL_IDX_ULL0   0
302 #endif
303 #define DUK_DBL_IDX_UI0    0
304 #define DUK_DBL_IDX_UI1    1
305 #define DUK_DBL_IDX_US0    0
306 #define DUK_DBL_IDX_US1    1
307 #define DUK_DBL_IDX_US2    2
308 #define DUK_DBL_IDX_US3    3
309 #define DUK_DBL_IDX_UC0    0
310 #define DUK_DBL_IDX_UC1    1
311 #define DUK_DBL_IDX_UC2    2
312 #define DUK_DBL_IDX_UC3    3
313 #define DUK_DBL_IDX_UC4    4
314 #define DUK_DBL_IDX_UC5    5
315 #define DUK_DBL_IDX_UC6    6
316 #define DUK_DBL_IDX_UC7    7
317 #define DUK_DBL_IDX_VP0    DUK_DBL_IDX_UI0  /* packed tval */
318 #define DUK_DBL_IDX_VP1    DUK_DBL_IDX_UI1  /* packed tval */
319 #elif defined(DUK_USE_DOUBLE_ME)
320 #if defined(DUK_USE_64BIT_OPS)
321 #define DUK_DBL_IDX_ULL0   0  /* not directly applicable, byte order differs from a double */
322 #endif
323 #define DUK_DBL_IDX_UI0    0
324 #define DUK_DBL_IDX_UI1    1
325 #define DUK_DBL_IDX_US0    1
326 #define DUK_DBL_IDX_US1    0
327 #define DUK_DBL_IDX_US2    3
328 #define DUK_DBL_IDX_US3    2
329 #define DUK_DBL_IDX_UC0    3
330 #define DUK_DBL_IDX_UC1    2
331 #define DUK_DBL_IDX_UC2    1
332 #define DUK_DBL_IDX_UC3    0
333 #define DUK_DBL_IDX_UC4    7
334 #define DUK_DBL_IDX_UC5    6
335 #define DUK_DBL_IDX_UC6    5
336 #define DUK_DBL_IDX_UC7    4
337 #define DUK_DBL_IDX_VP0    DUK_DBL_IDX_UI0  /* packed tval */
338 #define DUK_DBL_IDX_VP1    DUK_DBL_IDX_UI1  /* packed tval */
339 #else
340 #error internal error
341 #endif
342 
343 /*
344  *  Helper macros for reading/writing memory representation parts, used
345  *  by duk_numconv.c and duk_tval.h.
346  */
347 
348 #define DUK_DBLUNION_SET_DOUBLE(u,v)  do {  \
349 		(u)->d = (v); \
350 	} while (0)
351 
352 #define DUK_DBLUNION_SET_HIGH32(u,v)  do {  \
353 		(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) (v); \
354 	} while (0)
355 
356 #if defined(DUK_USE_64BIT_OPS)
357 #if defined(DUK_USE_DOUBLE_ME)
358 #define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u,v)  do { \
359 		(u)->ull[DUK_DBL_IDX_ULL0] = (duk_uint64_t) (v); \
360 	} while (0)
361 #else
362 #define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u,v)  do { \
363 		(u)->ull[DUK_DBL_IDX_ULL0] = ((duk_uint64_t) (v)) << 32; \
364 	} while (0)
365 #endif
366 #else  /* DUK_USE_64BIT_OPS */
367 #define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u,v)  do { \
368 		(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) (v); \
369 		(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) 0; \
370 	} while (0)
371 #endif  /* DUK_USE_64BIT_OPS */
372 
373 #define DUK_DBLUNION_SET_LOW32(u,v)  do {  \
374 		(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (v); \
375 	} while (0)
376 
377 #define DUK_DBLUNION_GET_DOUBLE(u)  ((u)->d)
378 #define DUK_DBLUNION_GET_HIGH32(u)  ((u)->ui[DUK_DBL_IDX_UI0])
379 #define DUK_DBLUNION_GET_LOW32(u)   ((u)->ui[DUK_DBL_IDX_UI1])
380 
381 #if defined(DUK_USE_64BIT_OPS)
382 #if defined(DUK_USE_DOUBLE_ME)
383 #define DUK_DBLUNION_SET_UINT64(u,v)  do { \
384 		(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) ((v) >> 32); \
385 		(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (v); \
386 	} while (0)
387 #define DUK_DBLUNION_GET_UINT64(u) \
388 	((((duk_uint64_t) (u)->ui[DUK_DBL_IDX_UI0]) << 32) | \
389 	 ((duk_uint64_t) (u)->ui[DUK_DBL_IDX_UI1]))
390 #else
391 #define DUK_DBLUNION_SET_UINT64(u,v)  do { \
392 		(u)->ull[DUK_DBL_IDX_ULL0] = (duk_uint64_t) (v); \
393 	} while (0)
394 #define DUK_DBLUNION_GET_UINT64(u)  ((u)->ull[DUK_DBL_IDX_ULL0])
395 #endif
396 #define DUK_DBLUNION_SET_INT64(u,v) DUK_DBLUNION_SET_UINT64((u), (duk_uint64_t) (v))
397 #define DUK_DBLUNION_GET_INT64(u)   ((duk_int64_t) DUK_DBLUNION_GET_UINT64((u)))
398 #endif  /* DUK_USE_64BIT_OPS */
399 
400 /*
401  *  Double NaN manipulation macros related to NaN normalization needed when
402  *  using the packed duk_tval representation.  NaN normalization is necessary
403  *  to keep double values compatible with the duk_tval format.
404  *
405  *  When packed duk_tval is used, the NaN space is used to store pointers
406  *  and other tagged values in addition to NaNs.  Actual NaNs are normalized
407  *  to a specific quiet NaN.  The macros below are used by the implementation
408  *  to check and normalize NaN values when they might be created.  The macros
409  *  are essentially NOPs when the non-packed duk_tval representation is used.
410  *
411  *  A FULL check is exact and checks all bits.  A NOTFULL check is used by
412  *  the packed duk_tval and works correctly for all NaNs except those that
413  *  begin with 0x7ff0.  Since the 'normalized NaN' values used with packed
414  *  duk_tval begin with 0x7ff8, the partial check is reliable when packed
415  *  duk_tval is used.  The 0x7ff8 prefix means the normalized NaN will be a
416  *  quiet NaN regardless of its remaining lower bits.
417  *
418  *  The ME variant below is specifically for ARM byte order, which has the
419  *  feature that while doubles have a mixed byte order (32107654), unsigned
420  *  long long values has a little endian byte order (76543210).  When writing
421  *  a logical double value through a ULL pointer, the 32-bit words need to be
422  *  swapped; hence the #if defined()s below for ULL writes with DUK_USE_DOUBLE_ME.
423  *  This is not full ARM support but suffices for some environments.
424  */
425 
426 #if defined(DUK_USE_64BIT_OPS)
427 #if defined(DUK_USE_DOUBLE_ME)
428 /* Macros for 64-bit ops + mixed endian doubles. */
429 #define DUK__DBLUNION_SET_NAN_FULL(u)  do { \
430 		(u)->ull[DUK_DBL_IDX_ULL0] = DUK_U64_CONSTANT(0x000000007ff80000); \
431 	} while (0)
432 #define DUK__DBLUNION_IS_NAN_FULL(u) \
433 	((((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000)) == DUK_U64_CONSTANT(0x000000007ff00000)) && \
434 	 ((((u)->ull[DUK_DBL_IDX_ULL0]) & DUK_U64_CONSTANT(0xffffffff000fffff)) != 0))
435 #define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) \
436 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x000000007ff80000))
437 #define DUK__DBLUNION_IS_ANYINF(u) \
438 	(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0xffffffff7fffffff)) == DUK_U64_CONSTANT(0x000000007ff00000))
439 #define DUK__DBLUNION_IS_POSINF(u) \
440 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x000000007ff00000))
441 #define DUK__DBLUNION_IS_NEGINF(u) \
442 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x00000000fff00000))
443 #define DUK__DBLUNION_IS_ANYZERO(u) \
444 	(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0xffffffff7fffffff)) == DUK_U64_CONSTANT(0x0000000000000000))
445 #define DUK__DBLUNION_IS_POSZERO(u) \
446 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000000000000))
447 #define DUK__DBLUNION_IS_NEGZERO(u) \
448 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000080000000))
449 #else
450 /* Macros for 64-bit ops + big/little endian doubles. */
451 #define DUK__DBLUNION_SET_NAN_FULL(u)  do { \
452 		(u)->ull[DUK_DBL_IDX_ULL0] = DUK_U64_CONSTANT(0x7ff8000000000000); \
453 	} while (0)
454 #define DUK__DBLUNION_IS_NAN_FULL(u) \
455 	((((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000)) == DUK_U64_CONSTANT(0x7ff0000000000000)) && \
456 	 ((((u)->ull[DUK_DBL_IDX_ULL0]) & DUK_U64_CONSTANT(0x000fffffffffffff)) != 0))
457 #define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) \
458 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x7ff8000000000000))
459 #define DUK__DBLUNION_IS_ANYINF(u) \
460 	(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7fffffffffffffff)) == DUK_U64_CONSTANT(0x7ff0000000000000))
461 #define DUK__DBLUNION_IS_POSINF(u) \
462 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x7ff0000000000000))
463 #define DUK__DBLUNION_IS_NEGINF(u) \
464 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0xfff0000000000000))
465 #define DUK__DBLUNION_IS_ANYZERO(u) \
466 	(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7fffffffffffffff)) == DUK_U64_CONSTANT(0x0000000000000000))
467 #define DUK__DBLUNION_IS_POSZERO(u) \
468 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000000000000))
469 #define DUK__DBLUNION_IS_NEGZERO(u) \
470 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x8000000000000000))
471 #endif
472 #else  /* DUK_USE_64BIT_OPS */
473 /* Macros for no 64-bit ops, any endianness. */
474 #define DUK__DBLUNION_SET_NAN_FULL(u)  do { \
475 		(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) 0x7ff80000UL; \
476 		(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) 0x00000000UL; \
477 	} while (0)
478 #define DUK__DBLUNION_IS_NAN_FULL(u) \
479 	((((u)->ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL) == 0x7ff00000UL) && \
480 	 (((u)->ui[DUK_DBL_IDX_UI0] & 0x000fffffUL) != 0 || \
481           (u)->ui[DUK_DBL_IDX_UI1] != 0))
482 #define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) \
483 	(((u)->ui[DUK_DBL_IDX_UI0] == 0x7ff80000UL) && \
484 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
485 #define DUK__DBLUNION_IS_ANYINF(u) \
486 	((((u)->ui[DUK_DBL_IDX_UI0] & 0x7fffffffUL) == 0x7ff00000UL) && \
487 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
488 #define DUK__DBLUNION_IS_POSINF(u) \
489 	(((u)->ui[DUK_DBL_IDX_UI0] == 0x7ff00000UL) && \
490 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
491 #define DUK__DBLUNION_IS_NEGINF(u) \
492 	(((u)->ui[DUK_DBL_IDX_UI0] == 0xfff00000UL) && \
493 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
494 #define DUK__DBLUNION_IS_ANYZERO(u) \
495 	((((u)->ui[DUK_DBL_IDX_UI0] & 0x7fffffffUL) == 0x00000000UL) && \
496 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
497 #define DUK__DBLUNION_IS_POSZERO(u) \
498 	(((u)->ui[DUK_DBL_IDX_UI0] == 0x00000000UL) && \
499 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
500 #define DUK__DBLUNION_IS_NEGZERO(u) \
501 	(((u)->ui[DUK_DBL_IDX_UI0] == 0x80000000UL) && \
502 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
503 #endif  /* DUK_USE_64BIT_OPS */
504 
505 #define DUK__DBLUNION_SET_NAN_NOTFULL(u)  do { \
506 		(u)->us[DUK_DBL_IDX_US0] = 0x7ff8UL; \
507 	} while (0)
508 
509 #define DUK__DBLUNION_IS_NAN_NOTFULL(u) \
510 	/* E == 0x7ff, topmost four bits of F != 0 => assume NaN */ \
511 	((((u)->us[DUK_DBL_IDX_US0] & 0x7ff0UL) == 0x7ff0UL) && \
512 	 (((u)->us[DUK_DBL_IDX_US0] & 0x000fUL) != 0x0000UL))
513 
514 #define DUK__DBLUNION_IS_NORMALIZED_NAN_NOTFULL(u) \
515 	/* E == 0x7ff, F == 8 => normalized NaN */ \
516 	((u)->us[DUK_DBL_IDX_US0] == 0x7ff8UL)
517 
518 #define DUK__DBLUNION_NORMALIZE_NAN_CHECK_FULL(u)  do { \
519 		if (DUK__DBLUNION_IS_NAN_FULL((u))) { \
520 			DUK__DBLUNION_SET_NAN_FULL((u)); \
521 		} \
522 	} while (0)
523 
524 #define DUK__DBLUNION_NORMALIZE_NAN_CHECK_NOTFULL(u)  do { \
525 		/* Check must be full. */ \
526 		if (DUK__DBLUNION_IS_NAN_FULL((u))) { \
527 			DUK__DBLUNION_SET_NAN_NOTFULL((u)); \
528 		} \
529 	} while (0)
530 
531 /* Concrete macros for NaN handling used by the implementation internals.
532  * Chosen so that they match the duk_tval representation: with a packed
533  * duk_tval, ensure NaNs are properly normalized; with a non-packed duk_tval
534  * these are essentially NOPs.
535  */
536 
537 #if defined(DUK_USE_PACKED_TVAL)
538 #define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u)  DUK__DBLUNION_NORMALIZE_NAN_CHECK_FULL((u))
539 #define DUK_DBLUNION_IS_NAN(u)               DUK__DBLUNION_IS_NAN_FULL((u))
540 #define DUK_DBLUNION_IS_NORMALIZED_NAN(u)    DUK__DBLUNION_IS_NORMALIZED_NAN_FULL((u))
541 #define DUK_DBLUNION_SET_NAN(d)              DUK__DBLUNION_SET_NAN_FULL((d))
542 #if 0
543 #define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u)  DUK__DBLUNION_NORMALIZE_NAN_CHECK_NOTFULL((u))
544 #define DUK_DBLUNION_IS_NAN(u)               DUK__DBLUNION_IS_NAN_NOTFULL((u))
545 #define DUK_DBLUNION_IS_NORMALIZED_NAN(u)    DUK__DBLUNION_IS_NORMALIZED_NAN_NOTFULL((u))
546 #define DUK_DBLUNION_SET_NAN(d)              DUK__DBLUNION_SET_NAN_NOTFULL((d))
547 #endif
548 #define DUK_DBLUNION_IS_NORMALIZED(u) \
549 	(!DUK_DBLUNION_IS_NAN((u)) ||  /* either not a NaN */ \
550 	 DUK_DBLUNION_IS_NORMALIZED_NAN((u)))  /* or is a normalized NaN */
551 #else  /* DUK_USE_PACKED_TVAL */
552 #define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u)  /* nop: no need to normalize */
553 #define DUK_DBLUNION_IS_NAN(u)               DUK__DBLUNION_IS_NAN_FULL((u))  /* (DUK_ISNAN((u)->d)) */
554 #define DUK_DBLUNION_IS_NORMALIZED_NAN(u)    DUK__DBLUNION_IS_NAN_FULL((u))  /* (DUK_ISNAN((u)->d)) */
555 #define DUK_DBLUNION_IS_NORMALIZED(u)        1  /* all doubles are considered normalized */
556 #define DUK_DBLUNION_SET_NAN(u)  do { \
557 		/* in non-packed representation we don't care about which NaN is used */ \
558 		(u)->d = DUK_DOUBLE_NAN; \
559 	} while (0)
560 #endif  /* DUK_USE_PACKED_TVAL */
561 
562 #define DUK_DBLUNION_IS_ANYINF(u) DUK__DBLUNION_IS_ANYINF((u))
563 #define DUK_DBLUNION_IS_POSINF(u) DUK__DBLUNION_IS_POSINF((u))
564 #define DUK_DBLUNION_IS_NEGINF(u) DUK__DBLUNION_IS_NEGINF((u))
565 
566 #define DUK_DBLUNION_IS_ANYZERO(u) DUK__DBLUNION_IS_ANYZERO((u))
567 #define DUK_DBLUNION_IS_POSZERO(u) DUK__DBLUNION_IS_POSZERO((u))
568 #define DUK_DBLUNION_IS_NEGZERO(u) DUK__DBLUNION_IS_NEGZERO((u))
569 
570 /* XXX: native 64-bit byteswaps when available */
571 
572 /* 64-bit byteswap, same operation independent of target endianness. */
573 #define DUK_DBLUNION_BSWAP64(u) do { \
574 		duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \
575 		duk__bswaptmp1 = (u)->ui[0]; \
576 		duk__bswaptmp2 = (u)->ui[1]; \
577 		duk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \
578 		duk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \
579 		(u)->ui[0] = duk__bswaptmp2; \
580 		(u)->ui[1] = duk__bswaptmp1; \
581 	} while (0)
582 
583 /* Byteswap an IEEE double in the duk_double_union from host to network
584  * order.  For a big endian target this is a no-op.
585  */
586 #if defined(DUK_USE_DOUBLE_LE)
587 #define DUK_DBLUNION_DOUBLE_HTON(u) do { \
588 		duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \
589 		duk__bswaptmp1 = (u)->ui[0]; \
590 		duk__bswaptmp2 = (u)->ui[1]; \
591 		duk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \
592 		duk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \
593 		(u)->ui[0] = duk__bswaptmp2; \
594 		(u)->ui[1] = duk__bswaptmp1; \
595 	} while (0)
596 #elif defined(DUK_USE_DOUBLE_ME)
597 #define DUK_DBLUNION_DOUBLE_HTON(u) do { \
598 		duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \
599 		duk__bswaptmp1 = (u)->ui[0]; \
600 		duk__bswaptmp2 = (u)->ui[1]; \
601 		duk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \
602 		duk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \
603 		(u)->ui[0] = duk__bswaptmp1; \
604 		(u)->ui[1] = duk__bswaptmp2; \
605 	} while (0)
606 #elif defined(DUK_USE_DOUBLE_BE)
607 #define DUK_DBLUNION_DOUBLE_HTON(u) do { } while (0)
608 #else
609 #error internal error, double endianness insane
610 #endif
611 
612 /* Reverse operation is the same. */
613 #define DUK_DBLUNION_DOUBLE_NTOH(u) DUK_DBLUNION_DOUBLE_HTON((u))
614 
615 /* Some sign bit helpers. */
616 #if defined(DUK_USE_64BIT_OPS)
617 #define DUK_DBLUNION_HAS_SIGNBIT(u) (((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x8000000000000000)) != 0)
618 #define DUK_DBLUNION_GET_SIGNBIT(u) (((u)->ull[DUK_DBL_IDX_ULL0] >> 63U))
619 #else
620 #define DUK_DBLUNION_HAS_SIGNBIT(u) (((u)->ui[DUK_DBL_IDX_UI0] & 0x80000000UL) != 0)
621 #define DUK_DBLUNION_GET_SIGNBIT(u) (((u)->ui[DUK_DBL_IDX_UI0] >> 31U))
622 #endif
623 
624 #endif  /* DUK_DBLUNION_H_INCLUDED */
625 /* #include duk_fltunion.h */
626 /*
627  *  Union to access IEEE float memory representation.
628  */
629 
630 #if !defined(DUK_FLTUNION_H_INCLUDED)
631 #define DUK_FLTUNION_H_INCLUDED
632 
633 /* #include duk_internal.h -> already included */
634 
635 union duk_float_union {
636 	float f;
637 	duk_uint32_t ui[1];
638 	duk_uint16_t us[2];
639 	duk_uint8_t uc[4];
640 };
641 
642 typedef union duk_float_union duk_float_union;
643 
644 #if defined(DUK_USE_DOUBLE_LE) || defined(DUK_USE_DOUBLE_ME)
645 #define DUK_FLT_IDX_UI0    0
646 #define DUK_FLT_IDX_US0    1
647 #define DUK_FLT_IDX_US1    0
648 #define DUK_FLT_IDX_UC0    3
649 #define DUK_FLT_IDX_UC1    2
650 #define DUK_FLT_IDX_UC2    1
651 #define DUK_FLT_IDX_UC3    0
652 #elif defined(DUK_USE_DOUBLE_BE)
653 #define DUK_FLT_IDX_UI0    0
654 #define DUK_FLT_IDX_US0    0
655 #define DUK_FLT_IDX_US1    1
656 #define DUK_FLT_IDX_UC0    0
657 #define DUK_FLT_IDX_UC1    1
658 #define DUK_FLT_IDX_UC2    2
659 #define DUK_FLT_IDX_UC3    3
660 #else
661 #error internal error
662 #endif
663 
664 #endif  /* DUK_FLTUNION_H_INCLUDED */
665 /* #include duk_replacements.h */
666 #if !defined(DUK_REPLACEMENTS_H_INCLUDED)
667 #define DUK_REPLACEMENTS_H_INCLUDED
668 
669 #if !defined(DUK_SINGLE_FILE)
670 #if defined(DUK_USE_COMPUTED_INFINITY)
671 DUK_INTERNAL_DECL double duk_computed_infinity;
672 #endif
673 #if defined(DUK_USE_COMPUTED_NAN)
674 DUK_INTERNAL_DECL double duk_computed_nan;
675 #endif
676 #endif  /* !DUK_SINGLE_FILE */
677 
678 #if defined(DUK_USE_REPL_FPCLASSIFY)
679 DUK_INTERNAL_DECL int duk_repl_fpclassify(double x);
680 #endif
681 #if defined(DUK_USE_REPL_SIGNBIT)
682 DUK_INTERNAL_DECL int duk_repl_signbit(double x);
683 #endif
684 #if defined(DUK_USE_REPL_ISFINITE)
685 DUK_INTERNAL_DECL int duk_repl_isfinite(double x);
686 #endif
687 #if defined(DUK_USE_REPL_ISNAN)
688 DUK_INTERNAL_DECL int duk_repl_isnan(double x);
689 #endif
690 #if defined(DUK_USE_REPL_ISINF)
691 DUK_INTERNAL_DECL int duk_repl_isinf(double x);
692 #endif
693 
694 #endif  /* DUK_REPLACEMENTS_H_INCLUDED */
695 /* #include duk_jmpbuf.h */
696 /*
697  *  Wrapper for jmp_buf.
698  *
699  *  This is used because jmp_buf is an array type for backward compatibility.
700  *  Wrapping jmp_buf in a struct makes pointer references, sizeof, etc,
701  *  behave more intuitively.
702  *
703  *  http://en.wikipedia.org/wiki/Setjmp.h#Member_types
704  */
705 
706 #if !defined(DUK_JMPBUF_H_INCLUDED)
707 #define DUK_JMPBUF_H_INCLUDED
708 
709 #if defined(DUK_USE_CPP_EXCEPTIONS)
710 struct duk_jmpbuf {
711 	duk_small_int_t dummy;  /* unused */
712 };
713 #else
714 struct duk_jmpbuf {
715 	DUK_JMPBUF_TYPE jb;
716 };
717 #endif
718 
719 #endif  /* DUK_JMPBUF_H_INCLUDED */
720 /* #include duk_exception.h */
721 /*
722  *  Exceptions for Duktape internal throws when C++ exceptions are used
723  *  for long control transfers.
724  */
725 
726 #if !defined(DUK_EXCEPTION_H_INCLUDED)
727 #define DUK_EXCEPTION_H_INCLUDED
728 
729 #if defined(DUK_USE_CPP_EXCEPTIONS)
730 /* Internal exception used as a setjmp-longjmp replacement.  User code should
731  * NEVER see or catch this exception, so it doesn't inherit from any base
732  * class which should minimize the chance of user code accidentally catching
733  * the exception.
734  */
735 class duk_internal_exception {
736 	/* intentionally empty */
737 };
738 
739 /* Fatal error, thrown as a specific C++ exception with C++ exceptions
740  * enabled.  It is unsafe to continue; doing so may cause crashes or memory
741  * leaks.  This is intended to be either uncaught, or caught by user code
742  * aware of the "unsafe to continue" semantics.
743  */
744 class duk_fatal_exception : public virtual std::runtime_error {
745  public:
duk_fatal_exception(const char * message)746 	duk_fatal_exception(const char *message) : std::runtime_error(message) {}
747 };
748 #endif
749 
750 #endif  /* DUK_EXCEPTION_H_INCLUDED */
751 /* #include duk_forwdecl.h */
752 /*
753  *  Forward declarations for all Duktape structures.
754  */
755 
756 #if !defined(DUK_FORWDECL_H_INCLUDED)
757 #define DUK_FORWDECL_H_INCLUDED
758 
759 /*
760  *  Forward declarations
761  */
762 
763 #if defined(DUK_USE_CPP_EXCEPTIONS)
764 class duk_internal_exception;
765 #else
766 struct duk_jmpbuf;
767 #endif
768 
769 /* duk_tval intentionally skipped */
770 struct duk_heaphdr;
771 struct duk_heaphdr_string;
772 struct duk_harray;
773 struct duk_hstring;
774 struct duk_hstring_external;
775 struct duk_hobject;
776 struct duk_hcompfunc;
777 struct duk_hnatfunc;
778 struct duk_hboundfunc;
779 struct duk_hthread;
780 struct duk_hbufobj;
781 struct duk_hdecenv;
782 struct duk_hobjenv;
783 struct duk_hproxy;
784 struct duk_hbuffer;
785 struct duk_hbuffer_fixed;
786 struct duk_hbuffer_dynamic;
787 struct duk_hbuffer_external;
788 
789 struct duk_propaccessor;
790 union duk_propvalue;
791 struct duk_propdesc;
792 
793 struct duk_heap;
794 struct duk_breakpoint;
795 
796 struct duk_activation;
797 struct duk_catcher;
798 struct duk_ljstate;
799 struct duk_strcache_entry;
800 struct duk_litcache_entry;
801 struct duk_strtab_entry;
802 
803 #if defined(DUK_USE_DEBUG)
804 struct duk_fixedbuffer;
805 #endif
806 
807 struct duk_bitdecoder_ctx;
808 struct duk_bitencoder_ctx;
809 struct duk_bufwriter_ctx;
810 
811 struct duk_token;
812 struct duk_re_token;
813 struct duk_lexer_point;
814 struct duk_lexer_ctx;
815 struct duk_lexer_codepoint;
816 
817 struct duk_compiler_instr;
818 struct duk_compiler_func;
819 struct duk_compiler_ctx;
820 
821 struct duk_re_matcher_ctx;
822 struct duk_re_compiler_ctx;
823 
824 #if defined(DUK_USE_CPP_EXCEPTIONS)
825 /* no typedef */
826 #else
827 typedef struct duk_jmpbuf duk_jmpbuf;
828 #endif
829 
830 /* duk_tval intentionally skipped */
831 typedef struct duk_heaphdr duk_heaphdr;
832 typedef struct duk_heaphdr_string duk_heaphdr_string;
833 typedef struct duk_harray duk_harray;
834 typedef struct duk_hstring duk_hstring;
835 typedef struct duk_hstring_external duk_hstring_external;
836 typedef struct duk_hobject duk_hobject;
837 typedef struct duk_hcompfunc duk_hcompfunc;
838 typedef struct duk_hnatfunc duk_hnatfunc;
839 typedef struct duk_hboundfunc duk_hboundfunc;
840 typedef struct duk_hthread duk_hthread;
841 typedef struct duk_hbufobj duk_hbufobj;
842 typedef struct duk_hdecenv duk_hdecenv;
843 typedef struct duk_hobjenv duk_hobjenv;
844 typedef struct duk_hproxy duk_hproxy;
845 typedef struct duk_hbuffer duk_hbuffer;
846 typedef struct duk_hbuffer_fixed duk_hbuffer_fixed;
847 typedef struct duk_hbuffer_dynamic duk_hbuffer_dynamic;
848 typedef struct duk_hbuffer_external duk_hbuffer_external;
849 
850 typedef struct duk_propaccessor duk_propaccessor;
851 typedef union duk_propvalue duk_propvalue;
852 typedef struct duk_propdesc duk_propdesc;
853 
854 typedef struct duk_heap duk_heap;
855 typedef struct duk_breakpoint duk_breakpoint;
856 
857 typedef struct duk_activation duk_activation;
858 typedef struct duk_catcher duk_catcher;
859 typedef struct duk_ljstate duk_ljstate;
860 typedef struct duk_strcache_entry duk_strcache_entry;
861 typedef struct duk_litcache_entry duk_litcache_entry;
862 typedef struct duk_strtab_entry duk_strtab_entry;
863 
864 #if defined(DUK_USE_DEBUG)
865 typedef struct duk_fixedbuffer duk_fixedbuffer;
866 #endif
867 
868 typedef struct duk_bitdecoder_ctx duk_bitdecoder_ctx;
869 typedef struct duk_bitencoder_ctx duk_bitencoder_ctx;
870 typedef struct duk_bufwriter_ctx duk_bufwriter_ctx;
871 
872 typedef struct duk_token duk_token;
873 typedef struct duk_re_token duk_re_token;
874 typedef struct duk_lexer_point duk_lexer_point;
875 typedef struct duk_lexer_ctx duk_lexer_ctx;
876 typedef struct duk_lexer_codepoint duk_lexer_codepoint;
877 
878 typedef struct duk_compiler_instr duk_compiler_instr;
879 typedef struct duk_compiler_func duk_compiler_func;
880 typedef struct duk_compiler_ctx duk_compiler_ctx;
881 
882 typedef struct duk_re_matcher_ctx duk_re_matcher_ctx;
883 typedef struct duk_re_compiler_ctx duk_re_compiler_ctx;
884 
885 #endif  /* DUK_FORWDECL_H_INCLUDED */
886 /* #include duk_tval.h */
887 /*
888  *  Tagged type definition (duk_tval) and accessor macros.
889  *
890  *  Access all fields through the accessor macros, as the representation
891  *  is quite tricky.
892  *
893  *  There are two packed type alternatives: an 8-byte representation
894  *  based on an IEEE double (preferred for compactness), and a 12-byte
895  *  representation (portability).  The latter is needed also in e.g.
896  *  64-bit environments (it usually pads to 16 bytes per value).
897  *
898  *  Selecting the tagged type format involves many trade-offs (memory
899  *  use, size and performance of generated code, portability, etc).
900  *
901  *  NB: because macro arguments are often expressions, macros should
902  *  avoid evaluating their argument more than once.
903  */
904 
905 #if !defined(DUK_TVAL_H_INCLUDED)
906 #define DUK_TVAL_H_INCLUDED
907 
908 /* sanity */
909 #if !defined(DUK_USE_DOUBLE_LE) && !defined(DUK_USE_DOUBLE_ME) && !defined(DUK_USE_DOUBLE_BE)
910 #error unsupported: cannot determine byte order variant
911 #endif
912 
913 #if defined(DUK_USE_PACKED_TVAL)
914 /* ======================================================================== */
915 
916 /*
917  *  Packed 8-byte representation
918  */
919 
920 /* use duk_double_union as duk_tval directly */
921 typedef union duk_double_union duk_tval;
922 typedef struct {
923 	duk_uint16_t a;
924 	duk_uint16_t b;
925 	duk_uint16_t c;
926 	duk_uint16_t d;
927 } duk_tval_unused;
928 
929 /* tags */
930 #define DUK_TAG_NORMALIZED_NAN    0x7ff8UL   /* the NaN variant we use */
931 /* avoid tag 0xfff0, no risk of confusion with negative infinity */
932 #define DUK_TAG_MIN               0xfff1UL
933 #if defined(DUK_USE_FASTINT)
934 #define DUK_TAG_FASTINT           0xfff1UL   /* embed: integer value */
935 #endif
936 #define DUK_TAG_UNUSED            0xfff2UL   /* marker; not actual tagged value */
937 #define DUK_TAG_UNDEFINED         0xfff3UL   /* embed: nothing */
938 #define DUK_TAG_NULL              0xfff4UL   /* embed: nothing */
939 #define DUK_TAG_BOOLEAN           0xfff5UL   /* embed: 0 or 1 (false or true) */
940 /* DUK_TAG_NUMBER would logically go here, but it has multiple 'tags' */
941 #define DUK_TAG_POINTER           0xfff6UL   /* embed: void ptr */
942 #define DUK_TAG_LIGHTFUNC         0xfff7UL   /* embed: func ptr */
943 #define DUK_TAG_STRING            0xfff8UL   /* embed: duk_hstring ptr */
944 #define DUK_TAG_OBJECT            0xfff9UL   /* embed: duk_hobject ptr */
945 #define DUK_TAG_BUFFER            0xfffaUL   /* embed: duk_hbuffer ptr */
946 #define DUK_TAG_MAX               0xfffaUL
947 
948 /* for convenience */
949 #define DUK_XTAG_BOOLEAN_FALSE    0xfff50000UL
950 #define DUK_XTAG_BOOLEAN_TRUE     0xfff50001UL
951 
952 #define DUK_TVAL_IS_VALID_TAG(tv) \
953 	(DUK_TVAL_GET_TAG((tv)) - DUK_TAG_MIN <= DUK_TAG_MAX - DUK_TAG_MIN)
954 
955 /* DUK_TVAL_UNUSED initializer for duk_tval_unused, works for any endianness. */
956 #define DUK_TVAL_UNUSED_INITIALIZER() \
957 	{ DUK_TAG_UNUSED, DUK_TAG_UNUSED, DUK_TAG_UNUSED, DUK_TAG_UNUSED }
958 
959 /* two casts to avoid gcc warning: "warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]" */
960 #if defined(DUK_USE_64BIT_OPS)
961 #if defined(DUK_USE_DOUBLE_ME)
962 #define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag)  do { \
963 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 16) | (((duk_uint64_t) (duk_uint32_t) (h)) << 32); \
964 	} while (0)
965 #else
966 #define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag)  do { \
967 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 48) | ((duk_uint64_t) (duk_uint32_t) (h)); \
968 	} while (0)
969 #endif
970 #else  /* DUK_USE_64BIT_OPS */
971 #define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag)  do { \
972 		duk_tval *duk__tv; \
973 		duk__tv = (tv); \
974 		duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) (tag)) << 16; \
975 		duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (h); \
976 	} while (0)
977 #endif  /* DUK_USE_64BIT_OPS */
978 
979 #if defined(DUK_USE_64BIT_OPS)
980 /* Double casting for pointer to avoid gcc warning (cast from pointer to integer of different size) */
981 #if defined(DUK_USE_DOUBLE_ME)
982 #define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \
983 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 16) | \
984 		                              ((duk_uint64_t) (flags)) | \
985 		                              (((duk_uint64_t) (duk_uint32_t) (fp)) << 32); \
986 	} while (0)
987 #else
988 #define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \
989 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 48) | \
990 		                              (((duk_uint64_t) (flags)) << 32) | \
991 		                              ((duk_uint64_t) (duk_uint32_t) (fp)); \
992 	} while (0)
993 #endif
994 #else  /* DUK_USE_64BIT_OPS */
995 #define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \
996 		duk_tval *duk__tv; \
997 		duk__tv = (tv); \
998 		duk__tv->ui[DUK_DBL_IDX_UI0] = (((duk_uint32_t) DUK_TAG_LIGHTFUNC) << 16) | ((duk_uint32_t) (flags)); \
999 		duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (fp); \
1000 	} while (0)
1001 #endif  /* DUK_USE_64BIT_OPS */
1002 
1003 #if defined(DUK_USE_FASTINT)
1004 /* Note: masking is done for 'i' to deal with negative numbers correctly */
1005 #if defined(DUK_USE_DOUBLE_ME)
1006 #define DUK__TVAL_SET_I48(tv,i)  do { \
1007 		duk_tval *duk__tv; \
1008 		duk__tv = (tv); \
1009 		duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16 | (((duk_uint32_t) ((i) >> 32)) & 0x0000ffffUL); \
1010 		duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
1011 	} while (0)
1012 #define DUK__TVAL_SET_U32(tv,i)  do { \
1013 		duk_tval *duk__tv; \
1014 		duk__tv = (tv); \
1015 		duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16; \
1016 		duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
1017 	} while (0)
1018 #else
1019 #define DUK__TVAL_SET_I48(tv,i)  do { \
1020 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (((duk_uint64_t) (i)) & DUK_U64_CONSTANT(0x0000ffffffffffff)); \
1021 	} while (0)
1022 #define DUK__TVAL_SET_U32(tv,i)  do { \
1023 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (duk_uint64_t) (i); \
1024 	} while (0)
1025 #endif
1026 
1027 /* This needs to go through a cast because sign extension is needed. */
1028 #define DUK__TVAL_SET_I32(tv,i)  do { \
1029 		duk_int64_t duk__tmp = (duk_int64_t) (i); \
1030 		DUK_TVAL_SET_I48((tv), duk__tmp); \
1031 	} while (0)
1032 
1033 /* XXX: Clumsy sign extend and masking of 16 topmost bits. */
1034 #if defined(DUK_USE_DOUBLE_ME)
1035 #define DUK__TVAL_GET_FASTINT(tv)      (((duk_int64_t) ((((duk_uint64_t) (tv)->ui[DUK_DBL_IDX_UI0]) << 32) | ((duk_uint64_t) (tv)->ui[DUK_DBL_IDX_UI1]))) << 16 >> 16)
1036 #else
1037 #define DUK__TVAL_GET_FASTINT(tv)      ((((duk_int64_t) (tv)->ull[DUK_DBL_IDX_ULL0]) << 16) >> 16)
1038 #endif
1039 #define DUK__TVAL_GET_FASTINT_U32(tv)  ((tv)->ui[DUK_DBL_IDX_UI1])
1040 #define DUK__TVAL_GET_FASTINT_I32(tv)  ((duk_int32_t) (tv)->ui[DUK_DBL_IDX_UI1])
1041 #endif  /* DUK_USE_FASTINT */
1042 
1043 #define DUK_TVAL_SET_UNDEFINED(tv)  do { \
1044 		(tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNDEFINED; \
1045 	} while (0)
1046 #define DUK_TVAL_SET_UNUSED(tv)  do { \
1047 		(tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNUSED; \
1048 	} while (0)
1049 #define DUK_TVAL_SET_NULL(tv)  do { \
1050 		(tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_NULL; \
1051 	} while (0)
1052 
1053 #define DUK_TVAL_SET_BOOLEAN(tv,val)         DUK_DBLUNION_SET_HIGH32((tv), (((duk_uint32_t) DUK_TAG_BOOLEAN) << 16) | ((duk_uint32_t) (val)))
1054 
1055 #define DUK_TVAL_SET_NAN(tv)                 DUK_DBLUNION_SET_NAN_FULL((tv))
1056 
1057 /* Assumes that caller has normalized NaNs, otherwise trouble ahead. */
1058 #if defined(DUK_USE_FASTINT)
1059 #define DUK_TVAL_SET_DOUBLE(tv,d)  do { \
1060 		duk_double_t duk__dblval; \
1061 		duk__dblval = (d); \
1062 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
1063 		DUK_DBLUNION_SET_DOUBLE((tv), duk__dblval); \
1064 	} while (0)
1065 #define DUK_TVAL_SET_I48(tv,i)               DUK__TVAL_SET_I48((tv), (i))
1066 #define DUK_TVAL_SET_I32(tv,i)               DUK__TVAL_SET_I32((tv), (i))
1067 #define DUK_TVAL_SET_U32(tv,i)               DUK__TVAL_SET_U32((tv), (i))
1068 #define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d)  duk_tval_set_number_chkfast_fast((tv), (d))
1069 #define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d)  duk_tval_set_number_chkfast_slow((tv), (d))
1070 #define DUK_TVAL_SET_NUMBER(tv,d)            DUK_TVAL_SET_DOUBLE((tv), (d))
1071 #define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { \
1072 		duk_tval *duk__tv; \
1073 		duk_double_t duk__d; \
1074 		duk__tv = (tv); \
1075 		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
1076 			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
1077 			DUK_TVAL_SET_NUMBER_CHKFAST_FAST(duk__tv, duk__d); \
1078 		} \
1079 	} while (0)
1080 #define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { \
1081 		duk_tval *duk__tv; \
1082 		duk_double_t duk__d; \
1083 		duk__tv = (tv); \
1084 		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
1085 			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
1086 			DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(duk__tv, duk__d); \
1087 		} \
1088 	} while (0)
1089 #else  /* DUK_USE_FASTINT */
1090 #define DUK_TVAL_SET_DOUBLE(tv,d)  do { \
1091 		duk_double_t duk__dblval; \
1092 		duk__dblval = (d); \
1093 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
1094 		DUK_DBLUNION_SET_DOUBLE((tv), duk__dblval); \
1095 	} while (0)
1096 #define DUK_TVAL_SET_I48(tv,i)               DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))  /* XXX: fast int-to-double */
1097 #define DUK_TVAL_SET_I32(tv,i)               DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))
1098 #define DUK_TVAL_SET_U32(tv,i)               DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))
1099 #define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d)    DUK_TVAL_SET_DOUBLE((tv), (d))
1100 #define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d)    DUK_TVAL_SET_DOUBLE((tv), (d))
1101 #define DUK_TVAL_SET_NUMBER(tv,d)            DUK_TVAL_SET_DOUBLE((tv), (d))
1102 #define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { } while (0)
1103 #define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { } while (0)
1104 #endif  /* DUK_USE_FASTINT */
1105 
1106 #define DUK_TVAL_SET_FASTINT(tv,i)           DUK_TVAL_SET_I48((tv), (i))  /* alias */
1107 
1108 #define DUK_TVAL_SET_LIGHTFUNC(tv,fp,flags)  DUK__TVAL_SET_LIGHTFUNC((tv), (fp), (flags))
1109 #define DUK_TVAL_SET_STRING(tv,h)            DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_STRING)
1110 #define DUK_TVAL_SET_OBJECT(tv,h)            DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_OBJECT)
1111 #define DUK_TVAL_SET_BUFFER(tv,h)            DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_BUFFER)
1112 #define DUK_TVAL_SET_POINTER(tv,p)           DUK__TVAL_SET_TAGGEDPOINTER((tv), (p), DUK_TAG_POINTER)
1113 
1114 #define DUK_TVAL_SET_TVAL(tv,x)              do { *(tv) = *(x); } while (0)
1115 
1116 /* getters */
1117 #define DUK_TVAL_GET_BOOLEAN(tv)             ((duk_small_uint_t) (tv)->us[DUK_DBL_IDX_US1])
1118 #if defined(DUK_USE_FASTINT)
1119 #define DUK_TVAL_GET_DOUBLE(tv)              ((tv)->d)
1120 #define DUK_TVAL_GET_FASTINT(tv)             DUK__TVAL_GET_FASTINT((tv))
1121 #define DUK_TVAL_GET_FASTINT_U32(tv)         DUK__TVAL_GET_FASTINT_U32((tv))
1122 #define DUK_TVAL_GET_FASTINT_I32(tv)         DUK__TVAL_GET_FASTINT_I32((tv))
1123 #define DUK_TVAL_GET_NUMBER(tv)              duk_tval_get_number_packed((tv))
1124 #else
1125 #define DUK_TVAL_GET_NUMBER(tv)              ((tv)->d)
1126 #define DUK_TVAL_GET_DOUBLE(tv)              ((tv)->d)
1127 #endif
1128 #define DUK_TVAL_GET_LIGHTFUNC(tv,out_fp,out_flags)  do { \
1129 		(out_flags) = (tv)->ui[DUK_DBL_IDX_UI0] & 0xffffUL; \
1130 		(out_fp) = (duk_c_function) (tv)->ui[DUK_DBL_IDX_UI1]; \
1131 	} while (0)
1132 #define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv)   ((duk_c_function) ((tv)->ui[DUK_DBL_IDX_UI1]))
1133 #define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv)     (((duk_small_uint_t) (tv)->ui[DUK_DBL_IDX_UI0]) & 0xffffUL)
1134 #define DUK_TVAL_GET_STRING(tv)              ((duk_hstring *) (tv)->vp[DUK_DBL_IDX_VP1])
1135 #define DUK_TVAL_GET_OBJECT(tv)              ((duk_hobject *) (tv)->vp[DUK_DBL_IDX_VP1])
1136 #define DUK_TVAL_GET_BUFFER(tv)              ((duk_hbuffer *) (tv)->vp[DUK_DBL_IDX_VP1])
1137 #define DUK_TVAL_GET_POINTER(tv)             ((void *) (tv)->vp[DUK_DBL_IDX_VP1])
1138 #define DUK_TVAL_GET_HEAPHDR(tv)             ((duk_heaphdr *) (tv)->vp[DUK_DBL_IDX_VP1])
1139 
1140 /* decoding */
1141 #define DUK_TVAL_GET_TAG(tv)                 ((duk_small_uint_t) (tv)->us[DUK_DBL_IDX_US0])
1142 
1143 #define DUK_TVAL_IS_UNDEFINED(tv)            (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_UNDEFINED)
1144 #define DUK_TVAL_IS_UNUSED(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_UNUSED)
1145 #define DUK_TVAL_IS_NULL(tv)                 (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_NULL)
1146 #define DUK_TVAL_IS_BOOLEAN(tv)              (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_BOOLEAN)
1147 #define DUK_TVAL_IS_BOOLEAN_TRUE(tv)         ((tv)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_TRUE)
1148 #define DUK_TVAL_IS_BOOLEAN_FALSE(tv)        ((tv)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_FALSE)
1149 #define DUK_TVAL_IS_LIGHTFUNC(tv)            (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_LIGHTFUNC)
1150 #define DUK_TVAL_IS_STRING(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_STRING)
1151 #define DUK_TVAL_IS_OBJECT(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_OBJECT)
1152 #define DUK_TVAL_IS_BUFFER(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_BUFFER)
1153 #define DUK_TVAL_IS_POINTER(tv)              (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_POINTER)
1154 #if defined(DUK_USE_FASTINT)
1155 /* 0xfff0 is -Infinity */
1156 #define DUK_TVAL_IS_DOUBLE(tv)               (DUK_TVAL_GET_TAG((tv)) <= 0xfff0UL)
1157 #define DUK_TVAL_IS_FASTINT(tv)              (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_FASTINT)
1158 #define DUK_TVAL_IS_NUMBER(tv)               (DUK_TVAL_GET_TAG((tv)) <= 0xfff1UL)
1159 #else
1160 #define DUK_TVAL_IS_NUMBER(tv)               (DUK_TVAL_GET_TAG((tv)) <= 0xfff0UL)
1161 #define DUK_TVAL_IS_DOUBLE(tv)               DUK_TVAL_IS_NUMBER((tv))
1162 #endif
1163 
1164 /* This is performance critical because it appears in every DECREF. */
1165 #define DUK_TVAL_IS_HEAP_ALLOCATED(tv)       (DUK_TVAL_GET_TAG((tv)) >= DUK_TAG_STRING)
1166 
1167 #if defined(DUK_USE_FASTINT)
1168 DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_packed(duk_tval *tv);
1169 #endif
1170 
1171 #else  /* DUK_USE_PACKED_TVAL */
1172 /* ======================================================================== */
1173 
1174 /*
1175  *  Portable 12-byte representation
1176  */
1177 
1178 /* Note: not initializing all bytes is normally not an issue: Duktape won't
1179  * read or use the uninitialized bytes so valgrind won't issue warnings.
1180  * In some special cases a harmless valgrind warning may be issued though.
1181  * For example, the DumpHeap debugger command writes out a compiled function's
1182  * 'data' area as is, including any uninitialized bytes, which causes a
1183  * valgrind warning.
1184  */
1185 
1186 typedef struct duk_tval_struct duk_tval;
1187 
1188 struct duk_tval_struct {
1189 	duk_small_uint_t t;
1190 	duk_small_uint_t v_extra;
1191 	union {
1192 		duk_double_t d;
1193 		duk_small_int_t i;
1194 #if defined(DUK_USE_FASTINT)
1195 		duk_int64_t fi;  /* if present, forces 16-byte duk_tval */
1196 #endif
1197 		void *voidptr;
1198 		duk_hstring *hstring;
1199 		duk_hobject *hobject;
1200 		duk_hcompfunc *hcompfunc;
1201 		duk_hnatfunc *hnatfunc;
1202 		duk_hthread *hthread;
1203 		duk_hbuffer *hbuffer;
1204 		duk_heaphdr *heaphdr;
1205 		duk_c_function lightfunc;
1206 	} v;
1207 };
1208 
1209 typedef struct {
1210 	duk_small_uint_t t;
1211 	duk_small_uint_t v_extra;
1212 	/* The rest of the fields don't matter except for debug dumps and such
1213 	 * for which a partial initializer may trigger out-ot-bounds memory
1214 	 * reads.  Include a double field which is usually as large or larger
1215 	 * than pointers (not always however).
1216 	 */
1217 	duk_double_t d;
1218 } duk_tval_unused;
1219 
1220 #define DUK_TVAL_UNUSED_INITIALIZER() \
1221 	{ DUK_TAG_UNUSED, 0, 0.0 }
1222 
1223 #define DUK_TAG_MIN                   0
1224 #define DUK_TAG_NUMBER                0  /* DUK_TAG_NUMBER only defined for non-packed duk_tval */
1225 #if defined(DUK_USE_FASTINT)
1226 #define DUK_TAG_FASTINT               1
1227 #endif
1228 #define DUK_TAG_UNDEFINED             2
1229 #define DUK_TAG_NULL                  3
1230 #define DUK_TAG_BOOLEAN               4
1231 #define DUK_TAG_POINTER               5
1232 #define DUK_TAG_LIGHTFUNC             6
1233 #define DUK_TAG_UNUSED                7  /* marker; not actual tagged type */
1234 #define DUK_TAG_STRING                8  /* first heap allocated, match bit boundary */
1235 #define DUK_TAG_OBJECT                9
1236 #define DUK_TAG_BUFFER                10
1237 #define DUK_TAG_MAX                   10
1238 
1239 #define DUK_TVAL_IS_VALID_TAG(tv) \
1240 	(DUK_TVAL_GET_TAG((tv)) - DUK_TAG_MIN <= DUK_TAG_MAX - DUK_TAG_MIN)
1241 
1242 /* DUK_TAG_NUMBER is intentionally first, as it is the default clause in code
1243  * to support the 8-byte representation.  Further, it is a non-heap-allocated
1244  * type so it should come before DUK_TAG_STRING.  Finally, it should not break
1245  * the tag value ranges covered by case-clauses in a switch-case.
1246  */
1247 
1248 /* setters */
1249 #define DUK_TVAL_SET_UNDEFINED(tv)  do { \
1250 		duk_tval *duk__tv; \
1251 		duk__tv = (tv); \
1252 		duk__tv->t = DUK_TAG_UNDEFINED; \
1253 	} while (0)
1254 
1255 #define DUK_TVAL_SET_UNUSED(tv)  do { \
1256 		duk_tval *duk__tv; \
1257 		duk__tv = (tv); \
1258 		duk__tv->t = DUK_TAG_UNUSED; \
1259 	} while (0)
1260 
1261 #define DUK_TVAL_SET_NULL(tv)  do { \
1262 		duk_tval *duk__tv; \
1263 		duk__tv = (tv); \
1264 		duk__tv->t = DUK_TAG_NULL; \
1265 	} while (0)
1266 
1267 #define DUK_TVAL_SET_BOOLEAN(tv,val)  do { \
1268 		duk_tval *duk__tv; \
1269 		duk__tv = (tv); \
1270 		duk__tv->t = DUK_TAG_BOOLEAN; \
1271 		duk__tv->v.i = (duk_small_int_t) (val); \
1272 	} while (0)
1273 
1274 #if defined(DUK_USE_FASTINT)
1275 #define DUK_TVAL_SET_DOUBLE(tv,val)  do { \
1276 		duk_tval *duk__tv; \
1277 		duk_double_t duk__dblval; \
1278 		duk__dblval = (val); \
1279 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); /* nop for unpacked duk_tval */ \
1280 		duk__tv = (tv); \
1281 		duk__tv->t = DUK_TAG_NUMBER; \
1282 		duk__tv->v.d = duk__dblval; \
1283 	} while (0)
1284 #define DUK_TVAL_SET_I48(tv,val)  do { \
1285 		duk_tval *duk__tv; \
1286 		duk__tv = (tv); \
1287 		duk__tv->t = DUK_TAG_FASTINT; \
1288 		duk__tv->v.fi = (val); \
1289 	} while (0)
1290 #define DUK_TVAL_SET_U32(tv,val)  do { \
1291 		duk_tval *duk__tv; \
1292 		duk__tv = (tv); \
1293 		duk__tv->t = DUK_TAG_FASTINT; \
1294 		duk__tv->v.fi = (duk_int64_t) (val); \
1295 	} while (0)
1296 #define DUK_TVAL_SET_I32(tv,val)  do { \
1297 		duk_tval *duk__tv; \
1298 		duk__tv = (tv); \
1299 		duk__tv->t = DUK_TAG_FASTINT; \
1300 		duk__tv->v.fi = (duk_int64_t) (val); \
1301 	} while (0)
1302 #define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) \
1303 	duk_tval_set_number_chkfast_fast((tv), (d))
1304 #define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) \
1305 	duk_tval_set_number_chkfast_slow((tv), (d))
1306 #define DUK_TVAL_SET_NUMBER(tv,val) \
1307 	DUK_TVAL_SET_DOUBLE((tv), (val))
1308 #define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { \
1309 		duk_tval *duk__tv; \
1310 		duk_double_t duk__d; \
1311 		duk__tv = (tv); \
1312 		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
1313 			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
1314 			DUK_TVAL_SET_NUMBER_CHKFAST_FAST(duk__tv, duk__d); \
1315 		} \
1316 	} while (0)
1317 #define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { \
1318 		duk_tval *duk__tv; \
1319 		duk_double_t duk__d; \
1320 		duk__tv = (tv); \
1321 		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
1322 			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
1323 			DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(duk__tv, duk__d); \
1324 		} \
1325 	} while (0)
1326 #else  /* DUK_USE_FASTINT */
1327 #define DUK_TVAL_SET_DOUBLE(tv,d) \
1328 	DUK_TVAL_SET_NUMBER((tv), (d))
1329 #define DUK_TVAL_SET_I48(tv,val) \
1330 	DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))  /* XXX: fast int-to-double */
1331 #define DUK_TVAL_SET_U32(tv,val) \
1332 	DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
1333 #define DUK_TVAL_SET_I32(tv,val) \
1334 	DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
1335 #define DUK_TVAL_SET_NUMBER(tv,val)  do { \
1336 		duk_tval *duk__tv; \
1337 		duk_double_t duk__dblval; \
1338 		duk__dblval = (val); \
1339 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); /* nop for unpacked duk_tval */ \
1340 		duk__tv = (tv); \
1341 		duk__tv->t = DUK_TAG_NUMBER; \
1342 		duk__tv->v.d = duk__dblval; \
1343 	} while (0)
1344 #define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) \
1345 	DUK_TVAL_SET_NUMBER((tv), (d))
1346 #define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) \
1347 	DUK_TVAL_SET_NUMBER((tv), (d))
1348 #define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { } while (0)
1349 #define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { } while (0)
1350 #endif  /* DUK_USE_FASTINT */
1351 
1352 #define DUK_TVAL_SET_FASTINT(tv,i) \
1353 	DUK_TVAL_SET_I48((tv), (i))  /* alias */
1354 
1355 #define DUK_TVAL_SET_POINTER(tv,hptr)  do { \
1356 		duk_tval *duk__tv; \
1357 		duk__tv = (tv); \
1358 		duk__tv->t = DUK_TAG_POINTER; \
1359 		duk__tv->v.voidptr = (hptr); \
1360 	} while (0)
1361 
1362 #define DUK_TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \
1363 		duk_tval *duk__tv; \
1364 		duk__tv = (tv); \
1365 		duk__tv->t = DUK_TAG_LIGHTFUNC; \
1366 		duk__tv->v_extra = (flags); \
1367 		duk__tv->v.lightfunc = (duk_c_function) (fp); \
1368 	} while (0)
1369 
1370 #define DUK_TVAL_SET_STRING(tv,hptr)  do { \
1371 		duk_tval *duk__tv; \
1372 		duk__tv = (tv); \
1373 		duk__tv->t = DUK_TAG_STRING; \
1374 		duk__tv->v.hstring = (hptr); \
1375 	} while (0)
1376 
1377 #define DUK_TVAL_SET_OBJECT(tv,hptr)  do { \
1378 		duk_tval *duk__tv; \
1379 		duk__tv = (tv); \
1380 		duk__tv->t = DUK_TAG_OBJECT; \
1381 		duk__tv->v.hobject = (hptr); \
1382 	} while (0)
1383 
1384 #define DUK_TVAL_SET_BUFFER(tv,hptr)  do { \
1385 		duk_tval *duk__tv; \
1386 		duk__tv = (tv); \
1387 		duk__tv->t = DUK_TAG_BUFFER; \
1388 		duk__tv->v.hbuffer = (hptr); \
1389 	} while (0)
1390 
1391 #define DUK_TVAL_SET_NAN(tv)  do { \
1392 		/* in non-packed representation we don't care about which NaN is used */ \
1393 		duk_tval *duk__tv; \
1394 		duk__tv = (tv); \
1395 		duk__tv->t = DUK_TAG_NUMBER; \
1396 		duk__tv->v.d = DUK_DOUBLE_NAN; \
1397 	} while (0)
1398 
1399 #define DUK_TVAL_SET_TVAL(tv,x)            do { *(tv) = *(x); } while (0)
1400 
1401 /* getters */
1402 #define DUK_TVAL_GET_BOOLEAN(tv)           ((duk_small_uint_t) (tv)->v.i)
1403 #if defined(DUK_USE_FASTINT)
1404 #define DUK_TVAL_GET_DOUBLE(tv)            ((tv)->v.d)
1405 #define DUK_TVAL_GET_FASTINT(tv)           ((tv)->v.fi)
1406 #define DUK_TVAL_GET_FASTINT_U32(tv)       ((duk_uint32_t) ((tv)->v.fi))
1407 #define DUK_TVAL_GET_FASTINT_I32(tv)       ((duk_int32_t) ((tv)->v.fi))
1408 #if 0
1409 #define DUK_TVAL_GET_NUMBER(tv)            (DUK_TVAL_IS_FASTINT((tv)) ? \
1410                                                (duk_double_t) DUK_TVAL_GET_FASTINT((tv)) : \
1411                                                DUK_TVAL_GET_DOUBLE((tv)))
1412 #define DUK_TVAL_GET_NUMBER(tv)            duk_tval_get_number_unpacked((tv))
1413 #else
1414 /* This seems reasonable overall. */
1415 #define DUK_TVAL_GET_NUMBER(tv)            (DUK_TVAL_IS_FASTINT((tv)) ? \
1416                                                duk_tval_get_number_unpacked_fastint((tv)) : \
1417                                                DUK_TVAL_GET_DOUBLE((tv)))
1418 #endif
1419 #else
1420 #define DUK_TVAL_GET_NUMBER(tv)            ((tv)->v.d)
1421 #define DUK_TVAL_GET_DOUBLE(tv)            ((tv)->v.d)
1422 #endif  /* DUK_USE_FASTINT */
1423 #define DUK_TVAL_GET_POINTER(tv)           ((tv)->v.voidptr)
1424 #define DUK_TVAL_GET_LIGHTFUNC(tv,out_fp,out_flags)  do { \
1425 		(out_flags) = (duk_uint32_t) (tv)->v_extra; \
1426 		(out_fp) = (tv)->v.lightfunc; \
1427 	} while (0)
1428 #define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv) ((tv)->v.lightfunc)
1429 #define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv)   ((duk_small_uint_t) ((tv)->v_extra))
1430 #define DUK_TVAL_GET_STRING(tv)            ((tv)->v.hstring)
1431 #define DUK_TVAL_GET_OBJECT(tv)            ((tv)->v.hobject)
1432 #define DUK_TVAL_GET_BUFFER(tv)            ((tv)->v.hbuffer)
1433 #define DUK_TVAL_GET_HEAPHDR(tv)           ((tv)->v.heaphdr)
1434 
1435 /* decoding */
1436 #define DUK_TVAL_GET_TAG(tv)               ((tv)->t)
1437 #define DUK_TVAL_IS_UNDEFINED(tv)          ((tv)->t == DUK_TAG_UNDEFINED)
1438 #define DUK_TVAL_IS_UNUSED(tv)             ((tv)->t == DUK_TAG_UNUSED)
1439 #define DUK_TVAL_IS_NULL(tv)               ((tv)->t == DUK_TAG_NULL)
1440 #define DUK_TVAL_IS_BOOLEAN(tv)            ((tv)->t == DUK_TAG_BOOLEAN)
1441 #define DUK_TVAL_IS_BOOLEAN_TRUE(tv)       (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i != 0))
1442 #define DUK_TVAL_IS_BOOLEAN_FALSE(tv)      (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i == 0))
1443 #if defined(DUK_USE_FASTINT)
1444 #define DUK_TVAL_IS_DOUBLE(tv)             ((tv)->t == DUK_TAG_NUMBER)
1445 #define DUK_TVAL_IS_FASTINT(tv)            ((tv)->t == DUK_TAG_FASTINT)
1446 #define DUK_TVAL_IS_NUMBER(tv)             ((tv)->t == DUK_TAG_NUMBER || \
1447                                             (tv)->t == DUK_TAG_FASTINT)
1448 #else
1449 #define DUK_TVAL_IS_NUMBER(tv)             ((tv)->t == DUK_TAG_NUMBER)
1450 #define DUK_TVAL_IS_DOUBLE(tv)             DUK_TVAL_IS_NUMBER((tv))
1451 #endif  /* DUK_USE_FASTINT */
1452 #define DUK_TVAL_IS_POINTER(tv)            ((tv)->t == DUK_TAG_POINTER)
1453 #define DUK_TVAL_IS_LIGHTFUNC(tv)          ((tv)->t == DUK_TAG_LIGHTFUNC)
1454 #define DUK_TVAL_IS_STRING(tv)             ((tv)->t == DUK_TAG_STRING)
1455 #define DUK_TVAL_IS_OBJECT(tv)             ((tv)->t == DUK_TAG_OBJECT)
1456 #define DUK_TVAL_IS_BUFFER(tv)             ((tv)->t == DUK_TAG_BUFFER)
1457 
1458 /* This is performance critical because it's needed for every DECREF.
1459  * Take advantage of the fact that the first heap allocated tag is 8,
1460  * so that bit 3 is set for all heap allocated tags (and never set for
1461  * non-heap-allocated tags).
1462  */
1463 #if 0
1464 #define DUK_TVAL_IS_HEAP_ALLOCATED(tv)     ((tv)->t >= DUK_TAG_STRING)
1465 #endif
1466 #define DUK_TVAL_IS_HEAP_ALLOCATED(tv)     ((tv)->t & 0x08)
1467 
1468 #if defined(DUK_USE_FASTINT)
1469 #if 0
1470 DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked(duk_tval *tv);
1471 #endif
1472 DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv);
1473 #endif
1474 
1475 #endif  /* DUK_USE_PACKED_TVAL */
1476 
1477 /*
1478  *  Convenience (independent of representation)
1479  */
1480 
1481 #define DUK_TVAL_SET_BOOLEAN_TRUE(tv)        DUK_TVAL_SET_BOOLEAN((tv), 1)
1482 #define DUK_TVAL_SET_BOOLEAN_FALSE(tv)       DUK_TVAL_SET_BOOLEAN((tv), 0)
1483 
1484 #define DUK_TVAL_STRING_IS_SYMBOL(tv) \
1485 	DUK_HSTRING_HAS_SYMBOL(DUK_TVAL_GET_STRING((tv)))
1486 
1487 /* Lightfunc flags packing and unpacking. */
1488 /* Sign extend: 0x0000##00 -> 0x##000000 -> sign extend to 0xssssss##.
1489  * Avoid signed shifts due to portability limitations.
1490  */
1491 #define DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags) \
1492 	((duk_int32_t) (duk_int8_t) (((duk_uint16_t) (lf_flags)) >> 8))
1493 #define DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags) \
1494 	(((lf_flags) >> 4) & 0x0fU)
1495 #define DUK_LFUNC_FLAGS_GET_NARGS(lf_flags) \
1496 	((lf_flags) & 0x0fU)
1497 #define DUK_LFUNC_FLAGS_PACK(magic,length,nargs) \
1498 	((((duk_small_uint_t) (magic)) & 0xffU) << 8) | ((length) << 4) | (nargs)
1499 
1500 #define DUK_LFUNC_NARGS_VARARGS             0x0f   /* varargs marker */
1501 #define DUK_LFUNC_NARGS_MIN                 0x00
1502 #define DUK_LFUNC_NARGS_MAX                 0x0e   /* max, excl. varargs marker */
1503 #define DUK_LFUNC_LENGTH_MIN                0x00
1504 #define DUK_LFUNC_LENGTH_MAX                0x0f
1505 #define DUK_LFUNC_MAGIC_MIN                 (-0x80)
1506 #define DUK_LFUNC_MAGIC_MAX                 0x7f
1507 
1508 /* fastint constants etc */
1509 #if defined(DUK_USE_FASTINT)
1510 #define DUK_FASTINT_MIN           (DUK_I64_CONSTANT(-0x800000000000))
1511 #define DUK_FASTINT_MAX           (DUK_I64_CONSTANT(0x7fffffffffff))
1512 #define DUK_FASTINT_BITS          48
1513 
1514 DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_fast(duk_tval *tv, duk_double_t x);
1515 DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_slow(duk_tval *tv, duk_double_t x);
1516 #endif
1517 
1518 #if defined(DUK_USE_ASSERTIONS)
1519 DUK_INTERNAL_DECL void duk_tval_assert_valid(duk_tval *tv);
1520 #define DUK_TVAL_ASSERT_VALID(tv)  do { duk_tval_assert_valid((tv)); } while (0)
1521 #else
1522 #define DUK_TVAL_ASSERT_VALID(tv)  do {} while (0)
1523 #endif
1524 
1525 #endif  /* DUK_TVAL_H_INCLUDED */
1526 /* #include duk_builtins.h */
1527 /*
1528  *  Automatically generated by genbuiltins.py, do not edit!
1529  */
1530 
1531 #if !defined(DUK_BUILTINS_H_INCLUDED)
1532 #define DUK_BUILTINS_H_INCLUDED
1533 
1534 #if defined(DUK_USE_ROM_STRINGS)
1535 #error ROM support not enabled, rerun configure.py with --rom-support
1536 #else  /* DUK_USE_ROM_STRINGS */
1537 #define DUK_STRIDX_UC_UNDEFINED                                       0                              /* 'Undefined' */
1538 #define DUK_HEAP_STRING_UC_UNDEFINED(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_UNDEFINED)
1539 #define DUK_HTHREAD_STRING_UC_UNDEFINED(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_UNDEFINED)
1540 #define DUK_STRIDX_UC_NULL                                            1                              /* 'Null' */
1541 #define DUK_HEAP_STRING_UC_NULL(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NULL)
1542 #define DUK_HTHREAD_STRING_UC_NULL(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NULL)
1543 #define DUK_STRIDX_UC_SYMBOL                                          2                              /* 'Symbol' */
1544 #define DUK_HEAP_STRING_UC_SYMBOL(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_SYMBOL)
1545 #define DUK_HTHREAD_STRING_UC_SYMBOL(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_SYMBOL)
1546 #define DUK_STRIDX_UC_ARGUMENTS                                       3                              /* 'Arguments' */
1547 #define DUK_HEAP_STRING_UC_ARGUMENTS(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ARGUMENTS)
1548 #define DUK_HTHREAD_STRING_UC_ARGUMENTS(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ARGUMENTS)
1549 #define DUK_STRIDX_UC_OBJECT                                          4                              /* 'Object' */
1550 #define DUK_HEAP_STRING_UC_OBJECT(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_OBJECT)
1551 #define DUK_HTHREAD_STRING_UC_OBJECT(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_OBJECT)
1552 #define DUK_STRIDX_UC_FUNCTION                                        5                              /* 'Function' */
1553 #define DUK_HEAP_STRING_UC_FUNCTION(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_FUNCTION)
1554 #define DUK_HTHREAD_STRING_UC_FUNCTION(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_FUNCTION)
1555 #define DUK_STRIDX_UC_ARRAY                                           6                              /* 'Array' */
1556 #define DUK_HEAP_STRING_UC_ARRAY(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ARRAY)
1557 #define DUK_HTHREAD_STRING_UC_ARRAY(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ARRAY)
1558 #define DUK_STRIDX_UC_STRING                                          7                              /* 'String' */
1559 #define DUK_HEAP_STRING_UC_STRING(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_STRING)
1560 #define DUK_HTHREAD_STRING_UC_STRING(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_STRING)
1561 #define DUK_STRIDX_UC_BOOLEAN                                         8                              /* 'Boolean' */
1562 #define DUK_HEAP_STRING_UC_BOOLEAN(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BOOLEAN)
1563 #define DUK_HTHREAD_STRING_UC_BOOLEAN(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BOOLEAN)
1564 #define DUK_STRIDX_UC_NUMBER                                          9                              /* 'Number' */
1565 #define DUK_HEAP_STRING_UC_NUMBER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NUMBER)
1566 #define DUK_HTHREAD_STRING_UC_NUMBER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NUMBER)
1567 #define DUK_STRIDX_UC_DATE                                            10                             /* 'Date' */
1568 #define DUK_HEAP_STRING_UC_DATE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_DATE)
1569 #define DUK_HTHREAD_STRING_UC_DATE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_DATE)
1570 #define DUK_STRIDX_REG_EXP                                            11                             /* 'RegExp' */
1571 #define DUK_HEAP_STRING_REG_EXP(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_REG_EXP)
1572 #define DUK_HTHREAD_STRING_REG_EXP(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_REG_EXP)
1573 #define DUK_STRIDX_UC_ERROR                                           12                             /* 'Error' */
1574 #define DUK_HEAP_STRING_UC_ERROR(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ERROR)
1575 #define DUK_HTHREAD_STRING_UC_ERROR(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ERROR)
1576 #define DUK_STRIDX_MATH                                               13                             /* 'Math' */
1577 #define DUK_HEAP_STRING_MATH(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MATH)
1578 #define DUK_HTHREAD_STRING_MATH(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MATH)
1579 #define DUK_STRIDX_JSON                                               14                             /* 'JSON' */
1580 #define DUK_HEAP_STRING_JSON(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON)
1581 #define DUK_HTHREAD_STRING_JSON(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON)
1582 #define DUK_STRIDX_EMPTY_STRING                                       15                             /* '' */
1583 #define DUK_HEAP_STRING_EMPTY_STRING(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EMPTY_STRING)
1584 #define DUK_HTHREAD_STRING_EMPTY_STRING(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EMPTY_STRING)
1585 #define DUK_STRIDX_ARRAY_BUFFER                                       16                             /* 'ArrayBuffer' */
1586 #define DUK_HEAP_STRING_ARRAY_BUFFER(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY_BUFFER)
1587 #define DUK_HTHREAD_STRING_ARRAY_BUFFER(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY_BUFFER)
1588 #define DUK_STRIDX_DATA_VIEW                                          17                             /* 'DataView' */
1589 #define DUK_HEAP_STRING_DATA_VIEW(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA_VIEW)
1590 #define DUK_HTHREAD_STRING_DATA_VIEW(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA_VIEW)
1591 #define DUK_STRIDX_INT8_ARRAY                                         18                             /* 'Int8Array' */
1592 #define DUK_HEAP_STRING_INT8_ARRAY(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT8_ARRAY)
1593 #define DUK_HTHREAD_STRING_INT8_ARRAY(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT8_ARRAY)
1594 #define DUK_STRIDX_UINT8_ARRAY                                        19                             /* 'Uint8Array' */
1595 #define DUK_HEAP_STRING_UINT8_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_ARRAY)
1596 #define DUK_HTHREAD_STRING_UINT8_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_ARRAY)
1597 #define DUK_STRIDX_UINT8_CLAMPED_ARRAY                                20                             /* 'Uint8ClampedArray' */
1598 #define DUK_HEAP_STRING_UINT8_CLAMPED_ARRAY(heap)                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
1599 #define DUK_HTHREAD_STRING_UINT8_CLAMPED_ARRAY(thr)                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
1600 #define DUK_STRIDX_INT16_ARRAY                                        21                             /* 'Int16Array' */
1601 #define DUK_HEAP_STRING_INT16_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT16_ARRAY)
1602 #define DUK_HTHREAD_STRING_INT16_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT16_ARRAY)
1603 #define DUK_STRIDX_UINT16_ARRAY                                       22                             /* 'Uint16Array' */
1604 #define DUK_HEAP_STRING_UINT16_ARRAY(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT16_ARRAY)
1605 #define DUK_HTHREAD_STRING_UINT16_ARRAY(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT16_ARRAY)
1606 #define DUK_STRIDX_INT32_ARRAY                                        23                             /* 'Int32Array' */
1607 #define DUK_HEAP_STRING_INT32_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT32_ARRAY)
1608 #define DUK_HTHREAD_STRING_INT32_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT32_ARRAY)
1609 #define DUK_STRIDX_UINT32_ARRAY                                       24                             /* 'Uint32Array' */
1610 #define DUK_HEAP_STRING_UINT32_ARRAY(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT32_ARRAY)
1611 #define DUK_HTHREAD_STRING_UINT32_ARRAY(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT32_ARRAY)
1612 #define DUK_STRIDX_FLOAT32_ARRAY                                      25                             /* 'Float32Array' */
1613 #define DUK_HEAP_STRING_FLOAT32_ARRAY(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT32_ARRAY)
1614 #define DUK_HTHREAD_STRING_FLOAT32_ARRAY(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT32_ARRAY)
1615 #define DUK_STRIDX_FLOAT64_ARRAY                                      26                             /* 'Float64Array' */
1616 #define DUK_HEAP_STRING_FLOAT64_ARRAY(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT64_ARRAY)
1617 #define DUK_HTHREAD_STRING_FLOAT64_ARRAY(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT64_ARRAY)
1618 #define DUK_STRIDX_GLOBAL                                             27                             /* 'global' */
1619 #define DUK_HEAP_STRING_GLOBAL(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GLOBAL)
1620 #define DUK_HTHREAD_STRING_GLOBAL(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GLOBAL)
1621 #define DUK_STRIDX_OBJ_ENV                                            28                             /* 'ObjEnv' */
1622 #define DUK_HEAP_STRING_OBJ_ENV(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OBJ_ENV)
1623 #define DUK_HTHREAD_STRING_OBJ_ENV(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OBJ_ENV)
1624 #define DUK_STRIDX_DEC_ENV                                            29                             /* 'DecEnv' */
1625 #define DUK_HEAP_STRING_DEC_ENV(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEC_ENV)
1626 #define DUK_HTHREAD_STRING_DEC_ENV(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEC_ENV)
1627 #define DUK_STRIDX_UC_BUFFER                                          30                             /* 'Buffer' */
1628 #define DUK_HEAP_STRING_UC_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BUFFER)
1629 #define DUK_HTHREAD_STRING_UC_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BUFFER)
1630 #define DUK_STRIDX_UC_POINTER                                         31                             /* 'Pointer' */
1631 #define DUK_HEAP_STRING_UC_POINTER(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_POINTER)
1632 #define DUK_HTHREAD_STRING_UC_POINTER(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_POINTER)
1633 #define DUK_STRIDX_UC_THREAD                                          32                             /* 'Thread' */
1634 #define DUK_HEAP_STRING_UC_THREAD(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_THREAD)
1635 #define DUK_HTHREAD_STRING_UC_THREAD(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_THREAD)
1636 #define DUK_STRIDX_EVAL                                               33                             /* 'eval' */
1637 #define DUK_HEAP_STRING_EVAL(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EVAL)
1638 #define DUK_HTHREAD_STRING_EVAL(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EVAL)
1639 #define DUK_STRIDX_VALUE                                              34                             /* 'value' */
1640 #define DUK_HEAP_STRING_VALUE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VALUE)
1641 #define DUK_HTHREAD_STRING_VALUE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VALUE)
1642 #define DUK_STRIDX_WRITABLE                                           35                             /* 'writable' */
1643 #define DUK_HEAP_STRING_WRITABLE(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITABLE)
1644 #define DUK_HTHREAD_STRING_WRITABLE(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITABLE)
1645 #define DUK_STRIDX_CONFIGURABLE                                       36                             /* 'configurable' */
1646 #define DUK_HEAP_STRING_CONFIGURABLE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONFIGURABLE)
1647 #define DUK_HTHREAD_STRING_CONFIGURABLE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONFIGURABLE)
1648 #define DUK_STRIDX_ENUMERABLE                                         37                             /* 'enumerable' */
1649 #define DUK_HEAP_STRING_ENUMERABLE(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUMERABLE)
1650 #define DUK_HTHREAD_STRING_ENUMERABLE(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUMERABLE)
1651 #define DUK_STRIDX_JOIN                                               38                             /* 'join' */
1652 #define DUK_HEAP_STRING_JOIN(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JOIN)
1653 #define DUK_HTHREAD_STRING_JOIN(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JOIN)
1654 #define DUK_STRIDX_TO_LOCALE_STRING                                   39                             /* 'toLocaleString' */
1655 #define DUK_HEAP_STRING_TO_LOCALE_STRING(heap)                        DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_LOCALE_STRING)
1656 #define DUK_HTHREAD_STRING_TO_LOCALE_STRING(thr)                      DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_LOCALE_STRING)
1657 #define DUK_STRIDX_VALUE_OF                                           40                             /* 'valueOf' */
1658 #define DUK_HEAP_STRING_VALUE_OF(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VALUE_OF)
1659 #define DUK_HTHREAD_STRING_VALUE_OF(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VALUE_OF)
1660 #define DUK_STRIDX_TO_UTC_STRING                                      41                             /* 'toUTCString' */
1661 #define DUK_HEAP_STRING_TO_UTC_STRING(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_UTC_STRING)
1662 #define DUK_HTHREAD_STRING_TO_UTC_STRING(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_UTC_STRING)
1663 #define DUK_STRIDX_TO_ISO_STRING                                      42                             /* 'toISOString' */
1664 #define DUK_HEAP_STRING_TO_ISO_STRING(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_ISO_STRING)
1665 #define DUK_HTHREAD_STRING_TO_ISO_STRING(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_ISO_STRING)
1666 #define DUK_STRIDX_TO_GMT_STRING                                      43                             /* 'toGMTString' */
1667 #define DUK_HEAP_STRING_TO_GMT_STRING(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_GMT_STRING)
1668 #define DUK_HTHREAD_STRING_TO_GMT_STRING(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_GMT_STRING)
1669 #define DUK_STRIDX_SOURCE                                             44                             /* 'source' */
1670 #define DUK_HEAP_STRING_SOURCE(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SOURCE)
1671 #define DUK_HTHREAD_STRING_SOURCE(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SOURCE)
1672 #define DUK_STRIDX_IGNORE_CASE                                        45                             /* 'ignoreCase' */
1673 #define DUK_HEAP_STRING_IGNORE_CASE(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IGNORE_CASE)
1674 #define DUK_HTHREAD_STRING_IGNORE_CASE(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IGNORE_CASE)
1675 #define DUK_STRIDX_MULTILINE                                          46                             /* 'multiline' */
1676 #define DUK_HEAP_STRING_MULTILINE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MULTILINE)
1677 #define DUK_HTHREAD_STRING_MULTILINE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MULTILINE)
1678 #define DUK_STRIDX_LAST_INDEX                                         47                             /* 'lastIndex' */
1679 #define DUK_HEAP_STRING_LAST_INDEX(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LAST_INDEX)
1680 #define DUK_HTHREAD_STRING_LAST_INDEX(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LAST_INDEX)
1681 #define DUK_STRIDX_FLAGS                                              48                             /* 'flags' */
1682 #define DUK_HEAP_STRING_FLAGS(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLAGS)
1683 #define DUK_HTHREAD_STRING_FLAGS(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLAGS)
1684 #define DUK_STRIDX_INDEX                                              49                             /* 'index' */
1685 #define DUK_HEAP_STRING_INDEX(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INDEX)
1686 #define DUK_HTHREAD_STRING_INDEX(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INDEX)
1687 #define DUK_STRIDX_PROTOTYPE                                          50                             /* 'prototype' */
1688 #define DUK_HEAP_STRING_PROTOTYPE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTOTYPE)
1689 #define DUK_HTHREAD_STRING_PROTOTYPE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTOTYPE)
1690 #define DUK_STRIDX_CONSTRUCTOR                                        51                             /* 'constructor' */
1691 #define DUK_HEAP_STRING_CONSTRUCTOR(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONSTRUCTOR)
1692 #define DUK_HTHREAD_STRING_CONSTRUCTOR(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONSTRUCTOR)
1693 #define DUK_STRIDX_MESSAGE                                            52                             /* 'message' */
1694 #define DUK_HEAP_STRING_MESSAGE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MESSAGE)
1695 #define DUK_HTHREAD_STRING_MESSAGE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MESSAGE)
1696 #define DUK_STRIDX_LC_BOOLEAN                                         53                             /* 'boolean' */
1697 #define DUK_HEAP_STRING_LC_BOOLEAN(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BOOLEAN)
1698 #define DUK_HTHREAD_STRING_LC_BOOLEAN(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BOOLEAN)
1699 #define DUK_STRIDX_LC_NUMBER                                          54                             /* 'number' */
1700 #define DUK_HEAP_STRING_LC_NUMBER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NUMBER)
1701 #define DUK_HTHREAD_STRING_LC_NUMBER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NUMBER)
1702 #define DUK_STRIDX_LC_STRING                                          55                             /* 'string' */
1703 #define DUK_HEAP_STRING_LC_STRING(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_STRING)
1704 #define DUK_HTHREAD_STRING_LC_STRING(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_STRING)
1705 #define DUK_STRIDX_LC_SYMBOL                                          56                             /* 'symbol' */
1706 #define DUK_HEAP_STRING_LC_SYMBOL(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_SYMBOL)
1707 #define DUK_HTHREAD_STRING_LC_SYMBOL(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_SYMBOL)
1708 #define DUK_STRIDX_LC_OBJECT                                          57                             /* 'object' */
1709 #define DUK_HEAP_STRING_LC_OBJECT(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_OBJECT)
1710 #define DUK_HTHREAD_STRING_LC_OBJECT(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_OBJECT)
1711 #define DUK_STRIDX_LC_UNDEFINED                                       58                             /* 'undefined' */
1712 #define DUK_HEAP_STRING_LC_UNDEFINED(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_UNDEFINED)
1713 #define DUK_HTHREAD_STRING_LC_UNDEFINED(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_UNDEFINED)
1714 #define DUK_STRIDX_NAN                                                59                             /* 'NaN' */
1715 #define DUK_HEAP_STRING_NAN(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAN)
1716 #define DUK_HTHREAD_STRING_NAN(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAN)
1717 #define DUK_STRIDX_INFINITY                                           60                             /* 'Infinity' */
1718 #define DUK_HEAP_STRING_INFINITY(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INFINITY)
1719 #define DUK_HTHREAD_STRING_INFINITY(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INFINITY)
1720 #define DUK_STRIDX_MINUS_INFINITY                                     61                             /* '-Infinity' */
1721 #define DUK_HEAP_STRING_MINUS_INFINITY(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MINUS_INFINITY)
1722 #define DUK_HTHREAD_STRING_MINUS_INFINITY(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MINUS_INFINITY)
1723 #define DUK_STRIDX_MINUS_ZERO                                         62                             /* '-0' */
1724 #define DUK_HEAP_STRING_MINUS_ZERO(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MINUS_ZERO)
1725 #define DUK_HTHREAD_STRING_MINUS_ZERO(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MINUS_ZERO)
1726 #define DUK_STRIDX_COMMA                                              63                             /* ',' */
1727 #define DUK_HEAP_STRING_COMMA(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMMA)
1728 #define DUK_HTHREAD_STRING_COMMA(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMMA)
1729 #define DUK_STRIDX_NEWLINE_4SPACE                                     64                             /* '\n    ' */
1730 #define DUK_HEAP_STRING_NEWLINE_4SPACE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEWLINE_4SPACE)
1731 #define DUK_HTHREAD_STRING_NEWLINE_4SPACE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEWLINE_4SPACE)
1732 #define DUK_STRIDX_BRACKETED_ELLIPSIS                                 65                             /* '[...]' */
1733 #define DUK_HEAP_STRING_BRACKETED_ELLIPSIS(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BRACKETED_ELLIPSIS)
1734 #define DUK_HTHREAD_STRING_BRACKETED_ELLIPSIS(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BRACKETED_ELLIPSIS)
1735 #define DUK_STRIDX_INVALID_DATE                                       66                             /* 'Invalid Date' */
1736 #define DUK_HEAP_STRING_INVALID_DATE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INVALID_DATE)
1737 #define DUK_HTHREAD_STRING_INVALID_DATE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INVALID_DATE)
1738 #define DUK_STRIDX_LC_ARGUMENTS                                       67                             /* 'arguments' */
1739 #define DUK_HEAP_STRING_LC_ARGUMENTS(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_ARGUMENTS)
1740 #define DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_ARGUMENTS)
1741 #define DUK_STRIDX_CALLEE                                             68                             /* 'callee' */
1742 #define DUK_HEAP_STRING_CALLEE(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CALLEE)
1743 #define DUK_HTHREAD_STRING_CALLEE(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CALLEE)
1744 #define DUK_STRIDX_CALLER                                             69                             /* 'caller' */
1745 #define DUK_HEAP_STRING_CALLER(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CALLER)
1746 #define DUK_HTHREAD_STRING_CALLER(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CALLER)
1747 #define DUK_STRIDX_APPLY                                              70                             /* 'apply' */
1748 #define DUK_HEAP_STRING_APPLY(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_APPLY)
1749 #define DUK_HTHREAD_STRING_APPLY(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_APPLY)
1750 #define DUK_STRIDX_CONSTRUCT                                          71                             /* 'construct' */
1751 #define DUK_HEAP_STRING_CONSTRUCT(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONSTRUCT)
1752 #define DUK_HTHREAD_STRING_CONSTRUCT(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONSTRUCT)
1753 #define DUK_STRIDX_DELETE_PROPERTY                                    72                             /* 'deleteProperty' */
1754 #define DUK_HEAP_STRING_DELETE_PROPERTY(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE_PROPERTY)
1755 #define DUK_HTHREAD_STRING_DELETE_PROPERTY(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE_PROPERTY)
1756 #define DUK_STRIDX_GET                                                73                             /* 'get' */
1757 #define DUK_HEAP_STRING_GET(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET)
1758 #define DUK_HTHREAD_STRING_GET(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET)
1759 #define DUK_STRIDX_HAS                                                74                             /* 'has' */
1760 #define DUK_HEAP_STRING_HAS(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HAS)
1761 #define DUK_HTHREAD_STRING_HAS(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HAS)
1762 #define DUK_STRIDX_OWN_KEYS                                           75                             /* 'ownKeys' */
1763 #define DUK_HEAP_STRING_OWN_KEYS(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OWN_KEYS)
1764 #define DUK_HTHREAD_STRING_OWN_KEYS(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OWN_KEYS)
1765 #define DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE                      76                             /* '\x81Symbol.toPrimitive\xff' */
1766 #define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_TO_PRIMITIVE(heap)           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE)
1767 #define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_TO_PRIMITIVE(thr)         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE)
1768 #define DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE                      77                             /* '\x81Symbol.hasInstance\xff' */
1769 #define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_HAS_INSTANCE(heap)           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE)
1770 #define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_HAS_INSTANCE(thr)         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE)
1771 #define DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG                     78                             /* '\x81Symbol.toStringTag\xff' */
1772 #define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_TO_STRING_TAG(heap)          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG)
1773 #define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_TO_STRING_TAG(thr)        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG)
1774 #define DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE              79                             /* '\x81Symbol.isConcatSpreadable\xff' */
1775 #define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE(heap)   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE)
1776 #define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE(thr)  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE)
1777 #define DUK_STRIDX_SET_PROTOTYPE_OF                                   80                             /* 'setPrototypeOf' */
1778 #define DUK_HEAP_STRING_SET_PROTOTYPE_OF(heap)                        DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_PROTOTYPE_OF)
1779 #define DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr)                      DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_PROTOTYPE_OF)
1780 #define DUK_STRIDX___PROTO__                                          81                             /* '__proto__' */
1781 #define DUK_HEAP_STRING___PROTO__(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX___PROTO__)
1782 #define DUK_HTHREAD_STRING___PROTO__(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX___PROTO__)
1783 #define DUK_STRIDX_TO_STRING                                          82                             /* 'toString' */
1784 #define DUK_HEAP_STRING_TO_STRING(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_STRING)
1785 #define DUK_HTHREAD_STRING_TO_STRING(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_STRING)
1786 #define DUK_STRIDX_TO_JSON                                            83                             /* 'toJSON' */
1787 #define DUK_HEAP_STRING_TO_JSON(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_JSON)
1788 #define DUK_HTHREAD_STRING_TO_JSON(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_JSON)
1789 #define DUK_STRIDX_TYPE                                               84                             /* 'type' */
1790 #define DUK_HEAP_STRING_TYPE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPE)
1791 #define DUK_HTHREAD_STRING_TYPE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPE)
1792 #define DUK_STRIDX_DATA                                               85                             /* 'data' */
1793 #define DUK_HEAP_STRING_DATA(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA)
1794 #define DUK_HTHREAD_STRING_DATA(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA)
1795 #define DUK_STRIDX_LC_BUFFER                                          86                             /* 'buffer' */
1796 #define DUK_HEAP_STRING_LC_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BUFFER)
1797 #define DUK_HTHREAD_STRING_LC_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BUFFER)
1798 #define DUK_STRIDX_LENGTH                                             87                             /* 'length' */
1799 #define DUK_HEAP_STRING_LENGTH(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LENGTH)
1800 #define DUK_HTHREAD_STRING_LENGTH(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LENGTH)
1801 #define DUK_STRIDX_SET                                                88                             /* 'set' */
1802 #define DUK_HEAP_STRING_SET(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET)
1803 #define DUK_HTHREAD_STRING_SET(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET)
1804 #define DUK_STRIDX_STACK                                              89                             /* 'stack' */
1805 #define DUK_HEAP_STRING_STACK(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STACK)
1806 #define DUK_HTHREAD_STRING_STACK(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STACK)
1807 #define DUK_STRIDX_PC                                                 90                             /* 'pc' */
1808 #define DUK_HEAP_STRING_PC(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PC)
1809 #define DUK_HTHREAD_STRING_PC(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PC)
1810 #define DUK_STRIDX_LINE_NUMBER                                        91                             /* 'lineNumber' */
1811 #define DUK_HEAP_STRING_LINE_NUMBER(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LINE_NUMBER)
1812 #define DUK_HTHREAD_STRING_LINE_NUMBER(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LINE_NUMBER)
1813 #define DUK_STRIDX_INT_TRACEDATA                                      92                             /* '\x82Tracedata' */
1814 #define DUK_HEAP_STRING_INT_TRACEDATA(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TRACEDATA)
1815 #define DUK_HTHREAD_STRING_INT_TRACEDATA(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TRACEDATA)
1816 #define DUK_STRIDX_NAME                                               93                             /* 'name' */
1817 #define DUK_HEAP_STRING_NAME(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAME)
1818 #define DUK_HTHREAD_STRING_NAME(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAME)
1819 #define DUK_STRIDX_FILE_NAME                                          94                             /* 'fileName' */
1820 #define DUK_HEAP_STRING_FILE_NAME(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILE_NAME)
1821 #define DUK_HTHREAD_STRING_FILE_NAME(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FILE_NAME)
1822 #define DUK_STRIDX_LC_POINTER                                         95                             /* 'pointer' */
1823 #define DUK_HEAP_STRING_LC_POINTER(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_POINTER)
1824 #define DUK_HTHREAD_STRING_LC_POINTER(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_POINTER)
1825 #define DUK_STRIDX_INT_TARGET                                         96                             /* '\x82Target' */
1826 #define DUK_HEAP_STRING_INT_TARGET(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TARGET)
1827 #define DUK_HTHREAD_STRING_INT_TARGET(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TARGET)
1828 #define DUK_STRIDX_INT_NEXT                                           97                             /* '\x82Next' */
1829 #define DUK_HEAP_STRING_INT_NEXT(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_NEXT)
1830 #define DUK_HTHREAD_STRING_INT_NEXT(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_NEXT)
1831 #define DUK_STRIDX_INT_BYTECODE                                       98                             /* '\x82Bytecode' */
1832 #define DUK_HEAP_STRING_INT_BYTECODE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_BYTECODE)
1833 #define DUK_HTHREAD_STRING_INT_BYTECODE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_BYTECODE)
1834 #define DUK_STRIDX_INT_FORMALS                                        99                             /* '\x82Formals' */
1835 #define DUK_HEAP_STRING_INT_FORMALS(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FORMALS)
1836 #define DUK_HTHREAD_STRING_INT_FORMALS(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FORMALS)
1837 #define DUK_STRIDX_INT_VARMAP                                         100                            /* '\x82Varmap' */
1838 #define DUK_HEAP_STRING_INT_VARMAP(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARMAP)
1839 #define DUK_HTHREAD_STRING_INT_VARMAP(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARMAP)
1840 #define DUK_STRIDX_INT_SOURCE                                         101                            /* '\x82Source' */
1841 #define DUK_HEAP_STRING_INT_SOURCE(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_SOURCE)
1842 #define DUK_HTHREAD_STRING_INT_SOURCE(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_SOURCE)
1843 #define DUK_STRIDX_INT_PC2LINE                                        102                            /* '\x82Pc2line' */
1844 #define DUK_HEAP_STRING_INT_PC2LINE(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_PC2LINE)
1845 #define DUK_HTHREAD_STRING_INT_PC2LINE(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_PC2LINE)
1846 #define DUK_STRIDX_INT_MAP                                            103                            /* '\x82Map' */
1847 #define DUK_HEAP_STRING_INT_MAP(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_MAP)
1848 #define DUK_HTHREAD_STRING_INT_MAP(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_MAP)
1849 #define DUK_STRIDX_INT_VARENV                                         104                            /* '\x82Varenv' */
1850 #define DUK_HEAP_STRING_INT_VARENV(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARENV)
1851 #define DUK_HTHREAD_STRING_INT_VARENV(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARENV)
1852 #define DUK_STRIDX_INT_FINALIZER                                      105                            /* '\x82Finalizer' */
1853 #define DUK_HEAP_STRING_INT_FINALIZER(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FINALIZER)
1854 #define DUK_HTHREAD_STRING_INT_FINALIZER(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FINALIZER)
1855 #define DUK_STRIDX_INT_VALUE                                          106                            /* '\x82Value' */
1856 #define DUK_HEAP_STRING_INT_VALUE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VALUE)
1857 #define DUK_HTHREAD_STRING_INT_VALUE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VALUE)
1858 #define DUK_STRIDX_COMPILE                                            107                            /* 'compile' */
1859 #define DUK_HEAP_STRING_COMPILE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMPILE)
1860 #define DUK_HTHREAD_STRING_COMPILE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMPILE)
1861 #define DUK_STRIDX_INPUT                                              108                            /* 'input' */
1862 #define DUK_HEAP_STRING_INPUT(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INPUT)
1863 #define DUK_HTHREAD_STRING_INPUT(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INPUT)
1864 #define DUK_STRIDX_ERR_CREATE                                         109                            /* 'errCreate' */
1865 #define DUK_HEAP_STRING_ERR_CREATE(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_CREATE)
1866 #define DUK_HTHREAD_STRING_ERR_CREATE(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_CREATE)
1867 #define DUK_STRIDX_ERR_THROW                                          110                            /* 'errThrow' */
1868 #define DUK_HEAP_STRING_ERR_THROW(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_THROW)
1869 #define DUK_HTHREAD_STRING_ERR_THROW(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_THROW)
1870 #define DUK_STRIDX_ENV                                                111                            /* 'env' */
1871 #define DUK_HEAP_STRING_ENV(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENV)
1872 #define DUK_HTHREAD_STRING_ENV(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENV)
1873 #define DUK_STRIDX_HEX                                                112                            /* 'hex' */
1874 #define DUK_HEAP_STRING_HEX(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HEX)
1875 #define DUK_HTHREAD_STRING_HEX(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HEX)
1876 #define DUK_STRIDX_BASE64                                             113                            /* 'base64' */
1877 #define DUK_HEAP_STRING_BASE64(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BASE64)
1878 #define DUK_HTHREAD_STRING_BASE64(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BASE64)
1879 #define DUK_STRIDX_JX                                                 114                            /* 'jx' */
1880 #define DUK_HEAP_STRING_JX(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JX)
1881 #define DUK_HTHREAD_STRING_JX(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JX)
1882 #define DUK_STRIDX_JC                                                 115                            /* 'jc' */
1883 #define DUK_HEAP_STRING_JC(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JC)
1884 #define DUK_HTHREAD_STRING_JC(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JC)
1885 #define DUK_STRIDX_JSON_EXT_UNDEFINED                                 116                            /* '{"_undef":true}' */
1886 #define DUK_HEAP_STRING_JSON_EXT_UNDEFINED(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_UNDEFINED)
1887 #define DUK_HTHREAD_STRING_JSON_EXT_UNDEFINED(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_UNDEFINED)
1888 #define DUK_STRIDX_JSON_EXT_NAN                                       117                            /* '{"_nan":true}' */
1889 #define DUK_HEAP_STRING_JSON_EXT_NAN(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NAN)
1890 #define DUK_HTHREAD_STRING_JSON_EXT_NAN(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NAN)
1891 #define DUK_STRIDX_JSON_EXT_POSINF                                    118                            /* '{"_inf":true}' */
1892 #define DUK_HEAP_STRING_JSON_EXT_POSINF(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_POSINF)
1893 #define DUK_HTHREAD_STRING_JSON_EXT_POSINF(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_POSINF)
1894 #define DUK_STRIDX_JSON_EXT_NEGINF                                    119                            /* '{"_ninf":true}' */
1895 #define DUK_HEAP_STRING_JSON_EXT_NEGINF(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NEGINF)
1896 #define DUK_HTHREAD_STRING_JSON_EXT_NEGINF(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NEGINF)
1897 #define DUK_STRIDX_JSON_EXT_FUNCTION1                                 120                            /* '{"_func":true}' */
1898 #define DUK_HEAP_STRING_JSON_EXT_FUNCTION1(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION1)
1899 #define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION1(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION1)
1900 #define DUK_STRIDX_JSON_EXT_FUNCTION2                                 121                            /* '{_func:true}' */
1901 #define DUK_HEAP_STRING_JSON_EXT_FUNCTION2(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION2)
1902 #define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION2(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION2)
1903 #define DUK_STRIDX_BREAK                                              122                            /* 'break' */
1904 #define DUK_HEAP_STRING_BREAK(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BREAK)
1905 #define DUK_HTHREAD_STRING_BREAK(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BREAK)
1906 #define DUK_STRIDX_CASE                                               123                            /* 'case' */
1907 #define DUK_HEAP_STRING_CASE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CASE)
1908 #define DUK_HTHREAD_STRING_CASE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CASE)
1909 #define DUK_STRIDX_CATCH                                              124                            /* 'catch' */
1910 #define DUK_HEAP_STRING_CATCH(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CATCH)
1911 #define DUK_HTHREAD_STRING_CATCH(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CATCH)
1912 #define DUK_STRIDX_CONTINUE                                           125                            /* 'continue' */
1913 #define DUK_HEAP_STRING_CONTINUE(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONTINUE)
1914 #define DUK_HTHREAD_STRING_CONTINUE(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONTINUE)
1915 #define DUK_STRIDX_DEBUGGER                                           126                            /* 'debugger' */
1916 #define DUK_HEAP_STRING_DEBUGGER(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEBUGGER)
1917 #define DUK_HTHREAD_STRING_DEBUGGER(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEBUGGER)
1918 #define DUK_STRIDX_DEFAULT                                            127                            /* 'default' */
1919 #define DUK_HEAP_STRING_DEFAULT(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEFAULT)
1920 #define DUK_HTHREAD_STRING_DEFAULT(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEFAULT)
1921 #define DUK_STRIDX_DELETE                                             128                            /* 'delete' */
1922 #define DUK_HEAP_STRING_DELETE(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE)
1923 #define DUK_HTHREAD_STRING_DELETE(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE)
1924 #define DUK_STRIDX_DO                                                 129                            /* 'do' */
1925 #define DUK_HEAP_STRING_DO(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DO)
1926 #define DUK_HTHREAD_STRING_DO(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DO)
1927 #define DUK_STRIDX_ELSE                                               130                            /* 'else' */
1928 #define DUK_HEAP_STRING_ELSE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ELSE)
1929 #define DUK_HTHREAD_STRING_ELSE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ELSE)
1930 #define DUK_STRIDX_FINALLY                                            131                            /* 'finally' */
1931 #define DUK_HEAP_STRING_FINALLY(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FINALLY)
1932 #define DUK_HTHREAD_STRING_FINALLY(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FINALLY)
1933 #define DUK_STRIDX_FOR                                                132                            /* 'for' */
1934 #define DUK_HEAP_STRING_FOR(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FOR)
1935 #define DUK_HTHREAD_STRING_FOR(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FOR)
1936 #define DUK_STRIDX_LC_FUNCTION                                        133                            /* 'function' */
1937 #define DUK_HEAP_STRING_LC_FUNCTION(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_FUNCTION)
1938 #define DUK_HTHREAD_STRING_LC_FUNCTION(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_FUNCTION)
1939 #define DUK_STRIDX_IF                                                 134                            /* 'if' */
1940 #define DUK_HEAP_STRING_IF(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IF)
1941 #define DUK_HTHREAD_STRING_IF(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IF)
1942 #define DUK_STRIDX_IN                                                 135                            /* 'in' */
1943 #define DUK_HEAP_STRING_IN(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IN)
1944 #define DUK_HTHREAD_STRING_IN(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IN)
1945 #define DUK_STRIDX_INSTANCEOF                                         136                            /* 'instanceof' */
1946 #define DUK_HEAP_STRING_INSTANCEOF(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INSTANCEOF)
1947 #define DUK_HTHREAD_STRING_INSTANCEOF(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INSTANCEOF)
1948 #define DUK_STRIDX_NEW                                                137                            /* 'new' */
1949 #define DUK_HEAP_STRING_NEW(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEW)
1950 #define DUK_HTHREAD_STRING_NEW(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEW)
1951 #define DUK_STRIDX_RETURN                                             138                            /* 'return' */
1952 #define DUK_HEAP_STRING_RETURN(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_RETURN)
1953 #define DUK_HTHREAD_STRING_RETURN(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_RETURN)
1954 #define DUK_STRIDX_SWITCH                                             139                            /* 'switch' */
1955 #define DUK_HEAP_STRING_SWITCH(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SWITCH)
1956 #define DUK_HTHREAD_STRING_SWITCH(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SWITCH)
1957 #define DUK_STRIDX_THIS                                               140                            /* 'this' */
1958 #define DUK_HEAP_STRING_THIS(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THIS)
1959 #define DUK_HTHREAD_STRING_THIS(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THIS)
1960 #define DUK_STRIDX_THROW                                              141                            /* 'throw' */
1961 #define DUK_HEAP_STRING_THROW(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THROW)
1962 #define DUK_HTHREAD_STRING_THROW(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THROW)
1963 #define DUK_STRIDX_TRY                                                142                            /* 'try' */
1964 #define DUK_HEAP_STRING_TRY(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRY)
1965 #define DUK_HTHREAD_STRING_TRY(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRY)
1966 #define DUK_STRIDX_TYPEOF                                             143                            /* 'typeof' */
1967 #define DUK_HEAP_STRING_TYPEOF(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPEOF)
1968 #define DUK_HTHREAD_STRING_TYPEOF(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPEOF)
1969 #define DUK_STRIDX_VAR                                                144                            /* 'var' */
1970 #define DUK_HEAP_STRING_VAR(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VAR)
1971 #define DUK_HTHREAD_STRING_VAR(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VAR)
1972 #define DUK_STRIDX_CONST                                              145                            /* 'const' */
1973 #define DUK_HEAP_STRING_CONST(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONST)
1974 #define DUK_HTHREAD_STRING_CONST(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONST)
1975 #define DUK_STRIDX_VOID                                               146                            /* 'void' */
1976 #define DUK_HEAP_STRING_VOID(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VOID)
1977 #define DUK_HTHREAD_STRING_VOID(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VOID)
1978 #define DUK_STRIDX_WHILE                                              147                            /* 'while' */
1979 #define DUK_HEAP_STRING_WHILE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WHILE)
1980 #define DUK_HTHREAD_STRING_WHILE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WHILE)
1981 #define DUK_STRIDX_WITH                                               148                            /* 'with' */
1982 #define DUK_HEAP_STRING_WITH(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WITH)
1983 #define DUK_HTHREAD_STRING_WITH(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WITH)
1984 #define DUK_STRIDX_CLASS                                              149                            /* 'class' */
1985 #define DUK_HEAP_STRING_CLASS(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CLASS)
1986 #define DUK_HTHREAD_STRING_CLASS(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CLASS)
1987 #define DUK_STRIDX_ENUM                                               150                            /* 'enum' */
1988 #define DUK_HEAP_STRING_ENUM(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUM)
1989 #define DUK_HTHREAD_STRING_ENUM(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUM)
1990 #define DUK_STRIDX_EXPORT                                             151                            /* 'export' */
1991 #define DUK_HEAP_STRING_EXPORT(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORT)
1992 #define DUK_HTHREAD_STRING_EXPORT(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXPORT)
1993 #define DUK_STRIDX_EXTENDS                                            152                            /* 'extends' */
1994 #define DUK_HEAP_STRING_EXTENDS(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXTENDS)
1995 #define DUK_HTHREAD_STRING_EXTENDS(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXTENDS)
1996 #define DUK_STRIDX_IMPORT                                             153                            /* 'import' */
1997 #define DUK_HEAP_STRING_IMPORT(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPORT)
1998 #define DUK_HTHREAD_STRING_IMPORT(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPORT)
1999 #define DUK_STRIDX_SUPER                                              154                            /* 'super' */
2000 #define DUK_HEAP_STRING_SUPER(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SUPER)
2001 #define DUK_HTHREAD_STRING_SUPER(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SUPER)
2002 #define DUK_STRIDX_LC_NULL                                            155                            /* 'null' */
2003 #define DUK_HEAP_STRING_LC_NULL(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NULL)
2004 #define DUK_HTHREAD_STRING_LC_NULL(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NULL)
2005 #define DUK_STRIDX_TRUE                                               156                            /* 'true' */
2006 #define DUK_HEAP_STRING_TRUE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRUE)
2007 #define DUK_HTHREAD_STRING_TRUE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRUE)
2008 #define DUK_STRIDX_FALSE                                              157                            /* 'false' */
2009 #define DUK_HEAP_STRING_FALSE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FALSE)
2010 #define DUK_HTHREAD_STRING_FALSE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FALSE)
2011 #define DUK_STRIDX_IMPLEMENTS                                         158                            /* 'implements' */
2012 #define DUK_HEAP_STRING_IMPLEMENTS(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPLEMENTS)
2013 #define DUK_HTHREAD_STRING_IMPLEMENTS(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPLEMENTS)
2014 #define DUK_STRIDX_INTERFACE                                          159                            /* 'interface' */
2015 #define DUK_HEAP_STRING_INTERFACE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INTERFACE)
2016 #define DUK_HTHREAD_STRING_INTERFACE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INTERFACE)
2017 #define DUK_STRIDX_LET                                                160                            /* 'let' */
2018 #define DUK_HEAP_STRING_LET(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LET)
2019 #define DUK_HTHREAD_STRING_LET(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LET)
2020 #define DUK_STRIDX_PACKAGE                                            161                            /* 'package' */
2021 #define DUK_HEAP_STRING_PACKAGE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PACKAGE)
2022 #define DUK_HTHREAD_STRING_PACKAGE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PACKAGE)
2023 #define DUK_STRIDX_PRIVATE                                            162                            /* 'private' */
2024 #define DUK_HEAP_STRING_PRIVATE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PRIVATE)
2025 #define DUK_HTHREAD_STRING_PRIVATE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PRIVATE)
2026 #define DUK_STRIDX_PROTECTED                                          163                            /* 'protected' */
2027 #define DUK_HEAP_STRING_PROTECTED(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTECTED)
2028 #define DUK_HTHREAD_STRING_PROTECTED(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTECTED)
2029 #define DUK_STRIDX_PUBLIC                                             164                            /* 'public' */
2030 #define DUK_HEAP_STRING_PUBLIC(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PUBLIC)
2031 #define DUK_HTHREAD_STRING_PUBLIC(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PUBLIC)
2032 #define DUK_STRIDX_STATIC                                             165                            /* 'static' */
2033 #define DUK_HEAP_STRING_STATIC(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STATIC)
2034 #define DUK_HTHREAD_STRING_STATIC(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STATIC)
2035 #define DUK_STRIDX_YIELD                                              166                            /* 'yield' */
2036 #define DUK_HEAP_STRING_YIELD(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_YIELD)
2037 #define DUK_HTHREAD_STRING_YIELD(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_YIELD)
2038 
2039 #define DUK_HEAP_NUM_STRINGS                                          167
2040 #define DUK_STRIDX_START_RESERVED                                     122
2041 #define DUK_STRIDX_START_STRICT_RESERVED                              158
2042 #define DUK_STRIDX_END_RESERVED                                       167                            /* exclusive endpoint */
2043 
2044 /* To convert a heap stridx to a token number, subtract
2045  * DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED.
2046  */
2047 #if !defined(DUK_SINGLE_FILE)
2048 DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[972];
2049 #endif  /* !DUK_SINGLE_FILE */
2050 #define DUK_STRDATA_MAX_STRLEN                                        27
2051 #define DUK_STRDATA_DATA_LENGTH                                       972
2052 #endif  /* DUK_USE_ROM_STRINGS */
2053 
2054 #if defined(DUK_USE_ROM_OBJECTS)
2055 #error RAM support not enabled, rerun configure.py with --ram-support
2056 #else  /* DUK_USE_ROM_OBJECTS */
2057 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor(duk_context *ctx);
2058 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_constructor(duk_context *ctx);
2059 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_context *ctx);
2060 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor(duk_context *ctx);
2061 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor(duk_context *ctx);
2062 DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_constructor(duk_context *ctx);
2063 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_constructor(duk_context *ctx);
2064 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor(duk_context *ctx);
2065 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_constructor(duk_context *ctx);
2066 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_constructor_shared(duk_context *ctx);
2067 DUK_INTERNAL_DECL duk_ret_t duk_bi_type_error_thrower(duk_context *ctx);
2068 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_int(duk_context *ctx);
2069 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_float(duk_context *ctx);
2070 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_constructor(duk_context *ctx);
2071 DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_constructor(duk_context *ctx);
2072 DUK_INTERNAL_DECL duk_ret_t duk_bi_proxy_constructor(duk_context *ctx);
2073 DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_constructor_shared(duk_context *ctx);
2074 DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_constructor(duk_context *ctx);
2075 DUK_INTERNAL_DECL duk_ret_t duk_bi_dataview_constructor(duk_context *ctx);
2076 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx);
2077 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_context *ctx);
2078 DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_constructor(duk_context *ctx);
2079 DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_constructor(duk_context *ctx);
2080 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_eval(duk_context *ctx);
2081 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_nan(duk_context *ctx);
2082 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_finite(duk_context *ctx);
2083 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri(duk_context *ctx);
2084 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri_component(duk_context *ctx);
2085 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri(duk_context *ctx);
2086 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri_component(duk_context *ctx);
2087 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_escape(duk_context *ctx);
2088 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_unescape(duk_context *ctx);
2089 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx);
2090 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_setprototype_shared(duk_context *ctx);
2091 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_context *ctx);
2092 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_keys_shared(duk_context *ctx);
2093 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_assign(duk_context *ctx);
2094 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_create(duk_context *ctx);
2095 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_define_property(duk_context *ctx);
2096 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_define_properties(duk_context *ctx);
2097 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_context *ctx);
2098 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_context *ctx);
2099 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_context *ctx);
2100 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_extensible(duk_context *ctx);
2101 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is(duk_context *ctx);
2102 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_string(duk_context *ctx);
2103 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_locale_string(duk_context *ctx);
2104 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_value_of(duk_context *ctx);
2105 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_has_own_property(duk_context *ctx);
2106 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_context *ctx);
2107 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_context *ctx);
2108 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_defineaccessor(duk_context *ctx);
2109 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_lookupaccessor(duk_context *ctx);
2110 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_to_string(duk_context *ctx);
2111 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx);
2112 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_call(duk_context *ctx);
2113 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx);
2114 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_hasinstance(duk_context *ctx);
2115 DUK_INTERNAL_DECL duk_ret_t duk_bi_native_function_length(duk_context *ctx);
2116 DUK_INTERNAL_DECL duk_ret_t duk_bi_native_function_name(duk_context *ctx);
2117 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor_is_array(duk_context *ctx);
2118 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_to_string(duk_context *ctx);
2119 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_join_shared(duk_context *ctx);
2120 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_concat(duk_context *ctx);
2121 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_pop(duk_context *ctx);
2122 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_push(duk_context *ctx);
2123 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reverse(duk_context *ctx);
2124 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_shift(duk_context *ctx);
2125 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_slice(duk_context *ctx);
2126 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_sort(duk_context *ctx);
2127 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_splice(duk_context *ctx);
2128 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_unshift(duk_context *ctx);
2129 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_context *ctx);
2130 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_iter_shared(duk_context *ctx);
2131 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_context *ctx);
2132 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor_from_char_code(duk_context *ctx);
2133 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor_from_code_point(duk_context *ctx);
2134 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_to_string(duk_context *ctx);
2135 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_at(duk_context *ctx);
2136 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_code_at(duk_context *ctx);
2137 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_concat(duk_context *ctx);
2138 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_indexof_shared(duk_context *ctx);
2139 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_locale_compare(duk_context *ctx);
2140 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_match(duk_context *ctx);
2141 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx);
2142 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_search(duk_context *ctx);
2143 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_slice(duk_context *ctx);
2144 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_split(duk_context *ctx);
2145 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substring(duk_context *ctx);
2146 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_caseconv_shared(duk_context *ctx);
2147 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_trim(duk_context *ctx);
2148 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_repeat(duk_context *ctx);
2149 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_startswith_endswith(duk_context *ctx);
2150 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_includes(duk_context *ctx);
2151 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substr(duk_context *ctx);
2152 DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_context *ctx);
2153 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_check_shared(duk_context *ctx);
2154 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_string(duk_context *ctx);
2155 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_locale_string(duk_context *ctx);
2156 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_value_of(duk_context *ctx);
2157 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_fixed(duk_context *ctx);
2158 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_exponential(duk_context *ctx);
2159 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_precision(duk_context *ctx);
2160 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_parse(duk_context *ctx);
2161 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_utc(duk_context *ctx);
2162 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_now(duk_context *ctx);
2163 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_tostring_shared(duk_context *ctx);
2164 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_to_json(duk_context *ctx);
2165 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_value_of(duk_context *ctx);
2166 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_shared(duk_context *ctx);
2167 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_context *ctx);
2168 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_time(duk_context *ctx);
2169 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_shared(duk_context *ctx);
2170 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_toprimitive(duk_context *ctx);
2171 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_exec(duk_context *ctx);
2172 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_test(duk_context *ctx);
2173 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_tostring(duk_context *ctx);
2174 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_flags(duk_context *ctx);
2175 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_shared_getter(duk_context *ctx);
2176 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx);
2177 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_setter(duk_context *ctx);
2178 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx);
2179 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_setter(duk_context *ctx);
2180 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx);
2181 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_setter(duk_context *ctx);
2182 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx);
2183 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_onearg_shared(duk_context *ctx);
2184 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_twoarg_shared(duk_context *ctx);
2185 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_clz32(duk_context *ctx);
2186 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_hypot(duk_context *ctx);
2187 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_imul(duk_context *ctx);
2188 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_max(duk_context *ctx);
2189 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_min(duk_context *ctx);
2190 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_random(duk_context *ctx);
2191 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_sign(duk_context *ctx);
2192 DUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_parse(duk_context *ctx);
2193 DUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_stringify(duk_context *ctx);
2194 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_info(duk_context *ctx);
2195 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_act(duk_context *ctx);
2196 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_gc(duk_context *ctx);
2197 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_fin(duk_context *ctx);
2198 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_enc(duk_context *ctx);
2199 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_dec(duk_context *ctx);
2200 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_compact(duk_context *ctx);
2201 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_yield(duk_context *ctx);
2202 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_resume(duk_context *ctx);
2203 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_current(duk_context *ctx);
2204 DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_context *ctx);
2205 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_apply(duk_context *ctx);
2206 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_construct(duk_context *ctx);
2207 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_delete_property(duk_context *ctx);
2208 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_get(duk_context *ctx);
2209 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_has(duk_context *ctx);
2210 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_set(duk_context *ctx);
2211 DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_key_for(duk_context *ctx);
2212 DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_tostring_shared(duk_context *ctx);
2213 DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_toprimitive(duk_context *ctx);
2214 DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_isview(duk_context *ctx);
2215 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_context *ctx);
2216 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_slice_shared(duk_context *ctx);
2217 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_byteoffset_getter(duk_context *ctx);
2218 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_buffer_getter(duk_context *ctx);
2219 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_readfield(duk_context *ctx);
2220 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_writefield(duk_context *ctx);
2221 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_set(duk_context *ctx);
2222 DUK_INTERNAL_DECL duk_ret_t duk_bi_uint8array_allocplain(duk_context *ctx);
2223 DUK_INTERNAL_DECL duk_ret_t duk_bi_uint8array_plainof(duk_context *ctx);
2224 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_concat(duk_context *ctx);
2225 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_context *ctx);
2226 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_context *ctx);
2227 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_context *ctx);
2228 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_compare_shared(duk_context *ctx);
2229 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_context *ctx);
2230 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_context *ctx);
2231 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_fill(duk_context *ctx);
2232 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_copy(duk_context *ctx);
2233 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_write(duk_context *ctx);
2234 DUK_INTERNAL_DECL duk_ret_t duk_bi_cbor_encode(duk_context *ctx);
2235 DUK_INTERNAL_DECL duk_ret_t duk_bi_cbor_decode(duk_context *ctx);
2236 DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_prototype_encoding_getter(duk_context *ctx);
2237 DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_prototype_encode(duk_context *ctx);
2238 DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_prototype_shared_getter(duk_context *ctx);
2239 DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_prototype_decode(duk_context *ctx);
2240 DUK_INTERNAL_DECL duk_ret_t duk_bi_performance_now(duk_context *ctx);
2241 #if !defined(DUK_SINGLE_FILE)
2242 DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[185];
2243 #endif  /* !DUK_SINGLE_FILE */
2244 #define DUK_BIDX_GLOBAL                                               0
2245 #define DUK_BIDX_GLOBAL_ENV                                           1
2246 #define DUK_BIDX_OBJECT_CONSTRUCTOR                                   2
2247 #define DUK_BIDX_OBJECT_PROTOTYPE                                     3
2248 #define DUK_BIDX_FUNCTION_CONSTRUCTOR                                 4
2249 #define DUK_BIDX_FUNCTION_PROTOTYPE                                   5
2250 #define DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE                            6
2251 #define DUK_BIDX_ARRAY_CONSTRUCTOR                                    7
2252 #define DUK_BIDX_ARRAY_PROTOTYPE                                      8
2253 #define DUK_BIDX_STRING_CONSTRUCTOR                                   9
2254 #define DUK_BIDX_STRING_PROTOTYPE                                     10
2255 #define DUK_BIDX_BOOLEAN_CONSTRUCTOR                                  11
2256 #define DUK_BIDX_BOOLEAN_PROTOTYPE                                    12
2257 #define DUK_BIDX_NUMBER_CONSTRUCTOR                                   13
2258 #define DUK_BIDX_NUMBER_PROTOTYPE                                     14
2259 #define DUK_BIDX_DATE_CONSTRUCTOR                                     15
2260 #define DUK_BIDX_DATE_PROTOTYPE                                       16
2261 #define DUK_BIDX_REGEXP_CONSTRUCTOR                                   17
2262 #define DUK_BIDX_REGEXP_PROTOTYPE                                     18
2263 #define DUK_BIDX_ERROR_CONSTRUCTOR                                    19
2264 #define DUK_BIDX_ERROR_PROTOTYPE                                      20
2265 #define DUK_BIDX_EVAL_ERROR_CONSTRUCTOR                               21
2266 #define DUK_BIDX_EVAL_ERROR_PROTOTYPE                                 22
2267 #define DUK_BIDX_RANGE_ERROR_CONSTRUCTOR                              23
2268 #define DUK_BIDX_RANGE_ERROR_PROTOTYPE                                24
2269 #define DUK_BIDX_REFERENCE_ERROR_CONSTRUCTOR                          25
2270 #define DUK_BIDX_REFERENCE_ERROR_PROTOTYPE                            26
2271 #define DUK_BIDX_SYNTAX_ERROR_CONSTRUCTOR                             27
2272 #define DUK_BIDX_SYNTAX_ERROR_PROTOTYPE                               28
2273 #define DUK_BIDX_TYPE_ERROR_CONSTRUCTOR                               29
2274 #define DUK_BIDX_TYPE_ERROR_PROTOTYPE                                 30
2275 #define DUK_BIDX_URI_ERROR_CONSTRUCTOR                                31
2276 #define DUK_BIDX_URI_ERROR_PROTOTYPE                                  32
2277 #define DUK_BIDX_TYPE_ERROR_THROWER                                   33
2278 #define DUK_BIDX_DUKTAPE                                              34
2279 #define DUK_BIDX_THREAD_PROTOTYPE                                     35
2280 #define DUK_BIDX_POINTER_PROTOTYPE                                    36
2281 #define DUK_BIDX_DOUBLE_ERROR                                         37
2282 #define DUK_BIDX_SYMBOL_PROTOTYPE                                     38
2283 #define DUK_BIDX_ARRAYBUFFER_PROTOTYPE                                39
2284 #define DUK_BIDX_DATAVIEW_PROTOTYPE                                   40
2285 #define DUK_BIDX_INT8ARRAY_PROTOTYPE                                  41
2286 #define DUK_BIDX_UINT8ARRAY_PROTOTYPE                                 42
2287 #define DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE                          43
2288 #define DUK_BIDX_INT16ARRAY_PROTOTYPE                                 44
2289 #define DUK_BIDX_UINT16ARRAY_PROTOTYPE                                45
2290 #define DUK_BIDX_INT32ARRAY_PROTOTYPE                                 46
2291 #define DUK_BIDX_UINT32ARRAY_PROTOTYPE                                47
2292 #define DUK_BIDX_FLOAT32ARRAY_PROTOTYPE                               48
2293 #define DUK_BIDX_FLOAT64ARRAY_PROTOTYPE                               49
2294 #define DUK_BIDX_NODEJS_BUFFER_PROTOTYPE                              50
2295 #define DUK_NUM_BUILTINS                                              51
2296 #define DUK_NUM_BIDX_BUILTINS                                         51
2297 #define DUK_NUM_ALL_BUILTINS                                          80
2298 #if defined(DUK_USE_DOUBLE_LE)
2299 #if !defined(DUK_SINGLE_FILE)
2300 DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4281];
2301 #endif  /* !DUK_SINGLE_FILE */
2302 #define DUK_BUILTINS_DATA_LENGTH                                      4281
2303 #elif defined(DUK_USE_DOUBLE_BE)
2304 #if !defined(DUK_SINGLE_FILE)
2305 DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4281];
2306 #endif  /* !DUK_SINGLE_FILE */
2307 #define DUK_BUILTINS_DATA_LENGTH                                      4281
2308 #elif defined(DUK_USE_DOUBLE_ME)
2309 #if !defined(DUK_SINGLE_FILE)
2310 DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4281];
2311 #endif  /* !DUK_SINGLE_FILE */
2312 #define DUK_BUILTINS_DATA_LENGTH                                      4281
2313 #else
2314 #error invalid endianness defines
2315 #endif
2316 #endif  /* DUK_USE_ROM_OBJECTS */
2317 #endif  /* DUK_BUILTINS_H_INCLUDED */
2318 
2319 /* #include duk_util.h */
2320 /*
2321  *  Utilities
2322  */
2323 
2324 #if !defined(DUK_UTIL_H_INCLUDED)
2325 #define DUK_UTIL_H_INCLUDED
2326 
2327 #if defined(DUK_USE_GET_RANDOM_DOUBLE)
2328 #define DUK_UTIL_GET_RANDOM_DOUBLE(thr) DUK_USE_GET_RANDOM_DOUBLE((thr)->heap_udata)
2329 #else
2330 #define DUK_UTIL_GET_RANDOM_DOUBLE(thr) duk_util_tinyrandom_get_double(thr)
2331 #endif
2332 
2333 /*
2334  *  Some useful constants
2335  */
2336 
2337 #define DUK_DOUBLE_2TO32     4294967296.0
2338 #define DUK_DOUBLE_2TO31     2147483648.0
2339 #define DUK_DOUBLE_LOG2E     1.4426950408889634
2340 #define DUK_DOUBLE_LOG10E    0.4342944819032518
2341 
2342 /*
2343  *  Endian conversion
2344  */
2345 
2346 #if defined(DUK_USE_INTEGER_LE)
2347 #define DUK_HTON32(x) DUK_BSWAP32((x))
2348 #define DUK_NTOH32(x) DUK_BSWAP32((x))
2349 #define DUK_HTON16(x) DUK_BSWAP16((x))
2350 #define DUK_NTOH16(x) DUK_BSWAP16((x))
2351 #elif defined(DUK_USE_INTEGER_BE)
2352 #define DUK_HTON32(x) (x)
2353 #define DUK_NTOH32(x) (x)
2354 #define DUK_HTON16(x) (x)
2355 #define DUK_NTOH16(x) (x)
2356 #else
2357 #error internal error, endianness defines broken
2358 #endif
2359 
2360 /*
2361  *  Bitstream decoder
2362  */
2363 
2364 struct duk_bitdecoder_ctx {
2365 	const duk_uint8_t *data;
2366 	duk_size_t offset;
2367 	duk_size_t length;
2368 	duk_uint32_t currval;
2369 	duk_small_int_t currbits;
2370 };
2371 
2372 #define DUK_BD_BITPACKED_STRING_MAXLEN 256
2373 
2374 /*
2375  *  Bitstream encoder
2376  */
2377 
2378 struct duk_bitencoder_ctx {
2379 	duk_uint8_t *data;
2380 	duk_size_t offset;
2381 	duk_size_t length;
2382 	duk_uint32_t currval;
2383 	duk_small_int_t currbits;
2384 	duk_small_int_t truncated;
2385 };
2386 
2387 /*
2388  *  Raw write/read macros for big endian, unaligned basic values.
2389  *  Caller ensures there's enough space.  The INC macro variants
2390  *  update the pointer argument automatically.
2391  */
2392 
2393 #define DUK_RAW_WRITE_U8(ptr,val)  do { \
2394 		*(ptr) = (duk_uint8_t) (val); \
2395 	} while (0)
2396 #define DUK_RAW_WRITE_U16_BE(ptr,val) duk_raw_write_u16_be((ptr), (duk_uint16_t) (val))
2397 #define DUK_RAW_WRITE_U32_BE(ptr,val) duk_raw_write_u32_be((ptr), (duk_uint32_t) (val))
2398 #define DUK_RAW_WRITE_FLOAT_BE(ptr,val) duk_raw_write_float_be((ptr), (duk_float_t) (val))
2399 #define DUK_RAW_WRITE_DOUBLE_BE(ptr,val) duk_raw_write_double_be((ptr), (duk_double_t) (val))
2400 #define DUK_RAW_WRITE_XUTF8(ptr,val) duk_raw_write_xutf8((ptr), (duk_ucodepoint_t) (val))
2401 
2402 #define DUK_RAW_WRITEINC_U8(ptr,val)  do { \
2403 		*(ptr)++ = (duk_uint8_t) (val); \
2404 	} while (0)
2405 #define DUK_RAW_WRITEINC_U16_BE(ptr,val) duk_raw_writeinc_u16_be(&(ptr), (duk_uint16_t) (val))
2406 #define DUK_RAW_WRITEINC_U32_BE(ptr,val) duk_raw_writeinc_u32_be(&(ptr), (duk_uint32_t) (val))
2407 #define DUK_RAW_WRITEINC_FLOAT_BE(ptr,val) duk_raw_writeinc_float_be(&(ptr), (duk_float_t) (val))
2408 #define DUK_RAW_WRITEINC_DOUBLE_BE(ptr,val) duk_raw_writeinc_double_be(&(ptr), (duk_double_t) (val))
2409 #define DUK_RAW_WRITEINC_XUTF8(ptr,val) duk_raw_writeinc_xutf8(&(ptr), (duk_ucodepoint_t) (val))
2410 #define DUK_RAW_WRITEINC_CESU8(ptr,val) duk_raw_writeinc_cesu8(&(ptr), (duk_ucodepoint_t) (val))
2411 
2412 #define DUK_RAW_READ_U8(ptr) ((duk_uint8_t) (*(ptr)))
2413 #define DUK_RAW_READ_U16_BE(ptr) duk_raw_read_u16_be((ptr));
2414 #define DUK_RAW_READ_U32_BE(ptr) duk_raw_read_u32_be((ptr));
2415 #define DUK_RAW_READ_DOUBLE_BE(ptr) duk_raw_read_double_be((ptr));
2416 
2417 #define DUK_RAW_READINC_U8(ptr) ((duk_uint8_t) (*(ptr)++))
2418 #define DUK_RAW_READINC_U16_BE(ptr) duk_raw_readinc_u16_be(&(ptr));
2419 #define DUK_RAW_READINC_U32_BE(ptr) duk_raw_readinc_u32_be(&(ptr));
2420 #define DUK_RAW_READINC_DOUBLE_BE(ptr) duk_raw_readinc_double_be(&(ptr));
2421 
2422 /*
2423  *  Double and float byte order operations.
2424  */
2425 
2426 DUK_INTERNAL_DECL void duk_dblunion_host_to_little(duk_double_union *u);
2427 DUK_INTERNAL_DECL void duk_dblunion_little_to_host(duk_double_union *u);
2428 DUK_INTERNAL_DECL void duk_dblunion_host_to_big(duk_double_union *u);
2429 DUK_INTERNAL_DECL void duk_dblunion_big_to_host(duk_double_union *u);
2430 DUK_INTERNAL_DECL void duk_fltunion_host_to_big(duk_float_union *u);
2431 DUK_INTERNAL_DECL void duk_fltunion_big_to_host(duk_float_union *u);
2432 
2433 /*
2434  *  Buffer writer (dynamic buffer only)
2435  *
2436  *  Helper for writing to a dynamic buffer with a concept of a "slack" area
2437  *  to reduce resizes.  You can ensure there is enough space beforehand and
2438  *  then write for a while without further checks, relying on a stable data
2439  *  pointer.  Slack handling is automatic so call sites only indicate how
2440  *  much data they need right now.
2441  *
2442  *  There are several ways to write using bufwriter.  The best approach
2443  *  depends mainly on how much performance matters over code footprint.
2444  *  The key issues are (1) ensuring there is space and (2) keeping the
2445  *  pointers consistent.  Fast code should ensure space for multiple writes
2446  *  with one ensure call.  Fastest inner loop code can temporarily borrow
2447  *  the 'p' pointer but must write it back eventually.
2448  *
2449  *  Be careful to ensure all macro arguments (other than static pointers like
2450  *  'thr' and 'bw_ctx') are evaluated exactly once, using temporaries if
2451  *  necessary (if that's not possible, there should be a note near the macro).
2452  *  Buffer write arguments often contain arithmetic etc so this is
2453  *  particularly important here.
2454  */
2455 
2456 /* XXX: Migrate bufwriter and other read/write helpers to its own header? */
2457 
2458 struct duk_bufwriter_ctx {
2459 	duk_uint8_t *p;
2460 	duk_uint8_t *p_base;
2461 	duk_uint8_t *p_limit;
2462 	duk_hbuffer_dynamic *buf;
2463 };
2464 
2465 #if defined(DUK_USE_PREFER_SIZE)
2466 #define DUK_BW_SLACK_ADD           64
2467 #define DUK_BW_SLACK_SHIFT         4    /* 2^4 -> 1/16 = 6.25% slack */
2468 #else
2469 #define DUK_BW_SLACK_ADD           64
2470 #define DUK_BW_SLACK_SHIFT         2    /* 2^2 -> 1/4 = 25% slack */
2471 #endif
2472 
2473 /* Initialization and finalization (compaction), converting to other types. */
2474 
2475 #define DUK_BW_INIT_PUSHBUF(thr,bw_ctx,sz) do { \
2476 		duk_bw_init_pushbuf((thr), (bw_ctx), (sz)); \
2477 	} while (0)
2478 #define DUK_BW_INIT_WITHBUF(thr,bw_ctx,buf) do { \
2479 		duk_bw_init((thr), (bw_ctx), (buf)); \
2480 	} while (0)
2481 #define DUK_BW_COMPACT(thr,bw_ctx) do { \
2482 		/* Make underlying buffer compact to match DUK_BW_GET_SIZE(). */ \
2483 		duk_bw_compact((thr), (bw_ctx)); \
2484 	} while (0)
2485 #define DUK_BW_PUSH_AS_STRING(thr,bw_ctx) do { \
2486 		duk_push_lstring((thr), \
2487 		                 (const char *) (bw_ctx)->p_base, \
2488 		                 (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
2489 	} while (0)
2490 
2491 /* Pointers may be NULL for a while when 'buf' size is zero and before any
2492  * ENSURE calls have been made.  Once an ENSURE has been made, the pointers
2493  * are required to be non-NULL so that it's always valid to use memcpy() and
2494  * memmove(), even for zero size.
2495  */
2496 #if defined(DUK_USE_ASSERTIONS)
2497 DUK_INTERNAL_DECL void duk_bw_assert_valid(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx);
2498 #define DUK_BW_ASSERT_VALID_EXPR(thr,bw_ctx)  (duk_bw_assert_valid((thr), (bw_ctx)))
2499 #define DUK_BW_ASSERT_VALID(thr,bw_ctx)  do { duk_bw_assert_valid((thr), (bw_ctx)); } while (0)
2500 #else
2501 #define DUK_BW_ASSERT_VALID_EXPR(thr,bw_ctx)  DUK_ASSERT_EXPR(1)
2502 #define DUK_BW_ASSERT_VALID(thr,bw_ctx)  do {} while (0)
2503 #endif
2504 
2505 /* Working with the pointer and current size. */
2506 
2507 #define DUK_BW_GET_PTR(thr,bw_ctx) \
2508 	((bw_ctx)->p)
2509 #define DUK_BW_SET_PTR(thr,bw_ctx,ptr) do { \
2510 		(bw_ctx)->p = (ptr); \
2511 	} while (0)
2512 #define DUK_BW_ADD_PTR(thr,bw_ctx,delta) do { \
2513 		(bw_ctx)->p += (delta); \
2514 	} while (0)
2515 #define DUK_BW_GET_BASEPTR(thr,bw_ctx) \
2516 	((bw_ctx)->p_base)
2517 #define DUK_BW_GET_LIMITPTR(thr,bw_ctx) \
2518 	((bw_ctx)->p_limit)
2519 #define DUK_BW_GET_SIZE(thr,bw_ctx) \
2520 	((duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base))
2521 #define DUK_BW_SET_SIZE(thr,bw_ctx,sz) do { \
2522 		DUK_ASSERT((duk_size_t) (sz) <= (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
2523 		(bw_ctx)->p = (bw_ctx)->p_base + (sz); \
2524 	} while (0)
2525 #define DUK_BW_RESET_SIZE(thr,bw_ctx) do { \
2526 		/* Reset to zero size, keep current limit. */ \
2527 		(bw_ctx)->p = (bw_ctx)->p_base; \
2528 	} while (0)
2529 #define DUK_BW_GET_BUFFER(thr,bw_ctx) \
2530 	((bw_ctx)->buf)
2531 
2532 /* Ensuring (reserving) space. */
2533 
2534 #define DUK_BW_ENSURE(thr,bw_ctx,sz) do { \
2535 		duk_size_t duk__sz, duk__space; \
2536 		DUK_BW_ASSERT_VALID((thr), (bw_ctx)); \
2537 		duk__sz = (sz); \
2538 		duk__space = (duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p); \
2539 		if (duk__space < duk__sz) { \
2540 			(void) duk_bw_resize((thr), (bw_ctx), duk__sz); \
2541 		} \
2542 	} while (0)
2543 /* NOTE: Multiple evaluation of 'ptr' in this macro. */
2544 /* XXX: Rework to use an always-inline function? */
2545 #define DUK_BW_ENSURE_RAW(thr,bw_ctx,sz,ptr) \
2546 	(((duk_size_t) ((bw_ctx)->p_limit - (ptr)) >= (sz)) ? \
2547 	 (ptr) : \
2548 	 ((bw_ctx)->p = (ptr), duk_bw_resize((thr),(bw_ctx),(sz))))
2549 #define DUK_BW_ENSURE_GETPTR(thr,bw_ctx,sz) \
2550 	DUK_BW_ENSURE_RAW((thr), (bw_ctx), (sz), (bw_ctx)->p)
2551 #define DUK_BW_ASSERT_SPACE_EXPR(thr,bw_ctx,sz) \
2552 	(DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)), \
2553 	 DUK_ASSERT_EXPR((duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p) >= (duk_size_t) (sz)))
2554 #define DUK_BW_ASSERT_SPACE(thr,bw_ctx,sz) do { \
2555 		DUK_BW_ASSERT_SPACE_EXPR((thr), (bw_ctx), (sz)); \
2556 	} while (0)
2557 
2558 /* Miscellaneous. */
2559 
2560 #define DUK_BW_SETPTR_AND_COMPACT(thr,bw_ctx,ptr) do { \
2561 		(bw_ctx)->p = (ptr); \
2562 		duk_bw_compact((thr), (bw_ctx)); \
2563 	} while (0)
2564 
2565 /* Fast write calls which assume you control the slack beforehand.
2566  * Multibyte write variants exist and use a temporary write pointer
2567  * because byte writes alias with anything: with a stored pointer
2568  * explicit pointer load/stores get generated (e.g. gcc -Os).
2569  */
2570 
2571 #define DUK_BW_WRITE_RAW_U8(thr,bw_ctx,val) do { \
2572 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 1); \
2573 		*(bw_ctx)->p++ = (duk_uint8_t) (val); \
2574 	} while (0)
2575 #define DUK_BW_WRITE_RAW_U8_2(thr,bw_ctx,val1,val2) do { \
2576 		duk_uint8_t *duk__p; \
2577 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 2); \
2578 		duk__p = (bw_ctx)->p; \
2579 		*duk__p++ = (duk_uint8_t) (val1); \
2580 		*duk__p++ = (duk_uint8_t) (val2); \
2581 		(bw_ctx)->p = duk__p; \
2582 	} while (0)
2583 #define DUK_BW_WRITE_RAW_U8_3(thr,bw_ctx,val1,val2,val3) do { \
2584 		duk_uint8_t *duk__p; \
2585 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 3); \
2586 		duk__p = (bw_ctx)->p; \
2587 		*duk__p++ = (duk_uint8_t) (val1); \
2588 		*duk__p++ = (duk_uint8_t) (val2); \
2589 		*duk__p++ = (duk_uint8_t) (val3); \
2590 		(bw_ctx)->p = duk__p; \
2591 	} while (0)
2592 #define DUK_BW_WRITE_RAW_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \
2593 		duk_uint8_t *duk__p; \
2594 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 4); \
2595 		duk__p = (bw_ctx)->p; \
2596 		*duk__p++ = (duk_uint8_t) (val1); \
2597 		*duk__p++ = (duk_uint8_t) (val2); \
2598 		*duk__p++ = (duk_uint8_t) (val3); \
2599 		*duk__p++ = (duk_uint8_t) (val4); \
2600 		(bw_ctx)->p = duk__p; \
2601 	} while (0)
2602 #define DUK_BW_WRITE_RAW_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \
2603 		duk_uint8_t *duk__p; \
2604 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 5); \
2605 		duk__p = (bw_ctx)->p; \
2606 		*duk__p++ = (duk_uint8_t) (val1); \
2607 		*duk__p++ = (duk_uint8_t) (val2); \
2608 		*duk__p++ = (duk_uint8_t) (val3); \
2609 		*duk__p++ = (duk_uint8_t) (val4); \
2610 		*duk__p++ = (duk_uint8_t) (val5); \
2611 		(bw_ctx)->p = duk__p; \
2612 	} while (0)
2613 #define DUK_BW_WRITE_RAW_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \
2614 		duk_uint8_t *duk__p; \
2615 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 6); \
2616 		duk__p = (bw_ctx)->p; \
2617 		*duk__p++ = (duk_uint8_t) (val1); \
2618 		*duk__p++ = (duk_uint8_t) (val2); \
2619 		*duk__p++ = (duk_uint8_t) (val3); \
2620 		*duk__p++ = (duk_uint8_t) (val4); \
2621 		*duk__p++ = (duk_uint8_t) (val5); \
2622 		*duk__p++ = (duk_uint8_t) (val6); \
2623 		(bw_ctx)->p = duk__p; \
2624 	} while (0)
2625 #define DUK_BW_WRITE_RAW_XUTF8(thr,bw_ctx,cp) do { \
2626 		duk_ucodepoint_t duk__cp; \
2627 		duk_small_int_t duk__enc_len; \
2628 		duk__cp = (duk_ucodepoint_t) (cp); \
2629 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_xutf8_length(duk__cp)); \
2630 		duk__enc_len = duk_unicode_encode_xutf8(duk__cp, (bw_ctx)->p); \
2631 		(bw_ctx)->p += duk__enc_len; \
2632 	} while (0)
2633 #define DUK_BW_WRITE_RAW_CESU8(thr,bw_ctx,cp) do { \
2634 		duk_ucodepoint_t duk__cp; \
2635 		duk_small_int_t duk__enc_len; \
2636 		duk__cp = (duk_ucodepoint_t) (cp); \
2637 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_cesu8_length(duk__cp)); \
2638 		duk__enc_len = duk_unicode_encode_cesu8(duk__cp, (bw_ctx)->p); \
2639 		(bw_ctx)->p += duk__enc_len; \
2640 	} while (0)
2641 /* XXX: add temporary duk__p pointer here too; sharing */
2642 /* XXX: avoid unsafe variants */
2643 #define DUK_BW_WRITE_RAW_BYTES(thr,bw_ctx,valptr,valsz) do { \
2644 		const void *duk__valptr; \
2645 		duk_size_t duk__valsz; \
2646 		duk__valptr = (const void *) (valptr); \
2647 		duk__valsz = (duk_size_t) (valsz); \
2648 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
2649 		(bw_ctx)->p += duk__valsz; \
2650 	} while (0)
2651 #define DUK_BW_WRITE_RAW_CSTRING(thr,bw_ctx,val) do { \
2652 		const duk_uint8_t *duk__val; \
2653 		duk_size_t duk__val_len; \
2654 		duk__val = (const duk_uint8_t *) (val); \
2655 		duk__val_len = DUK_STRLEN((const char *) duk__val); \
2656 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
2657 		(bw_ctx)->p += duk__val_len; \
2658 	} while (0)
2659 #define DUK_BW_WRITE_RAW_HSTRING(thr,bw_ctx,val) do { \
2660 		duk_size_t duk__val_len; \
2661 		duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
2662 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
2663 		(bw_ctx)->p += duk__val_len; \
2664 	} while (0)
2665 #define DUK_BW_WRITE_RAW_HBUFFER(thr,bw_ctx,val) do { \
2666 		duk_size_t duk__val_len; \
2667 		duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
2668 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2669 		(bw_ctx)->p += duk__val_len; \
2670 	} while (0)
2671 #define DUK_BW_WRITE_RAW_HBUFFER_FIXED(thr,bw_ctx,val) do { \
2672 		duk_size_t duk__val_len; \
2673 		duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
2674 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2675 		(bw_ctx)->p += duk__val_len; \
2676 	} while (0)
2677 #define DUK_BW_WRITE_RAW_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \
2678 		duk_size_t duk__val_len; \
2679 		duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
2680 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2681 		(bw_ctx)->p += duk__val_len; \
2682 	} while (0)
2683 
2684 /* Append bytes from a slice already in the buffer. */
2685 #define DUK_BW_WRITE_RAW_SLICE(thr,bw,dst_off,dst_len) \
2686 	duk_bw_write_raw_slice((thr), (bw), (dst_off), (dst_len))
2687 
2688 /* Insert bytes in the middle of the buffer from an external buffer. */
2689 #define DUK_BW_INSERT_RAW_BYTES(thr,bw,dst_off,buf,len) \
2690 	duk_bw_insert_raw_bytes((thr), (bw), (dst_off), (buf), (len))
2691 
2692 /* Insert bytes in the middle of the buffer from a slice already
2693  * in the buffer.  Source offset is interpreted "before" the operation.
2694  */
2695 #define DUK_BW_INSERT_RAW_SLICE(thr,bw,dst_off,src_off,len) \
2696 	duk_bw_insert_raw_slice((thr), (bw), (dst_off), (src_off), (len))
2697 
2698 /* Insert a reserved area somewhere in the buffer; caller fills it.
2699  * Evaluates to a (duk_uint_t *) pointing to the start of the reserved
2700  * area for convenience.
2701  */
2702 #define DUK_BW_INSERT_RAW_AREA(thr,bw,off,len) \
2703 	duk_bw_insert_raw_area((thr), (bw), (off), (len))
2704 
2705 /* Remove a slice from inside buffer. */
2706 #define DUK_BW_REMOVE_RAW_SLICE(thr,bw,off,len) \
2707 	duk_bw_remove_raw_slice((thr), (bw), (off), (len))
2708 
2709 /* Safe write calls which will ensure space first. */
2710 
2711 #define DUK_BW_WRITE_ENSURE_U8(thr,bw_ctx,val) do { \
2712 		DUK_BW_ENSURE((thr), (bw_ctx), 1); \
2713 		DUK_BW_WRITE_RAW_U8((thr), (bw_ctx), (val)); \
2714 	} while (0)
2715 #define DUK_BW_WRITE_ENSURE_U8_2(thr,bw_ctx,val1,val2) do { \
2716 		DUK_BW_ENSURE((thr), (bw_ctx), 2); \
2717 		DUK_BW_WRITE_RAW_U8_2((thr), (bw_ctx), (val1), (val2)); \
2718 	} while (0)
2719 #define DUK_BW_WRITE_ENSURE_U8_3(thr,bw_ctx,val1,val2,val3) do { \
2720 		DUK_BW_ENSURE((thr), (bw_ctx), 3); \
2721 		DUK_BW_WRITE_RAW_U8_3((thr), (bw_ctx), (val1), (val2), (val3)); \
2722 	} while (0)
2723 #define DUK_BW_WRITE_ENSURE_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \
2724 		DUK_BW_ENSURE((thr), (bw_ctx), 4); \
2725 		DUK_BW_WRITE_RAW_U8_4((thr), (bw_ctx), (val1), (val2), (val3), (val4)); \
2726 	} while (0)
2727 #define DUK_BW_WRITE_ENSURE_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \
2728 		DUK_BW_ENSURE((thr), (bw_ctx), 5); \
2729 		DUK_BW_WRITE_RAW_U8_5((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5)); \
2730 	} while (0)
2731 #define DUK_BW_WRITE_ENSURE_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \
2732 		DUK_BW_ENSURE((thr), (bw_ctx), 6); \
2733 		DUK_BW_WRITE_RAW_U8_6((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5), (val6)); \
2734 	} while (0)
2735 #define DUK_BW_WRITE_ENSURE_XUTF8(thr,bw_ctx,cp) do { \
2736 		DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_XUTF8_LENGTH); \
2737 		DUK_BW_WRITE_RAW_XUTF8((thr), (bw_ctx), (cp)); \
2738 	} while (0)
2739 #define DUK_BW_WRITE_ENSURE_CESU8(thr,bw_ctx,cp) do { \
2740 		DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_CESU8_LENGTH); \
2741 		DUK_BW_WRITE_RAW_CESU8((thr), (bw_ctx), (cp)); \
2742 	} while (0)
2743 /* XXX: add temporary duk__p pointer here too; sharing */
2744 /* XXX: avoid unsafe */
2745 #define DUK_BW_WRITE_ENSURE_BYTES(thr,bw_ctx,valptr,valsz) do { \
2746 		const void *duk__valptr; \
2747 		duk_size_t duk__valsz; \
2748 		duk__valptr = (const void *) (valptr); \
2749 		duk__valsz = (duk_size_t) (valsz); \
2750 		DUK_BW_ENSURE((thr), (bw_ctx), duk__valsz); \
2751 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
2752 		(bw_ctx)->p += duk__valsz; \
2753 	} while (0)
2754 #define DUK_BW_WRITE_ENSURE_CSTRING(thr,bw_ctx,val) do { \
2755 		const duk_uint8_t *duk__val; \
2756 		duk_size_t duk__val_len; \
2757 		duk__val = (const duk_uint8_t *) (val); \
2758 		duk__val_len = DUK_STRLEN((const char *) duk__val); \
2759 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2760 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
2761 		(bw_ctx)->p += duk__val_len; \
2762 	} while (0)
2763 #define DUK_BW_WRITE_ENSURE_HSTRING(thr,bw_ctx,val) do { \
2764 		duk_size_t duk__val_len; \
2765 		duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
2766 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2767 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
2768 		(bw_ctx)->p += duk__val_len; \
2769 	} while (0)
2770 #define DUK_BW_WRITE_ENSURE_HBUFFER(thr,bw_ctx,val) do { \
2771 		duk_size_t duk__val_len; \
2772 		duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
2773 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2774 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2775 		(bw_ctx)->p += duk__val_len; \
2776 	} while (0)
2777 #define DUK_BW_WRITE_ENSURE_HBUFFER_FIXED(thr,bw_ctx,val) do { \
2778 		duk_size_t duk__val_len; \
2779 		duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
2780 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2781 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2782 		(bw_ctx)->p += duk__val_len; \
2783 	} while (0)
2784 #define DUK_BW_WRITE_ENSURE_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \
2785 		duk_size_t duk__val_len; \
2786 		duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
2787 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2788 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2789 		(bw_ctx)->p += duk__val_len; \
2790 	} while (0)
2791 
2792 #define DUK_BW_WRITE_ENSURE_SLICE(thr,bw,dst_off,dst_len) \
2793 	duk_bw_write_ensure_slice((thr), (bw), (dst_off), (dst_len))
2794 #define DUK_BW_INSERT_ENSURE_BYTES(thr,bw,dst_off,buf,len) \
2795 	duk_bw_insert_ensure_bytes((thr), (bw), (dst_off), (buf), (len))
2796 #define DUK_BW_INSERT_ENSURE_SLICE(thr,bw,dst_off,src_off,len) \
2797 	duk_bw_insert_ensure_slice((thr), (bw), (dst_off), (src_off), (len))
2798 #define DUK_BW_INSERT_ENSURE_AREA(thr,bw,off,len) \
2799 	/* Evaluates to (duk_uint8_t *) pointing to start of area. */ \
2800 	duk_bw_insert_ensure_area((thr), (bw), (off), (len))
2801 #define DUK_BW_REMOVE_ENSURE_SLICE(thr,bw,off,len) \
2802 	/* No difference between raw/ensure because the buffer shrinks. */ \
2803 	DUK_BW_REMOVE_RAW_SLICE((thr), (bw), (off), (len))
2804 
2805 /*
2806  *  Externs and prototypes
2807  */
2808 
2809 #if !defined(DUK_SINGLE_FILE)
2810 DUK_INTERNAL_DECL const duk_uint8_t duk_lc_digits[36];
2811 DUK_INTERNAL_DECL const duk_uint8_t duk_uc_nybbles[16];
2812 DUK_INTERNAL_DECL const duk_int8_t duk_hex_dectab[256];
2813 #if defined(DUK_USE_HEX_FASTPATH)
2814 DUK_INTERNAL_DECL const duk_int16_t duk_hex_dectab_shift4[256];
2815 DUK_INTERNAL_DECL const duk_uint16_t duk_hex_enctab[256];
2816 #endif
2817 #endif  /* !DUK_SINGLE_FILE */
2818 
2819 /* Note: assumes that duk_util_probe_steps size is 32 */
2820 #if defined(DUK_USE_HOBJECT_HASH_PART)
2821 #if !defined(DUK_SINGLE_FILE)
2822 DUK_INTERNAL_DECL duk_uint8_t duk_util_probe_steps[32];
2823 #endif  /* !DUK_SINGLE_FILE */
2824 #endif
2825 
2826 #if defined(DUK_USE_STRHASH_DENSE)
2827 DUK_INTERNAL_DECL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed);
2828 #endif
2829 
2830 DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits);
2831 DUK_INTERNAL_DECL duk_small_uint_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx);
2832 DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_uint32_t def_value);
2833 DUK_INTERNAL_DECL duk_int32_t duk_bd_decode_flagged_signed(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value);
2834 DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode_varuint(duk_bitdecoder_ctx *ctx);
2835 DUK_INTERNAL_DECL duk_small_uint_t duk_bd_decode_bitpacked_string(duk_bitdecoder_ctx *bd, duk_uint8_t *out);
2836 
2837 DUK_INTERNAL_DECL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits);
2838 DUK_INTERNAL_DECL void duk_be_finish(duk_bitencoder_ctx *ctx);
2839 
2840 #if !defined(DUK_USE_GET_RANDOM_DOUBLE)
2841 DUK_INTERNAL_DECL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr);
2842 DUK_INTERNAL_DECL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr);
2843 #endif
2844 
2845 DUK_INTERNAL_DECL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf);
2846 DUK_INTERNAL_DECL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size);
2847 DUK_INTERNAL_DECL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz);
2848 DUK_INTERNAL_DECL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx);
2849 DUK_INTERNAL_DECL void duk_bw_write_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len);
2850 DUK_INTERNAL_DECL void duk_bw_write_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len);
2851 DUK_INTERNAL_DECL void duk_bw_insert_raw_bytes(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, const duk_uint8_t *buf, duk_size_t len);
2852 DUK_INTERNAL_DECL void duk_bw_insert_ensure_bytes(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, const duk_uint8_t *buf, duk_size_t len);
2853 DUK_INTERNAL_DECL void duk_bw_insert_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, duk_size_t src_off, duk_size_t len);
2854 DUK_INTERNAL_DECL void duk_bw_insert_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, duk_size_t src_off, duk_size_t len);
2855 DUK_INTERNAL_DECL duk_uint8_t *duk_bw_insert_raw_area(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len);
2856 DUK_INTERNAL_DECL duk_uint8_t *duk_bw_insert_ensure_area(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len);
2857 DUK_INTERNAL_DECL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len);
2858 /* No duk_bw_remove_ensure_slice(), functionality would be identical. */
2859 
2860 DUK_INTERNAL_DECL duk_uint16_t duk_raw_read_u16_be(const duk_uint8_t *p);
2861 DUK_INTERNAL_DECL duk_uint32_t duk_raw_read_u32_be(const duk_uint8_t *p);
2862 DUK_INTERNAL_DECL duk_float_t duk_raw_read_float_be(const duk_uint8_t *p);
2863 DUK_INTERNAL_DECL duk_double_t duk_raw_read_double_be(const duk_uint8_t *p);
2864 DUK_INTERNAL_DECL duk_uint16_t duk_raw_readinc_u16_be(const duk_uint8_t **p);
2865 DUK_INTERNAL_DECL duk_uint32_t duk_raw_readinc_u32_be(const duk_uint8_t **p);
2866 DUK_INTERNAL_DECL duk_float_t duk_raw_readinc_float_be(const duk_uint8_t **p);
2867 DUK_INTERNAL_DECL duk_double_t duk_raw_readinc_double_be(const duk_uint8_t **p);
2868 DUK_INTERNAL_DECL void duk_raw_write_u16_be(duk_uint8_t *p, duk_uint16_t val);
2869 DUK_INTERNAL_DECL void duk_raw_write_u32_be(duk_uint8_t *p, duk_uint32_t val);
2870 DUK_INTERNAL_DECL void duk_raw_write_float_be(duk_uint8_t *p, duk_float_t val);
2871 DUK_INTERNAL_DECL void duk_raw_write_double_be(duk_uint8_t *p, duk_double_t val);
2872 DUK_INTERNAL_DECL duk_small_int_t duk_raw_write_xutf8(duk_uint8_t *p, duk_ucodepoint_t val);
2873 DUK_INTERNAL_DECL duk_small_int_t duk_raw_write_cesu8(duk_uint8_t *p, duk_ucodepoint_t val);
2874 DUK_INTERNAL_DECL void duk_raw_writeinc_u16_be(duk_uint8_t **p, duk_uint16_t val);
2875 DUK_INTERNAL_DECL void duk_raw_writeinc_u32_be(duk_uint8_t **p, duk_uint32_t val);
2876 DUK_INTERNAL_DECL void duk_raw_writeinc_float_be(duk_uint8_t **p, duk_float_t val);
2877 DUK_INTERNAL_DECL void duk_raw_writeinc_double_be(duk_uint8_t **p, duk_double_t val);
2878 DUK_INTERNAL_DECL void duk_raw_writeinc_xutf8(duk_uint8_t **p, duk_ucodepoint_t val);
2879 DUK_INTERNAL_DECL void duk_raw_writeinc_cesu8(duk_uint8_t **p, duk_ucodepoint_t val);
2880 
2881 #if defined(DUK_USE_DEBUGGER_SUPPORT)  /* For now only needed by the debugger. */
2882 DUK_INTERNAL_DECL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len);
2883 #endif
2884 
2885 /* memcpy(), memmove() etc wrappers.  The plain variants like duk_memcpy()
2886  * assume C99+ and 'src' and 'dst' pointers must be non-NULL even when the
2887  * operation size is zero.  The unsafe variants like duk_memcpy_safe() deal
2888  * with the zero size case explicitly, and allow NULL pointers in that case
2889  * (which is undefined behavior in C99+).  For the majority of actual targets
2890  * a NULL pointer with a zero length is fine in practice.  These wrappers are
2891  * macros to force inlining; because there are hundreds of call sites, even a
2892  * few extra bytes per call site adds up to ~1kB footprint.
2893  */
2894 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
2895 #define duk_memcpy(dst,src,len)  do { \
2896 		void *duk__dst = (dst); \
2897 		const void *duk__src = (src); \
2898 		duk_size_t duk__len = (len); \
2899 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2900 		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
2901 		(void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \
2902 	} while (0)
2903 #define duk_memcpy_unsafe(dst,src,len)  duk_memcpy((dst), (src), (len))
2904 #define duk_memmove(dst,src,len)  do { \
2905 		void *duk__dst = (dst); \
2906 		const void *duk__src = (src); \
2907 		duk_size_t duk__len = (len); \
2908 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2909 		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
2910 		(void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \
2911 	} while (0)
2912 #define duk_memmove_unsafe(dst,src,len)  duk_memmove((dst), (src), (len))
2913 #define duk_memset(dst,val,len)  do { \
2914 		void *duk__dst = (dst); \
2915 		duk_small_int_t duk__val = (val); \
2916 		duk_size_t duk__len = (len); \
2917 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2918 		(void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \
2919 	} while (0)
2920 #define duk_memset_unsafe(dst,val,len)  duk_memset((dst), (val), (len))
2921 #define duk_memzero(dst,len)  do { \
2922 		void *duk__dst = (dst); \
2923 		duk_size_t duk__len = (len); \
2924 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2925 		(void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \
2926 	} while (0)
2927 #define duk_memzero_unsafe(dst,len)  duk_memzero((dst), (len))
2928 #else  /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
2929 #define duk_memcpy(dst,src,len)  do { \
2930 		void *duk__dst = (dst); \
2931 		const void *duk__src = (src); \
2932 		duk_size_t duk__len = (len); \
2933 		DUK_ASSERT(duk__dst != NULL); \
2934 		DUK_ASSERT(duk__src != NULL); \
2935 		(void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \
2936 	} while (0)
2937 #define duk_memcpy_unsafe(dst,src,len)  do { \
2938 		void *duk__dst = (dst); \
2939 		const void *duk__src = (src); \
2940 		duk_size_t duk__len = (len); \
2941 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2942 		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
2943 		if (DUK_LIKELY(duk__len > 0U)) { \
2944 			DUK_ASSERT(duk__dst != NULL); \
2945 			DUK_ASSERT(duk__src != NULL); \
2946 			(void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \
2947 		} \
2948 	} while (0)
2949 #define duk_memmove(dst,src,len)  do { \
2950 		void *duk__dst = (dst); \
2951 		const void *duk__src = (src); \
2952 		duk_size_t duk__len = (len); \
2953 		DUK_ASSERT(duk__dst != NULL); \
2954 		DUK_ASSERT(duk__src != NULL); \
2955 		(void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \
2956 	} while (0)
2957 #define duk_memmove_unsafe(dst,src,len)  do { \
2958 		void *duk__dst = (dst); \
2959 		const void *duk__src = (src); \
2960 		duk_size_t duk__len = (len); \
2961 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2962 		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
2963 		if (DUK_LIKELY(duk__len > 0U)) { \
2964 			DUK_ASSERT(duk__dst != NULL); \
2965 			DUK_ASSERT(duk__src != NULL); \
2966 			(void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \
2967 		} \
2968 	} while (0)
2969 #define duk_memset(dst,val,len)  do { \
2970 		void *duk__dst = (dst); \
2971 		duk_small_int_t duk__val = (val); \
2972 		duk_size_t duk__len = (len); \
2973 		DUK_ASSERT(duk__dst != NULL); \
2974 		(void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \
2975 	} while (0)
2976 #define duk_memset_unsafe(dst,val,len)  do { \
2977 		void *duk__dst = (dst); \
2978 		duk_small_int_t duk__val = (val); \
2979 		duk_size_t duk__len = (len); \
2980 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2981 		if (DUK_LIKELY(duk__len > 0U)) { \
2982 			DUK_ASSERT(duk__dst != NULL); \
2983 			(void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \
2984 		} \
2985 	} while (0)
2986 #define duk_memzero(dst,len)  do { \
2987 		void *duk__dst = (dst); \
2988 		duk_size_t duk__len = (len); \
2989 		DUK_ASSERT(duk__dst != NULL); \
2990 		(void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \
2991 	} while (0)
2992 #define duk_memzero_unsafe(dst,len)  do { \
2993 		void *duk__dst = (dst); \
2994 		duk_size_t duk__len = (len); \
2995 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2996 		if (DUK_LIKELY(duk__len > 0U)) { \
2997 			DUK_ASSERT(duk__dst != NULL); \
2998 			(void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \
2999 		} \
3000 	} while (0)
3001 #endif  /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
3002 
3003 DUK_INTERNAL_DECL duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len);
3004 DUK_INTERNAL_DECL duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len);
3005 
3006 DUK_INTERNAL_DECL duk_bool_t duk_is_whole_get_int32_nonegzero(duk_double_t x, duk_int32_t *ival);
3007 DUK_INTERNAL_DECL duk_bool_t duk_is_whole_get_int32(duk_double_t x, duk_int32_t *ival);
3008 DUK_INTERNAL_DECL duk_bool_t duk_double_is_anyinf(duk_double_t x);
3009 DUK_INTERNAL_DECL duk_bool_t duk_double_is_posinf(duk_double_t x);
3010 DUK_INTERNAL_DECL duk_bool_t duk_double_is_neginf(duk_double_t x);
3011 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan(duk_double_t x);
3012 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_or_zero(duk_double_t x);
3013 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_or_inf(duk_double_t x);
3014 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_zero_inf(duk_double_t x);
3015 DUK_INTERNAL_DECL duk_small_uint_t duk_double_signbit(duk_double_t x);
3016 DUK_INTERNAL_DECL duk_double_t duk_double_trunc_towards_zero(duk_double_t x);
3017 DUK_INTERNAL_DECL duk_bool_t duk_double_same_sign(duk_double_t x, duk_double_t y);
3018 DUK_INTERNAL_DECL duk_double_t duk_double_fmin(duk_double_t x, duk_double_t y);
3019 DUK_INTERNAL_DECL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y);
3020 DUK_INTERNAL_DECL duk_bool_t duk_double_is_finite(duk_double_t x);
3021 DUK_INTERNAL_DECL duk_bool_t duk_double_is_integer(duk_double_t x);
3022 DUK_INTERNAL_DECL duk_bool_t duk_double_is_safe_integer(duk_double_t x);
3023 
3024 DUK_INTERNAL_DECL duk_double_t duk_double_div(duk_double_t x, duk_double_t y);
3025 DUK_INTERNAL_DECL duk_int_t duk_double_to_int_t(duk_double_t x);
3026 DUK_INTERNAL_DECL duk_uint_t duk_double_to_uint_t(duk_double_t x);
3027 DUK_INTERNAL_DECL duk_int32_t duk_double_to_int32_t(duk_double_t x);
3028 DUK_INTERNAL_DECL duk_uint32_t duk_double_to_uint32_t(duk_double_t x);
3029 DUK_INTERNAL_DECL duk_float_t duk_double_to_float_t(duk_double_t x);
3030 DUK_INTERNAL_DECL duk_bool_t duk_double_equals(duk_double_t x, duk_double_t y);
3031 DUK_INTERNAL_DECL duk_bool_t duk_float_equals(duk_float_t x, duk_float_t y);
3032 
3033 /*
3034  *  Miscellaneous
3035  */
3036 
3037 /* Example: x     = 0x10 = 0b00010000
3038  *          x - 1 = 0x0f = 0b00001111
3039  *          x & (x - 1) == 0
3040  *
3041  *          x     = 0x07 = 0b00000111
3042  *          x - 1 = 0x06 = 0b00000110
3043  *          x & (x - 1) != 0
3044  *
3045  * However, incorrectly true for x == 0 so check for that explicitly.
3046  */
3047 #define DUK_IS_POWER_OF_TWO(x) \
3048 	((x) != 0U && ((x) & ((x) - 1U)) == 0U)
3049 
3050 #endif  /* DUK_UTIL_H_INCLUDED */
3051 /* #include duk_strings.h */
3052 /*
3053  *  Shared string macros.
3054  *
3055  *  Using shared macros helps minimize strings data size because it's easy
3056  *  to check if an existing string could be used.  String constants don't
3057  *  need to be all defined here; defining a string here makes sense if there's
3058  *  a high chance the string could be reused.  Also, using macros allows
3059  *  a call site express the exact string needed, but the macro may map to an
3060  *  approximate string to reduce unique string count.  Macros can also be
3061  *  more easily tuned for low memory targets than #if defined()s throughout
3062  *  the code base.
3063  *
3064  *  Because format strings behave differently in the call site (they need to
3065  *  be followed by format arguments), they use a special prefix DUK_STR_FMT_.
3066  *
3067  *  On some compilers using explicit shared strings is preferable; on others
3068  *  it may be better to use straight literals because the compiler will combine
3069  *  them anyway, and such strings won't end up unnecessarily in a symbol table.
3070  */
3071 
3072 #if !defined(DUK_ERRMSG_H_INCLUDED)
3073 #define DUK_ERRMSG_H_INCLUDED
3074 
3075 /* Mostly API and built-in method related */
3076 #define DUK_STR_INTERNAL_ERROR                   "internal error"
3077 #define DUK_STR_UNSUPPORTED                      "unsupported"
3078 #define DUK_STR_INVALID_COUNT                    "invalid count"
3079 #define DUK_STR_INVALID_ARGS                     "invalid args"
3080 #define DUK_STR_INVALID_STATE                    "invalid state"
3081 #define DUK_STR_INVALID_INPUT                    "invalid input"
3082 #define DUK_STR_INVALID_LENGTH                   "invalid length"
3083 #define DUK_STR_NOT_CONSTRUCTABLE                "not constructable"
3084 #define DUK_STR_CONSTRUCT_ONLY                   "constructor requires 'new'"
3085 #define DUK_STR_NOT_CALLABLE                     "not callable"
3086 #define DUK_STR_NOT_EXTENSIBLE                   "not extensible"
3087 #define DUK_STR_NOT_WRITABLE                     "not writable"
3088 #define DUK_STR_NOT_CONFIGURABLE                 "not configurable"
3089 #define DUK_STR_INVALID_CONTEXT                  "invalid context"
3090 #define DUK_STR_INVALID_INDEX                    "invalid args"
3091 #define DUK_STR_PUSH_BEYOND_ALLOC_STACK          "cannot push beyond allocated stack"
3092 #define DUK_STR_NOT_UNDEFINED                    "unexpected type"
3093 #define DUK_STR_NOT_NULL                         "unexpected type"
3094 #define DUK_STR_NOT_BOOLEAN                      "unexpected type"
3095 #define DUK_STR_NOT_NUMBER                       "unexpected type"
3096 #define DUK_STR_NOT_STRING                       "unexpected type"
3097 #define DUK_STR_NOT_OBJECT                       "unexpected type"
3098 #define DUK_STR_NOT_POINTER                      "unexpected type"
3099 #define DUK_STR_NOT_BUFFER                       "not buffer"  /* still in use with verbose messages */
3100 #define DUK_STR_UNEXPECTED_TYPE                  "unexpected type"
3101 #define DUK_STR_NOT_THREAD                       "unexpected type"
3102 #define DUK_STR_NOT_COMPFUNC                     "unexpected type"
3103 #define DUK_STR_NOT_NATFUNC                      "unexpected type"
3104 #define DUK_STR_NOT_C_FUNCTION                   "unexpected type"
3105 #define DUK_STR_NOT_FUNCTION                     "unexpected type"
3106 #define DUK_STR_NOT_REGEXP                       "unexpected type"
3107 #define DUK_STR_TOPRIMITIVE_FAILED               "coercion to primitive failed"
3108 #define DUK_STR_NUMBER_OUTSIDE_RANGE             "number outside range"
3109 #define DUK_STR_NOT_OBJECT_COERCIBLE             "not object coercible"
3110 #define DUK_STR_CANNOT_NUMBER_COERCE_SYMBOL      "cannot number coerce Symbol"
3111 #define DUK_STR_CANNOT_STRING_COERCE_SYMBOL      "cannot string coerce Symbol"
3112 #define DUK_STR_STRING_TOO_LONG                  "string too long"
3113 #define DUK_STR_BUFFER_TOO_LONG                  "buffer too long"
3114 #define DUK_STR_ALLOC_FAILED                     "alloc failed"
3115 #define DUK_STR_WRONG_BUFFER_TYPE                "wrong buffer type"
3116 #define DUK_STR_BASE64_ENCODE_FAILED             "base64 encode failed"
3117 #define DUK_STR_SOURCE_DECODE_FAILED             "source decode failed"
3118 #define DUK_STR_UTF8_DECODE_FAILED               "utf-8 decode failed"
3119 #define DUK_STR_BASE64_DECODE_FAILED             "base64 decode failed"
3120 #define DUK_STR_HEX_DECODE_FAILED                "hex decode failed"
3121 #define DUK_STR_INVALID_BYTECODE                 "invalid bytecode"
3122 #define DUK_STR_NO_SOURCECODE                    "no sourcecode"
3123 #define DUK_STR_RESULT_TOO_LONG                  "result too long"
3124 #define DUK_STR_INVALID_CFUNC_RC                 "invalid C function rc"
3125 #define DUK_STR_INVALID_INSTANCEOF_RVAL          "invalid instanceof rval"
3126 #define DUK_STR_INVALID_INSTANCEOF_RVAL_NOPROTO  "instanceof rval has no .prototype"
3127 
3128 /* JSON */
3129 #define DUK_STR_FMT_PTR                          "%p"
3130 #define DUK_STR_FMT_INVALID_JSON                 "invalid json (at offset %ld)"
3131 #define DUK_STR_CYCLIC_INPUT                     "cyclic input"
3132 
3133 /* Generic codec */
3134 #define DUK_STR_DEC_RECLIMIT                     "decode recursion limit"
3135 #define DUK_STR_ENC_RECLIMIT                     "encode recursion limit"
3136 
3137 /* Object property access */
3138 #define DUK_STR_INVALID_BASE                     "invalid base value"
3139 #define DUK_STR_STRICT_CALLER_READ               "cannot read strict 'caller'"
3140 #define DUK_STR_PROXY_REJECTED                   "proxy rejected"
3141 #define DUK_STR_INVALID_ARRAY_LENGTH             "invalid array length"
3142 #define DUK_STR_SETTER_UNDEFINED                 "setter undefined"
3143 #define DUK_STR_INVALID_DESCRIPTOR               "invalid descriptor"
3144 
3145 /* Proxy */
3146 #define DUK_STR_PROXY_REVOKED                    "proxy revoked"
3147 #define DUK_STR_INVALID_TRAP_RESULT              "invalid trap result"
3148 
3149 /* Variables */
3150 
3151 /* Lexer */
3152 #define DUK_STR_INVALID_ESCAPE                   "invalid escape"
3153 #define DUK_STR_UNTERMINATED_STRING              "unterminated string"
3154 #define DUK_STR_UNTERMINATED_COMMENT             "unterminated comment"
3155 #define DUK_STR_UNTERMINATED_REGEXP              "unterminated regexp"
3156 #define DUK_STR_TOKEN_LIMIT                      "token limit"
3157 #define DUK_STR_REGEXP_SUPPORT_DISABLED          "regexp support disabled"
3158 #define DUK_STR_INVALID_NUMBER_LITERAL           "invalid number literal"
3159 #define DUK_STR_INVALID_TOKEN                    "invalid token"
3160 
3161 /* Compiler */
3162 #define DUK_STR_PARSE_ERROR                      "parse error"
3163 #define DUK_STR_DUPLICATE_LABEL                  "duplicate label"
3164 #define DUK_STR_INVALID_LABEL                    "invalid label"
3165 #define DUK_STR_INVALID_ARRAY_LITERAL            "invalid array literal"
3166 #define DUK_STR_INVALID_OBJECT_LITERAL           "invalid object literal"
3167 #define DUK_STR_INVALID_VAR_DECLARATION          "invalid variable declaration"
3168 #define DUK_STR_CANNOT_DELETE_IDENTIFIER         "cannot delete identifier"
3169 #define DUK_STR_INVALID_EXPRESSION               "invalid expression"
3170 #define DUK_STR_INVALID_LVALUE                   "invalid lvalue"
3171 #define DUK_STR_INVALID_NEWTARGET                "invalid new.target"
3172 #define DUK_STR_EXPECTED_IDENTIFIER              "expected identifier"
3173 #define DUK_STR_EMPTY_EXPR_NOT_ALLOWED           "empty expression not allowed"
3174 #define DUK_STR_INVALID_FOR                      "invalid for statement"
3175 #define DUK_STR_INVALID_SWITCH                   "invalid switch statement"
3176 #define DUK_STR_INVALID_BREAK_CONT_LABEL         "invalid break/continue label"
3177 #define DUK_STR_INVALID_RETURN                   "invalid return"
3178 #define DUK_STR_INVALID_TRY                      "invalid try"
3179 #define DUK_STR_INVALID_THROW                    "invalid throw"
3180 #define DUK_STR_WITH_IN_STRICT_MODE              "with in strict mode"
3181 #define DUK_STR_FUNC_STMT_NOT_ALLOWED            "function statement not allowed"
3182 #define DUK_STR_UNTERMINATED_STMT                "unterminated statement"
3183 #define DUK_STR_INVALID_ARG_NAME                 "invalid argument name"
3184 #define DUK_STR_INVALID_FUNC_NAME                "invalid function name"
3185 #define DUK_STR_INVALID_GETSET_NAME              "invalid getter/setter name"
3186 #define DUK_STR_FUNC_NAME_REQUIRED               "function name required"
3187 
3188 /* RegExp */
3189 #define DUK_STR_INVALID_QUANTIFIER               "invalid regexp quantifier"
3190 #define DUK_STR_INVALID_QUANTIFIER_NO_ATOM       "quantifier without preceding atom"
3191 #define DUK_STR_INVALID_QUANTIFIER_VALUES        "quantifier values invalid (qmin > qmax)"
3192 #define DUK_STR_QUANTIFIER_TOO_MANY_COPIES       "quantifier requires too many atom copies"
3193 #define DUK_STR_UNEXPECTED_CLOSING_PAREN         "unexpected closing parenthesis"
3194 #define DUK_STR_UNEXPECTED_END_OF_PATTERN        "unexpected end of pattern"
3195 #define DUK_STR_UNEXPECTED_REGEXP_TOKEN          "unexpected token in regexp"
3196 #define DUK_STR_INVALID_REGEXP_FLAGS             "invalid regexp flags"
3197 #define DUK_STR_INVALID_REGEXP_ESCAPE            "invalid regexp escape"
3198 #define DUK_STR_INVALID_BACKREFS                 "invalid backreference(s)"
3199 #define DUK_STR_INVALID_REGEXP_CHARACTER         "invalid regexp character"
3200 #define DUK_STR_INVALID_REGEXP_GROUP             "invalid regexp group"
3201 #define DUK_STR_UNTERMINATED_CHARCLASS           "unterminated character class"
3202 #define DUK_STR_INVALID_RANGE                    "invalid range"
3203 
3204 /* Limits */
3205 #define DUK_STR_VALSTACK_LIMIT                   "valstack limit"
3206 #define DUK_STR_CALLSTACK_LIMIT                  "callstack limit"
3207 #define DUK_STR_PROTOTYPE_CHAIN_LIMIT            "prototype chain limit"
3208 #define DUK_STR_BOUND_CHAIN_LIMIT                "function call bound chain limit"
3209 #define DUK_STR_NATIVE_STACK_LIMIT               "C stack depth limit"
3210 #define DUK_STR_COMPILER_RECURSION_LIMIT         "compiler recursion limit"
3211 #define DUK_STR_BYTECODE_LIMIT                   "bytecode limit"
3212 #define DUK_STR_REG_LIMIT                        "register limit"
3213 #define DUK_STR_TEMP_LIMIT                       "temp limit"
3214 #define DUK_STR_CONST_LIMIT                      "const limit"
3215 #define DUK_STR_FUNC_LIMIT                       "function limit"
3216 #define DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT  "regexp compiler recursion limit"
3217 #define DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT  "regexp executor recursion limit"
3218 #define DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT       "regexp step limit"
3219 
3220 #endif  /* DUK_ERRMSG_H_INCLUDED */
3221 /* #include duk_js_bytecode.h */
3222 /*
3223  *  ECMAScript bytecode
3224  */
3225 
3226 #if !defined(DUK_JS_BYTECODE_H_INCLUDED)
3227 #define DUK_JS_BYTECODE_H_INCLUDED
3228 
3229 /*
3230  *  Bytecode instruction layout
3231  *  ===========================
3232  *
3233  *  Instructions are unsigned 32-bit integers divided as follows:
3234  *
3235  *  !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
3236  *  !1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0!
3237  *  +-----------------------------------------------+---------------+
3238  *  !       C       !       B       !       A       !       OP      !
3239  *  +-----------------------------------------------+---------------+
3240  *
3241  *  OP (8 bits):  opcode (DUK_OP_*), access should be fastest
3242  *                consecutive opcodes allocated when opcode needs flags
3243  *   A (8 bits):  typically a target register number
3244  *   B (8 bits):  typically first source register/constant number
3245  *   C (8 bits):  typically second source register/constant number
3246  *
3247  *  Some instructions combine BC or ABC together for larger parameter values.
3248  *  Signed integers (e.g. jump offsets) are encoded as unsigned, with an
3249  *  opcode specific bias.
3250  *
3251  *  Some opcodes have flags which are handled by allocating consecutive
3252  *  opcodes to make space for 1-N flags.  Flags can also be e.g. in the 'A'
3253  *  field when there's room for the specific opcode.
3254  *
3255  *  For example, if three flags were needed, they could be allocated from
3256  *  the opcode field as follows:
3257  *
3258  *  !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
3259  *  !1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0!
3260  *  +-----------------------------------------------+---------------+
3261  *  !       C       !       B       !       A       !    OP   !Z!Y!X!
3262  *  +-----------------------------------------------+---------------+
3263  *
3264  *  Some opcodes accept a reg/const argument which is handled by allocating
3265  *  flags in the OP field, see DUK_BC_ISREG() and DUK_BC_ISCONST().  The
3266  *  following convention is shared by most opcodes, so that the compiler
3267  *  can handle reg/const flagging without opcode specific code paths:
3268  *
3269  *  !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
3270  *  !1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0!
3271  *  +-----------------------------------------------+---------------+
3272  *  !       C       !       B       !       A       !     OP    !Y!X!
3273  *  +-----------------------------------------------+---------------+
3274  *
3275  *    X  1=B is const, 0=B is reg
3276  *    Y  1=C is const, 0=C is reg
3277  *
3278  *    In effect OP, OP + 1, OP + 2, and OP + 3 are allocated from the
3279  *    8-bit opcode space for a single logical opcode.  The base opcode
3280  *    number should be divisible by 4.  If the opcode is called 'FOO'
3281  *    the following opcode constants would be defined:
3282  *
3283  *      DUK_OP_FOO     100       // base opcode number
3284  *      DUK_OP_FOO_RR  100       // FOO, B=reg, C=reg
3285  *      DUK_OP_FOO_CR  101       // FOO, B=const, C=reg
3286  *      DUK_OP_FOO_RC  102       // FOO, B=reg, C=const
3287  *      DUK_OP_FOO_CC  103       // FOO, B=const, C=const
3288  *
3289  *  If only B or C is a reg/const, the unused opcode combinations can be
3290  *  used for other opcodes (which take no reg/const argument).  However,
3291  *  such opcode values are initially reserved, at least while opcode space
3292  *  is available.  For example, if 'BAR' uses B for a register field and
3293  *  C is a reg/const:
3294  *
3295  *      DUK_OP_BAR            116    // base opcode number
3296  *      DUK_OP_BAR_RR         116    // BAR, B=reg, C=reg
3297  *      DUK_OP_BAR_CR_UNUSED  117    // unused, could be repurposed
3298  *      DUK_OP_BAR_RC         118    // BAR, B=reg, C=const
3299  *      DUK_OP_BAR_CC_UNUSED  119    // unused, could be repurposed
3300  *
3301  *  Macro naming is a bit misleading, e.g. "ABC" in macro name but the
3302  *  field layout is concretely "CBA" in the register.
3303  */
3304 
3305 typedef duk_uint32_t duk_instr_t;
3306 
3307 #define DUK_BC_SHIFT_OP             0
3308 #define DUK_BC_SHIFT_A              8
3309 #define DUK_BC_SHIFT_B              16
3310 #define DUK_BC_SHIFT_C              24
3311 #define DUK_BC_SHIFT_BC             DUK_BC_SHIFT_B
3312 #define DUK_BC_SHIFT_ABC            DUK_BC_SHIFT_A
3313 
3314 #define DUK_BC_UNSHIFTED_MASK_OP    0xffUL
3315 #define DUK_BC_UNSHIFTED_MASK_A     0xffUL
3316 #define DUK_BC_UNSHIFTED_MASK_B     0xffUL
3317 #define DUK_BC_UNSHIFTED_MASK_C     0xffUL
3318 #define DUK_BC_UNSHIFTED_MASK_BC    0xffffUL
3319 #define DUK_BC_UNSHIFTED_MASK_ABC   0xffffffUL
3320 
3321 #define DUK_BC_SHIFTED_MASK_OP      (DUK_BC_UNSHIFTED_MASK_OP << DUK_BC_SHIFT_OP)
3322 #define DUK_BC_SHIFTED_MASK_A       (DUK_BC_UNSHIFTED_MASK_A << DUK_BC_SHIFT_A)
3323 #define DUK_BC_SHIFTED_MASK_B       (DUK_BC_UNSHIFTED_MASK_B << DUK_BC_SHIFT_B)
3324 #define DUK_BC_SHIFTED_MASK_C       (DUK_BC_UNSHIFTED_MASK_C << DUK_BC_SHIFT_C)
3325 #define DUK_BC_SHIFTED_MASK_BC      (DUK_BC_UNSHIFTED_MASK_BC << DUK_BC_SHIFT_BC)
3326 #define DUK_BC_SHIFTED_MASK_ABC     (DUK_BC_UNSHIFTED_MASK_ABC << DUK_BC_SHIFT_ABC)
3327 
3328 #define DUK_DEC_OP(x)               ((x) & 0xffUL)
3329 #define DUK_DEC_A(x)                (((x) >> 8) & 0xffUL)
3330 #define DUK_DEC_B(x)                (((x) >> 16) & 0xffUL)
3331 #define DUK_DEC_C(x)                (((x) >> 24) & 0xffUL)
3332 #define DUK_DEC_BC(x)               (((x) >> 16) & 0xffffUL)
3333 #define DUK_DEC_ABC(x)              (((x) >> 8) & 0xffffffUL)
3334 
3335 #define DUK_ENC_OP(op)              ((duk_instr_t) (op))
3336 #define DUK_ENC_OP_ABC(op,abc)      ((duk_instr_t) ( \
3337                                         (((duk_instr_t) (abc)) << 8) | \
3338                                         ((duk_instr_t) (op)) \
3339                                     ))
3340 #define DUK_ENC_OP_A_BC(op,a,bc)    ((duk_instr_t) ( \
3341                                         (((duk_instr_t) (bc)) << 16) | \
3342                                         (((duk_instr_t) (a)) << 8) | \
3343                                         ((duk_instr_t) (op)) \
3344                                     ))
3345 #define DUK_ENC_OP_A_B_C(op,a,b,c)  ((duk_instr_t) ( \
3346                                         (((duk_instr_t) (c)) << 24) | \
3347                                         (((duk_instr_t) (b)) << 16) | \
3348                                         (((duk_instr_t) (a)) << 8) | \
3349                                         ((duk_instr_t) (op)) \
3350                                     ))
3351 #define DUK_ENC_OP_A_B(op,a,b)      DUK_ENC_OP_A_B_C((op),(a),(b),0)
3352 #define DUK_ENC_OP_A(op,a)          DUK_ENC_OP_A_B_C((op),(a),0,0)
3353 #define DUK_ENC_OP_BC(op,bc)        DUK_ENC_OP_A_BC((op),0,(bc))
3354 
3355 /* Get opcode base value with B/C reg/const flags cleared. */
3356 #define DUK_BC_NOREGCONST_OP(op)    ((op) & 0xfc)
3357 
3358 /* Constants should be signed so that signed arithmetic involving them
3359  * won't cause values to be coerced accidentally to unsigned.
3360  */
3361 #define DUK_BC_OP_MIN               0
3362 #define DUK_BC_OP_MAX               0xffL
3363 #define DUK_BC_A_MIN                0
3364 #define DUK_BC_A_MAX                0xffL
3365 #define DUK_BC_B_MIN                0
3366 #define DUK_BC_B_MAX                0xffL
3367 #define DUK_BC_C_MIN                0
3368 #define DUK_BC_C_MAX                0xffL
3369 #define DUK_BC_BC_MIN               0
3370 #define DUK_BC_BC_MAX               0xffffL
3371 #define DUK_BC_ABC_MIN              0
3372 #define DUK_BC_ABC_MAX              0xffffffL
3373 
3374 /* Masks for B/C reg/const indicator in opcode field. */
3375 #define DUK_BC_REGCONST_B           (0x01UL)
3376 #define DUK_BC_REGCONST_C           (0x02UL)
3377 
3378 /* Misc. masks for opcode field. */
3379 #define DUK_BC_INCDECP_FLAG_DEC     (0x04UL)
3380 #define DUK_BC_INCDECP_FLAG_POST    (0x08UL)
3381 
3382 /* Opcodes. */
3383 #define DUK_OP_LDREG                0
3384 #define DUK_OP_STREG                1
3385 #define DUK_OP_JUMP                 2
3386 #define DUK_OP_LDCONST              3
3387 #define DUK_OP_LDINT                4
3388 #define DUK_OP_LDINTX               5
3389 #define DUK_OP_LDTHIS               6
3390 #define DUK_OP_LDUNDEF              7
3391 #define DUK_OP_LDNULL               8
3392 #define DUK_OP_LDTRUE               9
3393 #define DUK_OP_LDFALSE              10
3394 #define DUK_OP_GETVAR               11
3395 #define DUK_OP_BNOT                 12
3396 #define DUK_OP_LNOT                 13
3397 #define DUK_OP_UNM                  14
3398 #define DUK_OP_UNP                  15
3399 #define DUK_OP_EQ                   16
3400 #define DUK_OP_EQ_RR                16
3401 #define DUK_OP_EQ_CR                17
3402 #define DUK_OP_EQ_RC                18
3403 #define DUK_OP_EQ_CC                19
3404 #define DUK_OP_NEQ                  20
3405 #define DUK_OP_NEQ_RR               20
3406 #define DUK_OP_NEQ_CR               21
3407 #define DUK_OP_NEQ_RC               22
3408 #define DUK_OP_NEQ_CC               23
3409 #define DUK_OP_SEQ                  24
3410 #define DUK_OP_SEQ_RR               24
3411 #define DUK_OP_SEQ_CR               25
3412 #define DUK_OP_SEQ_RC               26
3413 #define DUK_OP_SEQ_CC               27
3414 #define DUK_OP_SNEQ                 28
3415 #define DUK_OP_SNEQ_RR              28
3416 #define DUK_OP_SNEQ_CR              29
3417 #define DUK_OP_SNEQ_RC              30
3418 #define DUK_OP_SNEQ_CC              31
3419 #define DUK_OP_GT                   32
3420 #define DUK_OP_GT_RR                32
3421 #define DUK_OP_GT_CR                33
3422 #define DUK_OP_GT_RC                34
3423 #define DUK_OP_GT_CC                35
3424 #define DUK_OP_GE                   36
3425 #define DUK_OP_GE_RR                36
3426 #define DUK_OP_GE_CR                37
3427 #define DUK_OP_GE_RC                38
3428 #define DUK_OP_GE_CC                39
3429 #define DUK_OP_LT                   40
3430 #define DUK_OP_LT_RR                40
3431 #define DUK_OP_LT_CR                41
3432 #define DUK_OP_LT_RC                42
3433 #define DUK_OP_LT_CC                43
3434 #define DUK_OP_LE                   44
3435 #define DUK_OP_LE_RR                44
3436 #define DUK_OP_LE_CR                45
3437 #define DUK_OP_LE_RC                46
3438 #define DUK_OP_LE_CC                47
3439 #define DUK_OP_IFTRUE               48
3440 #define DUK_OP_IFTRUE_R             48
3441 #define DUK_OP_IFTRUE_C             49
3442 #define DUK_OP_IFFALSE              50
3443 #define DUK_OP_IFFALSE_R            50
3444 #define DUK_OP_IFFALSE_C            51
3445 #define DUK_OP_ADD                  52
3446 #define DUK_OP_ADD_RR               52
3447 #define DUK_OP_ADD_CR               53
3448 #define DUK_OP_ADD_RC               54
3449 #define DUK_OP_ADD_CC               55
3450 #define DUK_OP_SUB                  56
3451 #define DUK_OP_SUB_RR               56
3452 #define DUK_OP_SUB_CR               57
3453 #define DUK_OP_SUB_RC               58
3454 #define DUK_OP_SUB_CC               59
3455 #define DUK_OP_MUL                  60
3456 #define DUK_OP_MUL_RR               60
3457 #define DUK_OP_MUL_CR               61
3458 #define DUK_OP_MUL_RC               62
3459 #define DUK_OP_MUL_CC               63
3460 #define DUK_OP_DIV                  64
3461 #define DUK_OP_DIV_RR               64
3462 #define DUK_OP_DIV_CR               65
3463 #define DUK_OP_DIV_RC               66
3464 #define DUK_OP_DIV_CC               67
3465 #define DUK_OP_MOD                  68
3466 #define DUK_OP_MOD_RR               68
3467 #define DUK_OP_MOD_CR               69
3468 #define DUK_OP_MOD_RC               70
3469 #define DUK_OP_MOD_CC               71
3470 #define DUK_OP_EXP                  72
3471 #define DUK_OP_EXP_RR               72
3472 #define DUK_OP_EXP_CR               73
3473 #define DUK_OP_EXP_RC               74
3474 #define DUK_OP_EXP_CC               75
3475 #define DUK_OP_BAND                 76
3476 #define DUK_OP_BAND_RR              76
3477 #define DUK_OP_BAND_CR              77
3478 #define DUK_OP_BAND_RC              78
3479 #define DUK_OP_BAND_CC              79
3480 #define DUK_OP_BOR                  80
3481 #define DUK_OP_BOR_RR               80
3482 #define DUK_OP_BOR_CR               81
3483 #define DUK_OP_BOR_RC               82
3484 #define DUK_OP_BOR_CC               83
3485 #define DUK_OP_BXOR                 84
3486 #define DUK_OP_BXOR_RR              84
3487 #define DUK_OP_BXOR_CR              85
3488 #define DUK_OP_BXOR_RC              86
3489 #define DUK_OP_BXOR_CC              87
3490 #define DUK_OP_BASL                 88
3491 #define DUK_OP_BASL_RR              88
3492 #define DUK_OP_BASL_CR              89
3493 #define DUK_OP_BASL_RC              90
3494 #define DUK_OP_BASL_CC              91
3495 #define DUK_OP_BLSR                 92
3496 #define DUK_OP_BLSR_RR              92
3497 #define DUK_OP_BLSR_CR              93
3498 #define DUK_OP_BLSR_RC              94
3499 #define DUK_OP_BLSR_CC              95
3500 #define DUK_OP_BASR                 96
3501 #define DUK_OP_BASR_RR              96
3502 #define DUK_OP_BASR_CR              97
3503 #define DUK_OP_BASR_RC              98
3504 #define DUK_OP_BASR_CC              99
3505 #define DUK_OP_INSTOF               100
3506 #define DUK_OP_INSTOF_RR            100
3507 #define DUK_OP_INSTOF_CR            101
3508 #define DUK_OP_INSTOF_RC            102
3509 #define DUK_OP_INSTOF_CC            103
3510 #define DUK_OP_IN                   104
3511 #define DUK_OP_IN_RR                104
3512 #define DUK_OP_IN_CR                105
3513 #define DUK_OP_IN_RC                106
3514 #define DUK_OP_IN_CC                107
3515 #define DUK_OP_GETPROP              108
3516 #define DUK_OP_GETPROP_RR           108
3517 #define DUK_OP_GETPROP_CR           109
3518 #define DUK_OP_GETPROP_RC           110
3519 #define DUK_OP_GETPROP_CC           111
3520 #define DUK_OP_PUTPROP              112
3521 #define DUK_OP_PUTPROP_RR           112
3522 #define DUK_OP_PUTPROP_CR           113
3523 #define DUK_OP_PUTPROP_RC           114
3524 #define DUK_OP_PUTPROP_CC           115
3525 #define DUK_OP_DELPROP              116
3526 #define DUK_OP_DELPROP_RR           116
3527 #define DUK_OP_DELPROP_CR_UNUSED    117  /* unused now */
3528 #define DUK_OP_DELPROP_RC           118
3529 #define DUK_OP_DELPROP_CC_UNUSED    119  /* unused now */
3530 #define DUK_OP_PREINCR              120  /* pre/post opcode values have constraints, */
3531 #define DUK_OP_PREDECR              121  /* see duk_js_executor.c and duk_js_compiler.c. */
3532 #define DUK_OP_POSTINCR             122
3533 #define DUK_OP_POSTDECR             123
3534 #define DUK_OP_PREINCV              124
3535 #define DUK_OP_PREDECV              125
3536 #define DUK_OP_POSTINCV             126
3537 #define DUK_OP_POSTDECV             127
3538 #define DUK_OP_PREINCP              128  /* pre/post inc/dec prop opcodes have constraints */
3539 #define DUK_OP_PREINCP_RR           128
3540 #define DUK_OP_PREINCP_CR           129
3541 #define DUK_OP_PREINCP_RC           130
3542 #define DUK_OP_PREINCP_CC           131
3543 #define DUK_OP_PREDECP              132
3544 #define DUK_OP_PREDECP_RR           132
3545 #define DUK_OP_PREDECP_CR           133
3546 #define DUK_OP_PREDECP_RC           134
3547 #define DUK_OP_PREDECP_CC           135
3548 #define DUK_OP_POSTINCP             136
3549 #define DUK_OP_POSTINCP_RR          136
3550 #define DUK_OP_POSTINCP_CR          137
3551 #define DUK_OP_POSTINCP_RC          138
3552 #define DUK_OP_POSTINCP_CC          139
3553 #define DUK_OP_POSTDECP             140
3554 #define DUK_OP_POSTDECP_RR          140
3555 #define DUK_OP_POSTDECP_CR          141
3556 #define DUK_OP_POSTDECP_RC          142
3557 #define DUK_OP_POSTDECP_CC          143
3558 #define DUK_OP_DECLVAR              144
3559 #define DUK_OP_DECLVAR_RR           144
3560 #define DUK_OP_DECLVAR_CR           145
3561 #define DUK_OP_DECLVAR_RC           146
3562 #define DUK_OP_DECLVAR_CC           147
3563 #define DUK_OP_REGEXP               148
3564 #define DUK_OP_REGEXP_RR            148
3565 #define DUK_OP_REGEXP_CR            149
3566 #define DUK_OP_REGEXP_RC            150
3567 #define DUK_OP_REGEXP_CC            151
3568 #define DUK_OP_CLOSURE              152
3569 #define DUK_OP_TYPEOF               153
3570 #define DUK_OP_TYPEOFID             154
3571 #define DUK_OP_PUTVAR               155
3572 #define DUK_OP_DELVAR               156
3573 #define DUK_OP_RETREG               157
3574 #define DUK_OP_RETUNDEF             158
3575 #define DUK_OP_RETCONST             159
3576 #define DUK_OP_RETCONSTN            160  /* return const without incref (e.g. number) */
3577 #define DUK_OP_LABEL                161
3578 #define DUK_OP_ENDLABEL             162
3579 #define DUK_OP_BREAK                163
3580 #define DUK_OP_CONTINUE             164
3581 #define DUK_OP_TRYCATCH             165
3582 #define DUK_OP_ENDTRY               166
3583 #define DUK_OP_ENDCATCH             167
3584 #define DUK_OP_ENDFIN               168
3585 #define DUK_OP_THROW                169
3586 #define DUK_OP_INVLHS               170
3587 #define DUK_OP_CSREG                171
3588 #define DUK_OP_CSVAR                172
3589 #define DUK_OP_CSVAR_RR             172
3590 #define DUK_OP_CSVAR_CR             173
3591 #define DUK_OP_CSVAR_RC             174
3592 #define DUK_OP_CSVAR_CC             175
3593 #define DUK_OP_CALL0                176  /* DUK_OP_CALL0 & 0x0F must be zero. */
3594 #define DUK_OP_CALL1                177
3595 #define DUK_OP_CALL2                178
3596 #define DUK_OP_CALL3                179
3597 #define DUK_OP_CALL4                180
3598 #define DUK_OP_CALL5                181
3599 #define DUK_OP_CALL6                182
3600 #define DUK_OP_CALL7                183
3601 #define DUK_OP_CALL8                184
3602 #define DUK_OP_CALL9                185
3603 #define DUK_OP_CALL10               186
3604 #define DUK_OP_CALL11               187
3605 #define DUK_OP_CALL12               188
3606 #define DUK_OP_CALL13               189
3607 #define DUK_OP_CALL14               190
3608 #define DUK_OP_CALL15               191
3609 #define DUK_OP_NEWOBJ               192
3610 #define DUK_OP_NEWARR               193
3611 #define DUK_OP_MPUTOBJ              194
3612 #define DUK_OP_MPUTOBJI             195
3613 #define DUK_OP_INITSET              196
3614 #define DUK_OP_INITGET              197
3615 #define DUK_OP_MPUTARR              198
3616 #define DUK_OP_MPUTARRI             199
3617 #define DUK_OP_SETALEN              200
3618 #define DUK_OP_INITENUM             201
3619 #define DUK_OP_NEXTENUM             202
3620 #define DUK_OP_NEWTARGET            203
3621 #define DUK_OP_DEBUGGER             204
3622 #define DUK_OP_NOP                  205
3623 #define DUK_OP_INVALID              206
3624 #define DUK_OP_UNUSED207            207
3625 #define DUK_OP_GETPROPC             208
3626 #define DUK_OP_GETPROPC_RR          208
3627 #define DUK_OP_GETPROPC_CR          209
3628 #define DUK_OP_GETPROPC_RC          210
3629 #define DUK_OP_GETPROPC_CC          211
3630 #define DUK_OP_UNUSED212            212
3631 #define DUK_OP_UNUSED213            213
3632 #define DUK_OP_UNUSED214            214
3633 #define DUK_OP_UNUSED215            215
3634 #define DUK_OP_UNUSED216            216
3635 #define DUK_OP_UNUSED217            217
3636 #define DUK_OP_UNUSED218            218
3637 #define DUK_OP_UNUSED219            219
3638 #define DUK_OP_UNUSED220            220
3639 #define DUK_OP_UNUSED221            221
3640 #define DUK_OP_UNUSED222            222
3641 #define DUK_OP_UNUSED223            223
3642 #define DUK_OP_UNUSED224            224
3643 #define DUK_OP_UNUSED225            225
3644 #define DUK_OP_UNUSED226            226
3645 #define DUK_OP_UNUSED227            227
3646 #define DUK_OP_UNUSED228            228
3647 #define DUK_OP_UNUSED229            229
3648 #define DUK_OP_UNUSED230            230
3649 #define DUK_OP_UNUSED231            231
3650 #define DUK_OP_UNUSED232            232
3651 #define DUK_OP_UNUSED233            233
3652 #define DUK_OP_UNUSED234            234
3653 #define DUK_OP_UNUSED235            235
3654 #define DUK_OP_UNUSED236            236
3655 #define DUK_OP_UNUSED237            237
3656 #define DUK_OP_UNUSED238            238
3657 #define DUK_OP_UNUSED239            239
3658 #define DUK_OP_UNUSED240            240
3659 #define DUK_OP_UNUSED241            241
3660 #define DUK_OP_UNUSED242            242
3661 #define DUK_OP_UNUSED243            243
3662 #define DUK_OP_UNUSED244            244
3663 #define DUK_OP_UNUSED245            245
3664 #define DUK_OP_UNUSED246            246
3665 #define DUK_OP_UNUSED247            247
3666 #define DUK_OP_UNUSED248            248
3667 #define DUK_OP_UNUSED249            249
3668 #define DUK_OP_UNUSED250            250
3669 #define DUK_OP_UNUSED251            251
3670 #define DUK_OP_UNUSED252            252
3671 #define DUK_OP_UNUSED253            253
3672 #define DUK_OP_UNUSED254            254
3673 #define DUK_OP_UNUSED255            255
3674 #define DUK_OP_NONE                 256  /* dummy value used as marker (doesn't fit in 8-bit field) */
3675 
3676 /* XXX: Allocate flags from opcode field?  Would take 16 opcode slots
3677  * but avoids shuffling in more cases.  Maybe not worth it.
3678  */
3679 /* DUK_OP_TRYCATCH flags in A. */
3680 #define DUK_BC_TRYCATCH_FLAG_HAVE_CATCH     (1U << 0)
3681 #define DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY   (1U << 1)
3682 #define DUK_BC_TRYCATCH_FLAG_CATCH_BINDING  (1U << 2)
3683 #define DUK_BC_TRYCATCH_FLAG_WITH_BINDING   (1U << 3)
3684 
3685 /* DUK_OP_DECLVAR flags in A; bottom bits are reserved for propdesc flags
3686  * (DUK_PROPDESC_FLAG_XXX).
3687  */
3688 #define DUK_BC_DECLVAR_FLAG_FUNC_DECL       (1U << 4)  /* function declaration */
3689 
3690 /* DUK_OP_CALLn flags, part of opcode field.  Three lowest bits must match
3691  * DUK_CALL_FLAG_xxx directly.
3692  */
3693 #define DUK_BC_CALL_FLAG_TAILCALL           (1U << 0)
3694 #define DUK_BC_CALL_FLAG_CONSTRUCT          (1U << 1)
3695 #define DUK_BC_CALL_FLAG_CALLED_AS_EVAL     (1U << 2)
3696 #define DUK_BC_CALL_FLAG_INDIRECT           (1U << 3)
3697 
3698 /* Misc constants and helper macros. */
3699 #define DUK_BC_LDINT_BIAS           (1L << 15)
3700 #define DUK_BC_LDINTX_SHIFT         16
3701 #define DUK_BC_JUMP_BIAS            (1L << 23)
3702 
3703 #endif  /* DUK_JS_BYTECODE_H_INCLUDED */
3704 /* #include duk_lexer.h */
3705 /*
3706  *  Lexer defines.
3707  */
3708 
3709 #if !defined(DUK_LEXER_H_INCLUDED)
3710 #define DUK_LEXER_H_INCLUDED
3711 
3712 typedef void (*duk_re_range_callback)(void *user, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct);
3713 
3714 /*
3715  *  A token is interpreted as any possible production of InputElementDiv
3716  *  and InputElementRegExp, see E5 Section 7 in its entirety.  Note that
3717  *  the E5 "Token" production does not cover all actual tokens of the
3718  *  language (which is explicitly stated in the specification, Section 7.5).
3719  *  Null and boolean literals are defined as part of both ReservedWord
3720  *  (E5 Section 7.6.1) and Literal (E5 Section 7.8) productions.  Here,
3721  *  null and boolean values have literal tokens, and are not reserved
3722  *  words.
3723  *
3724  *  Decimal literal negative/positive sign is -not- part of DUK_TOK_NUMBER.
3725  *  The number tokens always have a non-negative value.  The unary minus
3726  *  operator in "-1.0" is optimized during compilation to yield a single
3727  *  negative constant.
3728  *
3729  *  Token numbering is free except that reserved words are required to be
3730  *  in a continuous range and in a particular order.  See genstrings.py.
3731  */
3732 
3733 #define DUK_LEXER_INITCTX(ctx)        duk_lexer_initctx((ctx))
3734 
3735 #define DUK_LEXER_SETPOINT(ctx,pt)    duk_lexer_setpoint((ctx), (pt))
3736 
3737 #define DUK_LEXER_GETPOINT(ctx,pt)    duk_lexer_getpoint((ctx), (pt))
3738 
3739 /* Currently 6 characters of lookup are actually needed (duk_lexer.c). */
3740 #define DUK_LEXER_WINDOW_SIZE                     6
3741 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
3742 #define DUK_LEXER_BUFFER_SIZE                     64
3743 #endif
3744 
3745 #define DUK_TOK_MINVAL                            0
3746 
3747 /* returned after EOF (infinite amount) */
3748 #define DUK_TOK_EOF                               0
3749 
3750 /* identifier names (E5 Section 7.6) */
3751 #define DUK_TOK_IDENTIFIER                        1
3752 
3753 /* reserved words: keywords */
3754 #define DUK_TOK_START_RESERVED                    2
3755 #define DUK_TOK_BREAK                             2
3756 #define DUK_TOK_CASE                              3
3757 #define DUK_TOK_CATCH                             4
3758 #define DUK_TOK_CONTINUE                          5
3759 #define DUK_TOK_DEBUGGER                          6
3760 #define DUK_TOK_DEFAULT                           7
3761 #define DUK_TOK_DELETE                            8
3762 #define DUK_TOK_DO                                9
3763 #define DUK_TOK_ELSE                              10
3764 #define DUK_TOK_FINALLY                           11
3765 #define DUK_TOK_FOR                               12
3766 #define DUK_TOK_FUNCTION                          13
3767 #define DUK_TOK_IF                                14
3768 #define DUK_TOK_IN                                15
3769 #define DUK_TOK_INSTANCEOF                        16
3770 #define DUK_TOK_NEW                               17
3771 #define DUK_TOK_RETURN                            18
3772 #define DUK_TOK_SWITCH                            19
3773 #define DUK_TOK_THIS                              20
3774 #define DUK_TOK_THROW                             21
3775 #define DUK_TOK_TRY                               22
3776 #define DUK_TOK_TYPEOF                            23
3777 #define DUK_TOK_VAR                               24
3778 #define DUK_TOK_CONST                             25
3779 #define DUK_TOK_VOID                              26
3780 #define DUK_TOK_WHILE                             27
3781 #define DUK_TOK_WITH                              28
3782 
3783 /* reserved words: future reserved words */
3784 #define DUK_TOK_CLASS                             29
3785 #define DUK_TOK_ENUM                              30
3786 #define DUK_TOK_EXPORT                            31
3787 #define DUK_TOK_EXTENDS                           32
3788 #define DUK_TOK_IMPORT                            33
3789 #define DUK_TOK_SUPER                             34
3790 
3791 /* "null", "true", and "false" are always reserved words.
3792  * Note that "get" and "set" are not!
3793  */
3794 #define DUK_TOK_NULL                              35
3795 #define DUK_TOK_TRUE                              36
3796 #define DUK_TOK_FALSE                             37
3797 
3798 /* reserved words: additional future reserved words in strict mode */
3799 #define DUK_TOK_START_STRICT_RESERVED             38  /* inclusive */
3800 #define DUK_TOK_IMPLEMENTS                        38
3801 #define DUK_TOK_INTERFACE                         39
3802 #define DUK_TOK_LET                               40
3803 #define DUK_TOK_PACKAGE                           41
3804 #define DUK_TOK_PRIVATE                           42
3805 #define DUK_TOK_PROTECTED                         43
3806 #define DUK_TOK_PUBLIC                            44
3807 #define DUK_TOK_STATIC                            45
3808 #define DUK_TOK_YIELD                             46
3809 
3810 #define DUK_TOK_END_RESERVED                      47  /* exclusive */
3811 
3812 /* "get" and "set" are tokens but NOT ReservedWords.  They are currently
3813  * parsed and identifiers and these defines are actually now unused.
3814  */
3815 #define DUK_TOK_GET                               47
3816 #define DUK_TOK_SET                               48
3817 
3818 /* punctuators (unlike the spec, also includes "/" and "/=") */
3819 #define DUK_TOK_LCURLY                            49
3820 #define DUK_TOK_RCURLY                            50
3821 #define DUK_TOK_LBRACKET                          51
3822 #define DUK_TOK_RBRACKET                          52
3823 #define DUK_TOK_LPAREN                            53
3824 #define DUK_TOK_RPAREN                            54
3825 #define DUK_TOK_PERIOD                            55
3826 #define DUK_TOK_SEMICOLON                         56
3827 #define DUK_TOK_COMMA                             57
3828 #define DUK_TOK_LT                                58
3829 #define DUK_TOK_GT                                59
3830 #define DUK_TOK_LE                                60
3831 #define DUK_TOK_GE                                61
3832 #define DUK_TOK_EQ                                62
3833 #define DUK_TOK_NEQ                               63
3834 #define DUK_TOK_SEQ                               64
3835 #define DUK_TOK_SNEQ                              65
3836 #define DUK_TOK_ADD                               66
3837 #define DUK_TOK_SUB                               67
3838 #define DUK_TOK_MUL                               68
3839 #define DUK_TOK_DIV                               69
3840 #define DUK_TOK_MOD                               70
3841 #define DUK_TOK_EXP                               71
3842 #define DUK_TOK_INCREMENT                         72
3843 #define DUK_TOK_DECREMENT                         73
3844 #define DUK_TOK_ALSHIFT                           74   /* named "arithmetic" because result is signed */
3845 #define DUK_TOK_ARSHIFT                           75
3846 #define DUK_TOK_RSHIFT                            76
3847 #define DUK_TOK_BAND                              77
3848 #define DUK_TOK_BOR                               78
3849 #define DUK_TOK_BXOR                              79
3850 #define DUK_TOK_LNOT                              80
3851 #define DUK_TOK_BNOT                              81
3852 #define DUK_TOK_LAND                              82
3853 #define DUK_TOK_LOR                               83
3854 #define DUK_TOK_QUESTION                          84
3855 #define DUK_TOK_COLON                             85
3856 #define DUK_TOK_EQUALSIGN                         86
3857 #define DUK_TOK_ADD_EQ                            87
3858 #define DUK_TOK_SUB_EQ                            88
3859 #define DUK_TOK_MUL_EQ                            89
3860 #define DUK_TOK_DIV_EQ                            90
3861 #define DUK_TOK_MOD_EQ                            91
3862 #define DUK_TOK_EXP_EQ                            92
3863 #define DUK_TOK_ALSHIFT_EQ                        93
3864 #define DUK_TOK_ARSHIFT_EQ                        94
3865 #define DUK_TOK_RSHIFT_EQ                         95
3866 #define DUK_TOK_BAND_EQ                           96
3867 #define DUK_TOK_BOR_EQ                            97
3868 #define DUK_TOK_BXOR_EQ                           98
3869 
3870 /* literals (E5 Section 7.8), except null, true, false, which are treated
3871  * like reserved words (above).
3872  */
3873 #define DUK_TOK_NUMBER                            99
3874 #define DUK_TOK_STRING                            100
3875 #define DUK_TOK_REGEXP                            101
3876 
3877 #define DUK_TOK_MAXVAL                            101  /* inclusive */
3878 
3879 #define DUK_TOK_INVALID                           DUK_SMALL_UINT_MAX
3880 
3881 /* Convert heap string index to a token (reserved words) */
3882 #define DUK_STRIDX_TO_TOK(x)                        ((x) - DUK_STRIDX_START_RESERVED + DUK_TOK_START_RESERVED)
3883 
3884 /* Sanity check */
3885 #if (DUK_TOK_MAXVAL > 255)
3886 #error DUK_TOK_MAXVAL too large, code assumes it fits into 8 bits
3887 #endif
3888 
3889 /* Sanity checks for string and token defines */
3890 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_BREAK) != DUK_TOK_BREAK)
3891 #error mismatch in token defines
3892 #endif
3893 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CASE) != DUK_TOK_CASE)
3894 #error mismatch in token defines
3895 #endif
3896 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CATCH) != DUK_TOK_CATCH)
3897 #error mismatch in token defines
3898 #endif
3899 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CONTINUE) != DUK_TOK_CONTINUE)
3900 #error mismatch in token defines
3901 #endif
3902 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DEBUGGER) != DUK_TOK_DEBUGGER)
3903 #error mismatch in token defines
3904 #endif
3905 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DEFAULT) != DUK_TOK_DEFAULT)
3906 #error mismatch in token defines
3907 #endif
3908 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DELETE) != DUK_TOK_DELETE)
3909 #error mismatch in token defines
3910 #endif
3911 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DO) != DUK_TOK_DO)
3912 #error mismatch in token defines
3913 #endif
3914 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_ELSE) != DUK_TOK_ELSE)
3915 #error mismatch in token defines
3916 #endif
3917 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FINALLY) != DUK_TOK_FINALLY)
3918 #error mismatch in token defines
3919 #endif
3920 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FOR) != DUK_TOK_FOR)
3921 #error mismatch in token defines
3922 #endif
3923 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LC_FUNCTION) != DUK_TOK_FUNCTION)
3924 #error mismatch in token defines
3925 #endif
3926 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IF) != DUK_TOK_IF)
3927 #error mismatch in token defines
3928 #endif
3929 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IN) != DUK_TOK_IN)
3930 #error mismatch in token defines
3931 #endif
3932 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_INSTANCEOF) != DUK_TOK_INSTANCEOF)
3933 #error mismatch in token defines
3934 #endif
3935 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_NEW) != DUK_TOK_NEW)
3936 #error mismatch in token defines
3937 #endif
3938 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_RETURN) != DUK_TOK_RETURN)
3939 #error mismatch in token defines
3940 #endif
3941 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_SWITCH) != DUK_TOK_SWITCH)
3942 #error mismatch in token defines
3943 #endif
3944 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_THIS) != DUK_TOK_THIS)
3945 #error mismatch in token defines
3946 #endif
3947 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_THROW) != DUK_TOK_THROW)
3948 #error mismatch in token defines
3949 #endif
3950 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TRY) != DUK_TOK_TRY)
3951 #error mismatch in token defines
3952 #endif
3953 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TYPEOF) != DUK_TOK_TYPEOF)
3954 #error mismatch in token defines
3955 #endif
3956 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_VAR) != DUK_TOK_VAR)
3957 #error mismatch in token defines
3958 #endif
3959 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_VOID) != DUK_TOK_VOID)
3960 #error mismatch in token defines
3961 #endif
3962 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_WHILE) != DUK_TOK_WHILE)
3963 #error mismatch in token defines
3964 #endif
3965 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_WITH) != DUK_TOK_WITH)
3966 #error mismatch in token defines
3967 #endif
3968 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CLASS) != DUK_TOK_CLASS)
3969 #error mismatch in token defines
3970 #endif
3971 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CONST) != DUK_TOK_CONST)
3972 #error mismatch in token defines
3973 #endif
3974 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_ENUM) != DUK_TOK_ENUM)
3975 #error mismatch in token defines
3976 #endif
3977 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_EXPORT) != DUK_TOK_EXPORT)
3978 #error mismatch in token defines
3979 #endif
3980 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_EXTENDS) != DUK_TOK_EXTENDS)
3981 #error mismatch in token defines
3982 #endif
3983 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IMPORT) != DUK_TOK_IMPORT)
3984 #error mismatch in token defines
3985 #endif
3986 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_SUPER) != DUK_TOK_SUPER)
3987 #error mismatch in token defines
3988 #endif
3989 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LC_NULL) != DUK_TOK_NULL)
3990 #error mismatch in token defines
3991 #endif
3992 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TRUE) != DUK_TOK_TRUE)
3993 #error mismatch in token defines
3994 #endif
3995 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FALSE) != DUK_TOK_FALSE)
3996 #error mismatch in token defines
3997 #endif
3998 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IMPLEMENTS) != DUK_TOK_IMPLEMENTS)
3999 #error mismatch in token defines
4000 #endif
4001 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_INTERFACE) != DUK_TOK_INTERFACE)
4002 #error mismatch in token defines
4003 #endif
4004 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LET) != DUK_TOK_LET)
4005 #error mismatch in token defines
4006 #endif
4007 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PACKAGE) != DUK_TOK_PACKAGE)
4008 #error mismatch in token defines
4009 #endif
4010 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PRIVATE) != DUK_TOK_PRIVATE)
4011 #error mismatch in token defines
4012 #endif
4013 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PROTECTED) != DUK_TOK_PROTECTED)
4014 #error mismatch in token defines
4015 #endif
4016 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PUBLIC) != DUK_TOK_PUBLIC)
4017 #error mismatch in token defines
4018 #endif
4019 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_STATIC) != DUK_TOK_STATIC)
4020 #error mismatch in token defines
4021 #endif
4022 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_YIELD) != DUK_TOK_YIELD)
4023 #error mismatch in token defines
4024 #endif
4025 
4026 /* Regexp tokens */
4027 #define DUK_RETOK_EOF                              0
4028 #define DUK_RETOK_DISJUNCTION                      1
4029 #define DUK_RETOK_QUANTIFIER                       2
4030 #define DUK_RETOK_ASSERT_START                     3
4031 #define DUK_RETOK_ASSERT_END                       4
4032 #define DUK_RETOK_ASSERT_WORD_BOUNDARY             5
4033 #define DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY         6
4034 #define DUK_RETOK_ASSERT_START_POS_LOOKAHEAD       7
4035 #define DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD       8
4036 #define DUK_RETOK_ATOM_PERIOD                      9
4037 #define DUK_RETOK_ATOM_CHAR                        10
4038 #define DUK_RETOK_ATOM_DIGIT                       11  /* assumptions in regexp compiler */
4039 #define DUK_RETOK_ATOM_NOT_DIGIT                   12  /* -""- */
4040 #define DUK_RETOK_ATOM_WHITE                       13  /* -""- */
4041 #define DUK_RETOK_ATOM_NOT_WHITE                   14  /* -""- */
4042 #define DUK_RETOK_ATOM_WORD_CHAR                   15  /* -""- */
4043 #define DUK_RETOK_ATOM_NOT_WORD_CHAR               16  /* -""- */
4044 #define DUK_RETOK_ATOM_BACKREFERENCE               17
4045 #define DUK_RETOK_ATOM_START_CAPTURE_GROUP         18
4046 #define DUK_RETOK_ATOM_START_NONCAPTURE_GROUP      19
4047 #define DUK_RETOK_ATOM_START_CHARCLASS             20
4048 #define DUK_RETOK_ATOM_START_CHARCLASS_INVERTED    21
4049 #define DUK_RETOK_ATOM_END_GROUP                   22
4050 
4051 /* Constants for duk_lexer_ctx.buf. */
4052 #define DUK_LEXER_TEMP_BUF_LIMIT                   256
4053 
4054 /* A token value.  Can be memcpy()'d, but note that slot1/slot2 values are on the valstack.
4055  * Some fields (like num, str1, str2) are only valid for specific token types and may have
4056  * stale values otherwise.
4057  */
4058 struct duk_token {
4059 	duk_small_uint_t t;           /* token type (with reserved word identification) */
4060 	duk_small_uint_t t_nores;     /* token type (with reserved words as DUK_TOK_IDENTIFER) */
4061 	duk_double_t num;             /* numeric value of token */
4062 	duk_hstring *str1;            /* string 1 of token (borrowed, stored to ctx->slot1_idx) */
4063 	duk_hstring *str2;            /* string 2 of token (borrowed, stored to ctx->slot2_idx) */
4064 	duk_size_t start_offset;      /* start byte offset of token in lexer input */
4065 	duk_int_t start_line;         /* start line of token (first char) */
4066 	duk_int_t num_escapes;        /* number of escapes and line continuations (for directive prologue) */
4067 	duk_bool_t lineterm;          /* token was preceded by a lineterm */
4068 	duk_bool_t allow_auto_semi;   /* token allows automatic semicolon insertion (eof or preceded by newline) */
4069 };
4070 
4071 #define DUK_RE_QUANTIFIER_INFINITE         ((duk_uint32_t) 0xffffffffUL)
4072 
4073 /* A regexp token value. */
4074 struct duk_re_token {
4075 	duk_small_uint_t t;          /* token type */
4076 	duk_small_uint_t greedy;
4077 	duk_uint32_t num;            /* numeric value (character, count) */
4078 	duk_uint32_t qmin;
4079 	duk_uint32_t qmax;
4080 };
4081 
4082 /* A structure for 'snapshotting' a point for rewinding */
4083 struct duk_lexer_point {
4084 	duk_size_t offset;
4085 	duk_int_t line;
4086 };
4087 
4088 /* Lexer codepoint with additional info like offset/line number */
4089 struct duk_lexer_codepoint {
4090 	duk_codepoint_t codepoint;
4091 	duk_size_t offset;
4092 	duk_int_t line;
4093 };
4094 
4095 /* Lexer context.  Same context is used for ECMAScript and Regexp parsing. */
4096 struct duk_lexer_ctx {
4097 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
4098 	duk_lexer_codepoint *window; /* unicode code points, window[0] is always next, points to 'buffer' */
4099 	duk_lexer_codepoint buffer[DUK_LEXER_BUFFER_SIZE];
4100 #else
4101 	duk_lexer_codepoint window[DUK_LEXER_WINDOW_SIZE]; /* unicode code points, window[0] is always next */
4102 #endif
4103 
4104 	duk_hthread *thr;                              /* thread; minimizes argument passing */
4105 
4106 	const duk_uint8_t *input;                      /* input string (may be a user pointer) */
4107 	duk_size_t input_length;                       /* input byte length */
4108 	duk_size_t input_offset;                       /* input offset for window leading edge (not window[0]) */
4109 	duk_int_t input_line;                          /* input linenumber at input_offset (not window[0]), init to 1 */
4110 
4111 	duk_idx_t slot1_idx;                           /* valstack slot for 1st token value */
4112 	duk_idx_t slot2_idx;                           /* valstack slot for 2nd token value */
4113 	duk_idx_t buf_idx;                             /* valstack slot for temp buffer */
4114 	duk_hbuffer_dynamic *buf;                      /* temp accumulation buffer */
4115 	duk_bufwriter_ctx bw;                          /* bufwriter for temp accumulation */
4116 
4117 	duk_int_t token_count;                         /* number of tokens parsed */
4118 	duk_int_t token_limit;                         /* maximum token count before error (sanity backstop) */
4119 
4120 	duk_small_uint_t flags;                        /* lexer flags, use compiler flag defines for now */
4121 };
4122 
4123 /*
4124  *  Prototypes
4125  */
4126 
4127 DUK_INTERNAL_DECL void duk_lexer_initctx(duk_lexer_ctx *lex_ctx);
4128 
4129 DUK_INTERNAL_DECL void duk_lexer_getpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt);
4130 DUK_INTERNAL_DECL void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt);
4131 
4132 DUK_INTERNAL_DECL
4133 void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
4134                                       duk_token *out_token,
4135                                       duk_bool_t strict_mode,
4136                                       duk_bool_t regexp_mode);
4137 #if defined(DUK_USE_REGEXP_SUPPORT)
4138 DUK_INTERNAL_DECL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token);
4139 DUK_INTERNAL_DECL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata);
4140 #endif  /* DUK_USE_REGEXP_SUPPORT */
4141 
4142 #endif  /* DUK_LEXER_H_INCLUDED */
4143 /* #include duk_js_compiler.h */
4144 /*
4145  *  ECMAScript compiler.
4146  */
4147 
4148 #if !defined(DUK_JS_COMPILER_H_INCLUDED)
4149 #define DUK_JS_COMPILER_H_INCLUDED
4150 
4151 /* ECMAScript compiler limits */
4152 #define DUK_COMPILER_TOKEN_LIMIT           100000000L  /* 1e8: protects against deeply nested inner functions */
4153 
4154 /* maximum loopcount for peephole optimization */
4155 #define DUK_COMPILER_PEEPHOLE_MAXITER      3
4156 
4157 /* maximum bytecode length in instructions */
4158 #define DUK_COMPILER_MAX_BYTECODE_LENGTH   (256L * 1024L * 1024L)  /* 1 GB */
4159 
4160 /*
4161  *  Compiler intermediate values
4162  *
4163  *  Intermediate values describe either plain values (e.g. strings or
4164  *  numbers) or binary operations which have not yet been coerced into
4165  *  either a left-hand-side or right-hand-side role (e.g. object property).
4166  */
4167 
4168 #define DUK_IVAL_NONE          0   /* no value */
4169 #define DUK_IVAL_PLAIN         1   /* register, constant, or value */
4170 #define DUK_IVAL_ARITH         2   /* binary arithmetic; DUK_OP_ADD, DUK_OP_EQ, other binary ops */
4171 #define DUK_IVAL_PROP          3   /* property access */
4172 #define DUK_IVAL_VAR           4   /* variable access */
4173 
4174 #define DUK_ISPEC_NONE         0   /* no value */
4175 #define DUK_ISPEC_VALUE        1   /* value resides in 'valstack_idx' */
4176 #define DUK_ISPEC_REGCONST     2   /* value resides in a register or constant */
4177 
4178 /* Bit mask which indicates that a regconst is a constant instead of a register.
4179  * Chosen so that when a regconst is cast to duk_int32_t, all consts are
4180  * negative values.
4181  */
4182 #define DUK_REGCONST_CONST_MARKER    DUK_INT32_MIN  /* = -0x80000000 */
4183 
4184 /* Type to represent a reg/const reference during compilation, with <0
4185  * indicating a constant.  Some call sites also use -1 to indicate 'none'.
4186  */
4187 typedef duk_int32_t duk_regconst_t;
4188 
4189 typedef struct {
4190 	duk_small_uint_t t;          /* DUK_ISPEC_XXX */
4191 	duk_regconst_t regconst;
4192 	duk_idx_t valstack_idx;      /* always set; points to a reserved valstack slot */
4193 } duk_ispec;
4194 
4195 typedef struct {
4196 	/*
4197 	 *  PLAIN: x1
4198 	 *  ARITH: x1 <op> x2
4199 	 *  PROP: x1.x2
4200 	 *  VAR: x1 (name)
4201 	 */
4202 
4203 	/* XXX: can be optimized for smaller footprint esp. on 32-bit environments */
4204 	duk_small_uint_t t;          /* DUK_IVAL_XXX */
4205 	duk_small_uint_t op;         /* bytecode opcode for binary ops */
4206 	duk_ispec x1;
4207 	duk_ispec x2;
4208 } duk_ivalue;
4209 
4210 /*
4211  *  Bytecode instruction representation during compilation
4212  *
4213  *  Contains the actual instruction and (optionally) debug info.
4214  */
4215 
4216 struct duk_compiler_instr {
4217 	duk_instr_t ins;
4218 #if defined(DUK_USE_PC2LINE)
4219 	duk_uint32_t line;
4220 #endif
4221 };
4222 
4223 /*
4224  *  Compiler state
4225  */
4226 
4227 #define DUK_LABEL_FLAG_ALLOW_BREAK       (1U << 0)
4228 #define DUK_LABEL_FLAG_ALLOW_CONTINUE    (1U << 1)
4229 
4230 #define DUK_DECL_TYPE_VAR                0
4231 #define DUK_DECL_TYPE_FUNC               1
4232 
4233 /* XXX: optimize to 16 bytes */
4234 typedef struct {
4235 	duk_small_uint_t flags;
4236 	duk_int_t label_id;          /* numeric label_id (-1 reserved as marker) */
4237 	duk_hstring *h_label;        /* borrowed label name */
4238 	duk_int_t catch_depth;       /* catch depth at point of definition */
4239 	duk_int_t pc_label;          /* pc of label statement:
4240 	                              * pc+1: break jump site
4241 	                              * pc+2: continue jump site
4242 	                              */
4243 
4244 	/* Fast jumps (which avoid longjmp) jump directly to the jump sites
4245 	 * which are always known even while the iteration/switch statement
4246 	 * is still being parsed.  A final peephole pass "straightens out"
4247 	 * the jumps.
4248 	 */
4249 } duk_labelinfo;
4250 
4251 /* Compiling state of one function, eventually converted to duk_hcompfunc */
4252 struct duk_compiler_func {
4253 	/* These pointers are at the start of the struct so that they pack
4254 	 * nicely.  Mixing pointers and integer values is bad on some
4255 	 * platforms (e.g. if int is 32 bits and pointers are 64 bits).
4256 	 */
4257 
4258 	duk_bufwriter_ctx bw_code;          /* bufwriter for code */
4259 
4260 	duk_hstring *h_name;                /* function name (borrowed reference), ends up in _name */
4261 	/* h_code: held in bw_code */
4262 	duk_hobject *h_consts;              /* array */
4263 	duk_hobject *h_funcs;               /* array of function templates: [func1, offset1, line1, func2, offset2, line2]
4264 	                                     * offset/line points to closing brace to allow skipping on pass 2
4265 	                                     */
4266 	duk_hobject *h_decls;               /* array of declarations: [ name1, val1, name2, val2, ... ]
4267 	                                     * valN = (typeN) | (fnum << 8), where fnum is inner func number (0 for vars)
4268 	                                     * record function and variable declarations in pass 1
4269 	                                     */
4270 	duk_hobject *h_labelnames;          /* array of active label names */
4271 	duk_hbuffer_dynamic *h_labelinfos;  /* C array of duk_labelinfo */
4272 	duk_hobject *h_argnames;            /* array of formal argument names (-> _Formals) */
4273 	duk_hobject *h_varmap;              /* variable map for pass 2 (identifier -> register number or null (unmapped)) */
4274 
4275 	/* Value stack indices for tracking objects. */
4276 	/* code_idx: not needed */
4277 	duk_idx_t consts_idx;
4278 	duk_idx_t funcs_idx;
4279 	duk_idx_t decls_idx;
4280 	duk_idx_t labelnames_idx;
4281 	duk_idx_t labelinfos_idx;
4282 	duk_idx_t argnames_idx;
4283 	duk_idx_t varmap_idx;
4284 
4285 	/* Temp reg handling. */
4286 	duk_regconst_t temp_first;           /* first register that is a temporary (below: variables) */
4287 	duk_regconst_t temp_next;            /* next temporary register to allocate */
4288 	duk_regconst_t temp_max;             /* highest value of temp_reg (temp_max - 1 is highest used reg) */
4289 
4290 	/* Shuffle registers if large number of regs/consts. */
4291 	duk_regconst_t shuffle1;
4292 	duk_regconst_t shuffle2;
4293 	duk_regconst_t shuffle3;
4294 
4295 	/* Stats for current expression being parsed. */
4296 	duk_int_t nud_count;
4297 	duk_int_t led_count;
4298 	duk_int_t paren_level;              /* parenthesis count, 0 = top level */
4299 	duk_bool_t expr_lhs;                /* expression is left-hand-side compatible */
4300 	duk_bool_t allow_in;                /* current paren level allows 'in' token */
4301 
4302 	/* Misc. */
4303 	duk_int_t stmt_next;                /* statement id allocation (running counter) */
4304 	duk_int_t label_next;               /* label id allocation (running counter) */
4305 	duk_int_t catch_depth;              /* catch stack depth */
4306 	duk_int_t with_depth;               /* with stack depth (affects identifier lookups) */
4307 	duk_int_t fnum_next;                /* inner function numbering */
4308 	duk_int_t num_formals;              /* number of formal arguments */
4309 	duk_regconst_t reg_stmt_value;      /* register for writing value of 'non-empty' statements (global or eval code), -1 is marker */
4310 #if defined(DUK_USE_DEBUGGER_SUPPORT)
4311 	duk_int_t min_line;                 /* XXX: typing (duk_hcompfunc has duk_uint32_t) */
4312 	duk_int_t max_line;
4313 #endif
4314 
4315 	/* Status booleans. */
4316 	duk_uint8_t is_function;             /* is an actual function (not global/eval code) */
4317 	duk_uint8_t is_eval;                 /* is eval code */
4318 	duk_uint8_t is_global;               /* is global code */
4319 	duk_uint8_t is_namebinding;          /* needs a name binding */
4320 	duk_uint8_t is_constructable;        /* result is constructable */
4321 	duk_uint8_t is_setget;               /* is a setter/getter */
4322 	duk_uint8_t is_strict;               /* function is strict */
4323 	duk_uint8_t is_notail;               /* function must not be tail called */
4324 	duk_uint8_t in_directive_prologue;   /* parsing in "directive prologue", recognize directives */
4325 	duk_uint8_t in_scanning;             /* parsing in "scanning" phase (first pass) */
4326 	duk_uint8_t may_direct_eval;         /* function may call direct eval */
4327 	duk_uint8_t id_access_arguments;     /* function refers to 'arguments' identifier */
4328 	duk_uint8_t id_access_slow;          /* function makes one or more slow path accesses that won't match own static variables */
4329 	duk_uint8_t id_access_slow_own;      /* function makes one or more slow path accesses that may match own static variables */
4330 	duk_uint8_t is_arguments_shadowed;   /* argument/function declaration shadows 'arguments' */
4331 	duk_uint8_t needs_shuffle;           /* function needs shuffle registers */
4332 	duk_uint8_t reject_regexp_in_adv;    /* reject RegExp literal on next advance() call; needed for handling IdentifierName productions */
4333 	duk_uint8_t allow_regexp_in_adv;     /* allow RegExp literal on next advance() call */
4334 };
4335 
4336 struct duk_compiler_ctx {
4337 	duk_hthread *thr;
4338 
4339 	/* filename being compiled (ends up in functions' '_filename' property) */
4340 	duk_hstring *h_filename;            /* borrowed reference */
4341 
4342 	/* lexing (tokenization) state (contains two valstack slot indices) */
4343 	duk_lexer_ctx lex;
4344 
4345 	/* current and previous token for parsing */
4346 	duk_token prev_token;
4347 	duk_token curr_token;
4348 	duk_idx_t tok11_idx;                /* curr_token slot1 (matches 'lex' slot1_idx) */
4349 	duk_idx_t tok12_idx;                /* curr_token slot2 (matches 'lex' slot2_idx) */
4350 	duk_idx_t tok21_idx;                /* prev_token slot1 */
4351 	duk_idx_t tok22_idx;                /* prev_token slot2 */
4352 
4353 	/* recursion limit */
4354 	duk_int_t recursion_depth;
4355 	duk_int_t recursion_limit;
4356 
4357 	/* code emission temporary */
4358 	duk_int_t emit_jumpslot_pc;
4359 
4360 	/* current function being compiled (embedded instead of pointer for more compact access) */
4361 	duk_compiler_func curr_func;
4362 };
4363 
4364 /*
4365  *  Prototypes
4366  */
4367 
4368 DUK_INTERNAL_DECL void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer, duk_size_t src_length, duk_small_uint_t flags);
4369 
4370 #endif  /* DUK_JS_COMPILER_H_INCLUDED */
4371 /* #include duk_regexp.h */
4372 /*
4373  *  Regular expression structs, constants, and bytecode defines.
4374  */
4375 
4376 #if !defined(DUK_REGEXP_H_INCLUDED)
4377 #define DUK_REGEXP_H_INCLUDED
4378 
4379 /* maximum bytecode copies for {n,m} quantifiers */
4380 #define DUK_RE_MAX_ATOM_COPIES             1000
4381 
4382 /* regexp compilation limits */
4383 #define DUK_RE_COMPILE_TOKEN_LIMIT         100000000L   /* 1e8 */
4384 
4385 /* regexp execution limits */
4386 #define DUK_RE_EXECUTE_STEPS_LIMIT         1000000000L  /* 1e9 */
4387 
4388 /* regexp opcodes */
4389 #define DUK_REOP_MATCH                     1
4390 #define DUK_REOP_CHAR                      2
4391 #define DUK_REOP_PERIOD                    3
4392 #define DUK_REOP_RANGES                    4
4393 #define DUK_REOP_INVRANGES                 5
4394 #define DUK_REOP_JUMP                      6
4395 #define DUK_REOP_SPLIT1                    7
4396 #define DUK_REOP_SPLIT2                    8
4397 #define DUK_REOP_SQMINIMAL                 9
4398 #define DUK_REOP_SQGREEDY                  10
4399 #define DUK_REOP_SAVE                      11
4400 #define DUK_REOP_WIPERANGE                 12
4401 #define DUK_REOP_LOOKPOS                   13
4402 #define DUK_REOP_LOOKNEG                   14
4403 #define DUK_REOP_BACKREFERENCE             15
4404 #define DUK_REOP_ASSERT_START              16
4405 #define DUK_REOP_ASSERT_END                17
4406 #define DUK_REOP_ASSERT_WORD_BOUNDARY      18
4407 #define DUK_REOP_ASSERT_NOT_WORD_BOUNDARY  19
4408 
4409 /* flags */
4410 #define DUK_RE_FLAG_GLOBAL                 (1U << 0)
4411 #define DUK_RE_FLAG_IGNORE_CASE            (1U << 1)
4412 #define DUK_RE_FLAG_MULTILINE              (1U << 2)
4413 
4414 struct duk_re_matcher_ctx {
4415 	duk_hthread *thr;
4416 
4417 	duk_uint32_t re_flags;
4418 	const duk_uint8_t *input;
4419 	const duk_uint8_t *input_end;
4420 	const duk_uint8_t *bytecode;
4421 	const duk_uint8_t *bytecode_end;
4422 	const duk_uint8_t **saved;  /* allocated from valstack (fixed buffer) */
4423 	duk_uint32_t nsaved;
4424 	duk_uint32_t recursion_depth;
4425 	duk_uint32_t recursion_limit;
4426 	duk_uint32_t steps_count;
4427 	duk_uint32_t steps_limit;
4428 };
4429 
4430 struct duk_re_compiler_ctx {
4431 	duk_hthread *thr;
4432 
4433 	duk_uint32_t re_flags;
4434 	duk_lexer_ctx lex;
4435 	duk_re_token curr_token;
4436 	duk_bufwriter_ctx bw;
4437 	duk_uint32_t captures;  /* highest capture number emitted so far (used as: ++captures) */
4438 	duk_uint32_t highest_backref;
4439 	duk_uint32_t recursion_depth;
4440 	duk_uint32_t recursion_limit;
4441 	duk_uint32_t nranges;  /* internal temporary value, used for char classes */
4442 };
4443 
4444 /*
4445  *  Prototypes
4446  */
4447 
4448 #if defined(DUK_USE_REGEXP_SUPPORT)
4449 DUK_INTERNAL_DECL void duk_regexp_compile(duk_hthread *thr);
4450 DUK_INTERNAL_DECL void duk_regexp_create_instance(duk_hthread *thr);
4451 DUK_INTERNAL_DECL void duk_regexp_match(duk_hthread *thr);
4452 DUK_INTERNAL_DECL void duk_regexp_match_force_global(duk_hthread *thr);  /* hacky helper for String.prototype.split() */
4453 #endif
4454 
4455 #endif  /* DUK_REGEXP_H_INCLUDED */
4456 /* #include duk_heaphdr.h */
4457 /*
4458  *  Heap header definition and assorted macros, including ref counting.
4459  *  Access all fields through the accessor macros.
4460  */
4461 
4462 #if !defined(DUK_HEAPHDR_H_INCLUDED)
4463 #define DUK_HEAPHDR_H_INCLUDED
4464 
4465 /*
4466  *  Common heap header
4467  *
4468  *  All heap objects share the same flags and refcount fields.  Objects other
4469  *  than strings also need to have a single or double linked list pointers
4470  *  for insertion into the "heap allocated" list.  Strings have single linked
4471  *  list pointers for string table chaining.
4472  *
4473  *  Technically, 'h_refcount' must be wide enough to guarantee that it cannot
4474  *  wrap; otherwise objects might be freed incorrectly after wrapping.  The
4475  *  default refcount field is 32 bits even on 64-bit systems: while that's in
4476  *  theory incorrect, the Duktape heap needs to be larger than 64GB for the
4477  *  count to actually wrap (assuming 16-byte duk_tvals).  This is very unlikely
4478  *  to ever be an issue, but if it is, disabling DUK_USE_REFCOUNT32 causes
4479  *  Duktape to use size_t for refcounts which should always be safe.
4480  *
4481  *  Heap header size on 32-bit platforms: 8 bytes without reference counting,
4482  *  16 bytes with reference counting.
4483  *
4484  *  Note that 'raw' macros such as DUK_HEAPHDR_GET_REFCOUNT() are not
4485  *  defined without DUK_USE_REFERENCE_COUNTING, so caller must #if defined()
4486  *  around them.
4487  */
4488 
4489 /* XXX: macro for shared header fields (avoids some padding issues) */
4490 
4491 struct duk_heaphdr {
4492 	duk_uint32_t h_flags;
4493 
4494 #if defined(DUK_USE_REFERENCE_COUNTING)
4495 #if defined(DUK_USE_ASSERTIONS)
4496 	/* When assertions enabled, used by mark-and-sweep for refcount
4497 	 * validation.  Largest reasonable type; also detects overflows.
4498 	 */
4499 	duk_size_t h_assert_refcount;
4500 #endif
4501 #if defined(DUK_USE_REFCOUNT16)
4502 	duk_uint16_t h_refcount;
4503 #elif defined(DUK_USE_REFCOUNT32)
4504 	duk_uint32_t h_refcount;
4505 #else
4506 	duk_size_t h_refcount;
4507 #endif
4508 #endif  /* DUK_USE_REFERENCE_COUNTING */
4509 
4510 #if defined(DUK_USE_HEAPPTR16)
4511 	duk_uint16_t h_next16;
4512 #else
4513 	duk_heaphdr *h_next;
4514 #endif
4515 
4516 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
4517 	/* refcounting requires direct heap frees, which in turn requires a dual linked heap */
4518 #if defined(DUK_USE_HEAPPTR16)
4519 	duk_uint16_t h_prev16;
4520 #else
4521 	duk_heaphdr *h_prev;
4522 #endif
4523 #endif
4524 
4525 	/* When DUK_USE_HEAPPTR16 (and DUK_USE_REFCOUNT16) is in use, the
4526 	 * struct won't align nicely to 4 bytes.  This 16-bit extra field
4527 	 * is added to make the alignment clean; the field can be used by
4528 	 * heap objects when 16-bit packing is used.  This field is now
4529 	 * conditional to DUK_USE_HEAPPTR16 only, but it is intended to be
4530 	 * used with DUK_USE_REFCOUNT16 and DUK_USE_DOUBLE_LINKED_HEAP;
4531 	 * this only matter to low memory environments anyway.
4532 	 */
4533 #if defined(DUK_USE_HEAPPTR16)
4534 	duk_uint16_t h_extra16;
4535 #endif
4536 };
4537 
4538 struct duk_heaphdr_string {
4539 	/* 16 bits would be enough for shared heaphdr flags and duk_hstring
4540 	 * flags.  The initial parts of duk_heaphdr_string and duk_heaphdr
4541 	 * must match so changing the flags field size here would be quite
4542 	 * awkward.  However, to minimize struct size, we can pack at least
4543 	 * 16 bits of duk_hstring data into the flags field.
4544 	 */
4545 	duk_uint32_t h_flags;
4546 
4547 #if defined(DUK_USE_REFERENCE_COUNTING)
4548 #if defined(DUK_USE_ASSERTIONS)
4549 	/* When assertions enabled, used by mark-and-sweep for refcount
4550 	 * validation.  Largest reasonable type; also detects overflows.
4551 	 */
4552 	duk_size_t h_assert_refcount;
4553 #endif
4554 #if defined(DUK_USE_REFCOUNT16)
4555 	duk_uint16_t h_refcount;
4556 	duk_uint16_t h_strextra16;  /* round out to 8 bytes */
4557 #elif defined(DUK_USE_REFCOUNT32)
4558 	duk_uint32_t h_refcount;
4559 #else
4560 	duk_size_t h_refcount;
4561 #endif
4562 #else
4563 	duk_uint16_t h_strextra16;
4564 #endif  /* DUK_USE_REFERENCE_COUNTING */
4565 
4566 	duk_hstring *h_next;
4567 	/* No 'h_prev' pointer for strings. */
4568 };
4569 
4570 #define DUK_HEAPHDR_FLAGS_TYPE_MASK      0x00000003UL
4571 #define DUK_HEAPHDR_FLAGS_FLAG_MASK      (~DUK_HEAPHDR_FLAGS_TYPE_MASK)
4572 
4573                                              /* 2 bits for heap type */
4574 #define DUK_HEAPHDR_FLAGS_HEAP_START     2   /* 5 heap flags */
4575 #define DUK_HEAPHDR_FLAGS_USER_START     7   /* 25 user flags */
4576 
4577 #define DUK_HEAPHDR_HEAP_FLAG_NUMBER(n)  (DUK_HEAPHDR_FLAGS_HEAP_START + (n))
4578 #define DUK_HEAPHDR_USER_FLAG_NUMBER(n)  (DUK_HEAPHDR_FLAGS_USER_START + (n))
4579 #define DUK_HEAPHDR_HEAP_FLAG(n)         (1UL << (DUK_HEAPHDR_FLAGS_HEAP_START + (n)))
4580 #define DUK_HEAPHDR_USER_FLAG(n)         (1UL << (DUK_HEAPHDR_FLAGS_USER_START + (n)))
4581 
4582 #define DUK_HEAPHDR_FLAG_REACHABLE       DUK_HEAPHDR_HEAP_FLAG(0)  /* mark-and-sweep: reachable */
4583 #define DUK_HEAPHDR_FLAG_TEMPROOT        DUK_HEAPHDR_HEAP_FLAG(1)  /* mark-and-sweep: children not processed */
4584 #define DUK_HEAPHDR_FLAG_FINALIZABLE     DUK_HEAPHDR_HEAP_FLAG(2)  /* mark-and-sweep: finalizable (on current pass) */
4585 #define DUK_HEAPHDR_FLAG_FINALIZED       DUK_HEAPHDR_HEAP_FLAG(3)  /* mark-and-sweep: finalized (on previous pass) */
4586 #define DUK_HEAPHDR_FLAG_READONLY        DUK_HEAPHDR_HEAP_FLAG(4)  /* read-only object, in code section */
4587 
4588 #define DUK_HTYPE_MIN                    0
4589 #define DUK_HTYPE_STRING                 0
4590 #define DUK_HTYPE_OBJECT                 1
4591 #define DUK_HTYPE_BUFFER                 2
4592 #define DUK_HTYPE_MAX                    2
4593 
4594 #if defined(DUK_USE_HEAPPTR16)
4595 #define DUK_HEAPHDR_GET_NEXT(heap,h) \
4596 	((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_next16))
4597 #define DUK_HEAPHDR_SET_NEXT(heap,h,val)   do { \
4598 		(h)->h_next16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) val); \
4599 	} while (0)
4600 #else
4601 #define DUK_HEAPHDR_GET_NEXT(heap,h)  ((h)->h_next)
4602 #define DUK_HEAPHDR_SET_NEXT(heap,h,val)   do { \
4603 		(h)->h_next = (val); \
4604 	} while (0)
4605 #endif
4606 
4607 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
4608 #if defined(DUK_USE_HEAPPTR16)
4609 #define DUK_HEAPHDR_GET_PREV(heap,h) \
4610 	((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_prev16))
4611 #define DUK_HEAPHDR_SET_PREV(heap,h,val)   do { \
4612 		(h)->h_prev16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (val)); \
4613 	} while (0)
4614 #else
4615 #define DUK_HEAPHDR_GET_PREV(heap,h)       ((h)->h_prev)
4616 #define DUK_HEAPHDR_SET_PREV(heap,h,val)   do { \
4617 		(h)->h_prev = (val); \
4618 	} while (0)
4619 #endif
4620 #endif
4621 
4622 #if defined(DUK_USE_REFERENCE_COUNTING)
4623 #define DUK_HEAPHDR_GET_REFCOUNT(h)   ((h)->h_refcount)
4624 #define DUK_HEAPHDR_SET_REFCOUNT(h,val)  do { \
4625 		(h)->h_refcount = (val); \
4626 		DUK_ASSERT((h)->h_refcount == (val));  /* No truncation. */ \
4627 	} while (0)
4628 #define DUK_HEAPHDR_PREINC_REFCOUNT(h)  (++(h)->h_refcount)  /* result: updated refcount */
4629 #define DUK_HEAPHDR_PREDEC_REFCOUNT(h)  (--(h)->h_refcount)  /* result: updated refcount */
4630 #else
4631 /* refcount macros not defined without refcounting, caller must #if defined() now */
4632 #endif  /* DUK_USE_REFERENCE_COUNTING */
4633 
4634 /*
4635  *  Note: type is treated as a field separate from flags, so some masking is
4636  *  involved in the macros below.
4637  */
4638 
4639 #define DUK_HEAPHDR_GET_FLAGS_RAW(h)  ((h)->h_flags)
4640 #define DUK_HEAPHDR_SET_FLAGS_RAW(h,val)  do { \
4641 		(h)->h_flags = (val); } \
4642 	}
4643 #define DUK_HEAPHDR_GET_FLAGS(h)      ((h)->h_flags & DUK_HEAPHDR_FLAGS_FLAG_MASK)
4644 #define DUK_HEAPHDR_SET_FLAGS(h,val)  do { \
4645 		(h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) | (val); \
4646 	} while (0)
4647 #define DUK_HEAPHDR_GET_TYPE(h)       ((h)->h_flags & DUK_HEAPHDR_FLAGS_TYPE_MASK)
4648 #define DUK_HEAPHDR_SET_TYPE(h,val)   do { \
4649 		(h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_TYPE_MASK)) | (val); \
4650 	} while (0)
4651 
4652 /* Comparison for type >= DUK_HTYPE_MIN skipped; because DUK_HTYPE_MIN is zero
4653  * and the comparison is unsigned, it's always true and generates warnings.
4654  */
4655 #define DUK_HEAPHDR_HTYPE_VALID(h)    ( \
4656 	DUK_HEAPHDR_GET_TYPE((h)) <= DUK_HTYPE_MAX \
4657 	)
4658 
4659 #define DUK_HEAPHDR_SET_TYPE_AND_FLAGS(h,tval,fval)  do { \
4660 		(h)->h_flags = ((tval) & DUK_HEAPHDR_FLAGS_TYPE_MASK) | \
4661 		               ((fval) & DUK_HEAPHDR_FLAGS_FLAG_MASK); \
4662 	} while (0)
4663 
4664 #define DUK_HEAPHDR_SET_FLAG_BITS(h,bits)  do { \
4665 		DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \
4666 		(h)->h_flags |= (bits); \
4667 	} while (0)
4668 
4669 #define DUK_HEAPHDR_CLEAR_FLAG_BITS(h,bits)  do { \
4670 		DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \
4671 		(h)->h_flags &= ~((bits)); \
4672 	} while (0)
4673 
4674 #define DUK_HEAPHDR_CHECK_FLAG_BITS(h,bits)  (((h)->h_flags & (bits)) != 0)
4675 
4676 #define DUK_HEAPHDR_SET_REACHABLE(h)      DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
4677 #define DUK_HEAPHDR_CLEAR_REACHABLE(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
4678 #define DUK_HEAPHDR_HAS_REACHABLE(h)      DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
4679 
4680 #define DUK_HEAPHDR_SET_TEMPROOT(h)       DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
4681 #define DUK_HEAPHDR_CLEAR_TEMPROOT(h)     DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
4682 #define DUK_HEAPHDR_HAS_TEMPROOT(h)       DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
4683 
4684 #define DUK_HEAPHDR_SET_FINALIZABLE(h)    DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
4685 #define DUK_HEAPHDR_CLEAR_FINALIZABLE(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
4686 #define DUK_HEAPHDR_HAS_FINALIZABLE(h)    DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
4687 
4688 #define DUK_HEAPHDR_SET_FINALIZED(h)      DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
4689 #define DUK_HEAPHDR_CLEAR_FINALIZED(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
4690 #define DUK_HEAPHDR_HAS_FINALIZED(h)      DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
4691 
4692 #define DUK_HEAPHDR_SET_READONLY(h)       DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
4693 #define DUK_HEAPHDR_CLEAR_READONLY(h)     DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
4694 #define DUK_HEAPHDR_HAS_READONLY(h)       DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
4695 
4696 /* get or set a range of flags; m=first bit number, n=number of bits */
4697 #define DUK_HEAPHDR_GET_FLAG_RANGE(h,m,n)  (((h)->h_flags >> (m)) & ((1UL << (n)) - 1UL))
4698 
4699 #define DUK_HEAPHDR_SET_FLAG_RANGE(h,m,n,v)  do { \
4700 		(h)->h_flags = \
4701 			((h)->h_flags & (~(((1UL << (n)) - 1UL) << (m)))) \
4702 			| ((v) << (m)); \
4703 	} while (0)
4704 
4705 /* init pointer fields to null */
4706 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
4707 #define DUK_HEAPHDR_INIT_NULLS(h)       do { \
4708 		DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \
4709 		DUK_HEAPHDR_SET_PREV((h), (void *) NULL); \
4710 	} while (0)
4711 #else
4712 #define DUK_HEAPHDR_INIT_NULLS(h)       do { \
4713 		DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \
4714 	} while (0)
4715 #endif
4716 
4717 #define DUK_HEAPHDR_STRING_INIT_NULLS(h)  do { \
4718 		(h)->h_next = NULL; \
4719 	} while (0)
4720 
4721 /*
4722  *  Type tests
4723  */
4724 
4725 /* Take advantage of the fact that for DUK_HTYPE_xxx numbers the lowest bit
4726  * is only set for DUK_HTYPE_OBJECT (= 1).
4727  */
4728 #if 0
4729 #define DUK_HEAPHDR_IS_OBJECT(h) (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_OBJECT)
4730 #endif
4731 #define DUK_HEAPHDR_IS_OBJECT(h) ((h)->h_flags & 0x01UL)
4732 #define DUK_HEAPHDR_IS_STRING(h) (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_STRING)
4733 #define DUK_HEAPHDR_IS_BUFFER(h) (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_BUFFER)
4734 
4735 /*
4736  *  Assert helpers
4737  */
4738 
4739 /* Check that prev/next links are consistent: if e.g. h->prev is != NULL,
4740  * h->prev->next should point back to h.
4741  */
4742 #if defined(DUK_USE_ASSERTIONS)
4743 DUK_INTERNAL_DECL void duk_heaphdr_assert_valid_subclassed(duk_heaphdr *h);
4744 DUK_INTERNAL_DECL void duk_heaphdr_assert_links(duk_heap *heap, duk_heaphdr *h);
4745 DUK_INTERNAL_DECL void duk_heaphdr_assert_valid(duk_heaphdr *h);
4746 #define DUK_HEAPHDR_ASSERT_LINKS(heap,h)  do { duk_heaphdr_assert_links((heap), (h)); } while (0)
4747 #define DUK_HEAPHDR_ASSERT_VALID(h)  do { duk_heaphdr_assert_valid((h)); } while (0)
4748 #else
4749 #define DUK_HEAPHDR_ASSERT_LINKS(heap,h)  do {} while (0)
4750 #define DUK_HEAPHDR_ASSERT_VALID(h)  do {} while (0)
4751 #endif
4752 
4753 #endif  /* DUK_HEAPHDR_H_INCLUDED */
4754 /* #include duk_refcount.h */
4755 /*
4756  *  Reference counting helper macros.  The macros take a thread argument
4757  *  and must thus always be executed in a specific thread context.  The
4758  *  thread argument is not really needed anymore: DECREF can operate with
4759  *  a heap pointer only, and INCREF needs neither.
4760  */
4761 
4762 #if !defined(DUK_REFCOUNT_H_INCLUDED)
4763 #define DUK_REFCOUNT_H_INCLUDED
4764 
4765 #if defined(DUK_USE_REFERENCE_COUNTING)
4766 
4767 #if defined(DUK_USE_ROM_OBJECTS)
4768 /* With ROM objects "needs refcount update" is true when the value is
4769  * heap allocated and is not a ROM object.
4770  */
4771 /* XXX: double evaluation for 'tv' argument. */
4772 #define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) \
4773 	(DUK_TVAL_IS_HEAP_ALLOCATED((tv)) && !DUK_HEAPHDR_HAS_READONLY(DUK_TVAL_GET_HEAPHDR((tv))))
4774 #define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h)  (!DUK_HEAPHDR_HAS_READONLY((h)))
4775 #else  /* DUK_USE_ROM_OBJECTS */
4776 /* Without ROM objects "needs refcount update" == is heap allocated. */
4777 #define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)    DUK_TVAL_IS_HEAP_ALLOCATED((tv))
4778 #define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h)  1
4779 #endif  /* DUK_USE_ROM_OBJECTS */
4780 
4781 /* Fast variants, inline refcount operations except for refzero handling.
4782  * Can be used explicitly when speed is always more important than size.
4783  * For a good compiler and a single file build, these are basically the
4784  * same as a forced inline.
4785  */
4786 #define DUK_TVAL_INCREF_FAST(thr,tv) do { \
4787 		duk_tval *duk__tv = (tv); \
4788 		DUK_ASSERT(duk__tv != NULL); \
4789 		if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
4790 			duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
4791 			DUK_ASSERT(duk__h != NULL); \
4792 			DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4793 			DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \
4794 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) != 0);  /* No wrapping. */ \
4795 		} \
4796 	} while (0)
4797 #define DUK_TVAL_DECREF_FAST(thr,tv) do { \
4798 		duk_tval *duk__tv = (tv); \
4799 		DUK_ASSERT(duk__tv != NULL); \
4800 		if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
4801 			duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
4802 			DUK_ASSERT(duk__h != NULL); \
4803 			DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4804 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
4805 			if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
4806 				duk_heaphdr_refzero((thr), duk__h); \
4807 			} \
4808 		} \
4809 	} while (0)
4810 #define DUK_TVAL_DECREF_NORZ_FAST(thr,tv) do { \
4811 		duk_tval *duk__tv = (tv); \
4812 		DUK_ASSERT(duk__tv != NULL); \
4813 		if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
4814 			duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
4815 			DUK_ASSERT(duk__h != NULL); \
4816 			DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4817 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
4818 			if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
4819 				duk_heaphdr_refzero_norz((thr), duk__h); \
4820 			} \
4821 		} \
4822 	} while (0)
4823 #define DUK_HEAPHDR_INCREF_FAST(thr,h) do { \
4824 		duk_heaphdr *duk__h = (duk_heaphdr *) (h); \
4825 		DUK_ASSERT(duk__h != NULL); \
4826 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4827 		if (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \
4828 			DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \
4829 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) != 0);  /* No wrapping. */ \
4830 		} \
4831 	} while (0)
4832 #define DUK_HEAPHDR_DECREF_FAST_RAW(thr,h,rzcall,rzcast) do { \
4833 		duk_heaphdr *duk__h = (duk_heaphdr *) (h); \
4834 		DUK_ASSERT(duk__h != NULL); \
4835 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4836 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
4837 		if (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \
4838 			if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
4839 				(rzcall)((thr), (rzcast) duk__h); \
4840 			} \
4841 		} \
4842 	} while (0)
4843 #define DUK_HEAPHDR_DECREF_FAST(thr,h) \
4844 	DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero,duk_heaphdr *)
4845 #define DUK_HEAPHDR_DECREF_NORZ_FAST(thr,h) \
4846 	DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero_norz,duk_heaphdr *)
4847 
4848 /* Slow variants, call to a helper to reduce code size.
4849  * Can be used explicitly when size is always more important than speed.
4850  */
4851 #define DUK_TVAL_INCREF_SLOW(thr,tv)         do { duk_tval_incref((tv)); } while (0)
4852 #define DUK_TVAL_DECREF_SLOW(thr,tv)         do { duk_tval_decref((thr), (tv)); } while (0)
4853 #define DUK_TVAL_DECREF_NORZ_SLOW(thr,tv)    do { duk_tval_decref_norz((thr), (tv)); } while (0)
4854 #define DUK_HEAPHDR_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
4855 #define DUK_HEAPHDR_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
4856 #define DUK_HEAPHDR_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
4857 #define DUK_HSTRING_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
4858 #define DUK_HSTRING_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
4859 #define DUK_HSTRING_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
4860 #define DUK_HBUFFER_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
4861 #define DUK_HBUFFER_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
4862 #define DUK_HBUFFER_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
4863 #define DUK_HOBJECT_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
4864 #define DUK_HOBJECT_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
4865 #define DUK_HOBJECT_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
4866 
4867 /* Default variants.  Selection depends on speed/size preference.
4868  * Concretely: with gcc 4.8.1 -Os x64 the difference in final binary
4869  * is about +1kB for _FAST variants.
4870  */
4871 #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
4872 /* XXX: It would be nice to specialize for specific duk_hobject subtypes
4873  * but current refzero queue handling prevents that.
4874  */
4875 #define DUK_TVAL_INCREF(thr,tv)                DUK_TVAL_INCREF_FAST((thr),(tv))
4876 #define DUK_TVAL_DECREF(thr,tv)                DUK_TVAL_DECREF_FAST((thr),(tv))
4877 #define DUK_TVAL_DECREF_NORZ(thr,tv)           DUK_TVAL_DECREF_NORZ_FAST((thr),(tv))
4878 #define DUK_HEAPHDR_INCREF(thr,h)              DUK_HEAPHDR_INCREF_FAST((thr),(h))
4879 #define DUK_HEAPHDR_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero,duk_heaphdr *)
4880 #define DUK_HEAPHDR_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero_norz,duk_heaphdr *)
4881 #define DUK_HSTRING_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4882 #define DUK_HSTRING_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hstring_refzero,duk_hstring *)
4883 #define DUK_HSTRING_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hstring_refzero,duk_hstring *)  /* no 'norz' variant */
4884 #define DUK_HOBJECT_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4885 #define DUK_HOBJECT_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4886 #define DUK_HOBJECT_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4887 #define DUK_HBUFFER_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4888 #define DUK_HBUFFER_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hbuffer_refzero,duk_hbuffer *)
4889 #define DUK_HBUFFER_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hbuffer_refzero,duk_hbuffer *)  /* no 'norz' variant */
4890 #define DUK_HCOMPFUNC_INCREF(thr,h)            DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4891 #define DUK_HCOMPFUNC_DECREF(thr,h)            DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4892 #define DUK_HCOMPFUNC_DECREF_NORZ(thr,h)       DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4893 #define DUK_HNATFUNC_INCREF(thr,h)             DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4894 #define DUK_HNATFUNC_DECREF(thr,h)             DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4895 #define DUK_HNATFUNC_DECREF_NORZ(thr,h)        DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4896 #define DUK_HBUFOBJ_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4897 #define DUK_HBUFOBJ_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4898 #define DUK_HBUFOBJ_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4899 #define DUK_HTHREAD_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4900 #define DUK_HTHREAD_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4901 #define DUK_HTHREAD_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4902 #else
4903 #define DUK_TVAL_INCREF(thr,tv)                DUK_TVAL_INCREF_SLOW((thr),(tv))
4904 #define DUK_TVAL_DECREF(thr,tv)                DUK_TVAL_DECREF_SLOW((thr),(tv))
4905 #define DUK_TVAL_DECREF_NORZ(thr,tv)           DUK_TVAL_DECREF_NORZ_SLOW((thr),(tv))
4906 #define DUK_HEAPHDR_INCREF(thr,h)              DUK_HEAPHDR_INCREF_SLOW((thr),(h))
4907 #define DUK_HEAPHDR_DECREF(thr,h)              DUK_HEAPHDR_DECREF_SLOW((thr),(h))
4908 #define DUK_HEAPHDR_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_NORZ_SLOW((thr),(h))
4909 #define DUK_HSTRING_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4910 #define DUK_HSTRING_DECREF(thr,h)              DUK_HSTRING_DECREF_SLOW((thr),(h))
4911 #define DUK_HSTRING_DECREF_NORZ(thr,h)         DUK_HSTRING_DECREF_NORZ_SLOW((thr),(h))
4912 #define DUK_HOBJECT_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4913 #define DUK_HOBJECT_DECREF(thr,h)              DUK_HOBJECT_DECREF_SLOW((thr),(h))
4914 #define DUK_HOBJECT_DECREF_NORZ(thr,h)         DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(h))
4915 #define DUK_HBUFFER_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4916 #define DUK_HBUFFER_DECREF(thr,h)              DUK_HBUFFER_DECREF_SLOW((thr),(h))
4917 #define DUK_HBUFFER_DECREF_NORZ(thr,h)         DUK_HBUFFER_DECREF_NORZ_SLOW((thr),(h))
4918 #define DUK_HCOMPFUNC_INCREF(thr,h)            DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4919 #define DUK_HCOMPFUNC_DECREF(thr,h)            DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
4920 #define DUK_HCOMPFUNC_DECREF_NORZ(thr,h)       DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
4921 #define DUK_HNATFUNC_INCREF(thr,h)             DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4922 #define DUK_HNATFUNC_DECREF(thr,h)             DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
4923 #define DUK_HNATFUNC_DECREF_NORZ(thr,h)        DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
4924 #define DUK_HBUFOBJ_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4925 #define DUK_HBUFOBJ_DECREF(thr,h)              DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
4926 #define DUK_HBUFOB_DECREF_NORZ(thr,h)          DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
4927 #define DUK_HTHREAD_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4928 #define DUK_HTHREAD_DECREF(thr,h)              DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
4929 #define DUK_HTHREAD_DECREF_NORZ(thr,h)         DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
4930 #endif
4931 
4932 /* Convenience for some situations; the above macros don't allow NULLs
4933  * for performance reasons.  Macros cover only actually needed cases.
4934  */
4935 #define DUK_HEAPHDR_INCREF_ALLOWNULL(thr,h) do { \
4936 		if ((h) != NULL) { \
4937 			DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h)); \
4938 		} \
4939 	} while (0)
4940 #define DUK_HEAPHDR_DECREF_ALLOWNULL(thr,h) do { \
4941 		if ((h) != NULL) { \
4942 			DUK_HEAPHDR_DECREF((thr), (duk_heaphdr *) (h)); \
4943 		} \
4944 	} while (0)
4945 #define DUK_HEAPHDR_DECREF_NORZ_ALLOWNULL(thr,h) do { \
4946 		if ((h) != NULL) { \
4947 			DUK_HEAPHDR_DECREF_NORZ((thr), (duk_heaphdr *) (h)); \
4948 		} \
4949 	} while (0)
4950 #define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h) do { \
4951 		if ((h) != NULL) { \
4952 			DUK_HOBJECT_INCREF((thr), (h)); \
4953 		} \
4954 	} while (0)
4955 #define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h) do { \
4956 		if ((h) != NULL) { \
4957 			DUK_HOBJECT_DECREF((thr), (h)); \
4958 		} \
4959 	} while (0)
4960 #define DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr,h) do { \
4961 		if ((h) != NULL) { \
4962 			DUK_HOBJECT_DECREF_NORZ((thr), (h)); \
4963 		} \
4964 	} while (0)
4965 #define DUK_HBUFFER_INCREF_ALLOWNULL(thr,h) do { \
4966 		if ((h) != NULL) { \
4967 			DUK_HBUFFER_INCREF((thr), (h)); \
4968 		} \
4969 	} while (0)
4970 #define DUK_HBUFFER_DECREF_ALLOWNULL(thr,h) do { \
4971 		if ((h) != NULL) { \
4972 			DUK_HBUFFER_DECREF((thr), (h)); \
4973 		} \
4974 	} while (0)
4975 #define DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr,h) do { \
4976 		if ((h) != NULL) { \
4977 			DUK_HBUFFER_DECREF_NORZ((thr), (h)); \
4978 		} \
4979 	} while (0)
4980 #define DUK_HTHREAD_INCREF_ALLOWNULL(thr,h) do { \
4981 		if ((h) != NULL) { \
4982 			DUK_HTHREAD_INCREF((thr), (h)); \
4983 		} \
4984 	} while (0)
4985 #define DUK_HTHREAD_DECREF_ALLOWNULL(thr,h) do { \
4986 		if ((h) != NULL) { \
4987 			DUK_HTHREAD_DECREF((thr), (h)); \
4988 		} \
4989 	} while (0)
4990 #define DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr,h) do { \
4991 		if ((h) != NULL) { \
4992 			DUK_HTHREAD_DECREF_NORZ((thr), (h)); \
4993 		} \
4994 	} while (0)
4995 
4996 /* Called after one or more DECREF NORZ calls to handle pending side effects.
4997  * At present DECREF NORZ does freeing inline but doesn't execute finalizers,
4998  * so these macros check for pending finalizers and execute them.  The FAST
4999  * variant is performance critical.
5000  */
5001 #if defined(DUK_USE_FINALIZER_SUPPORT)
5002 #define DUK_REFZERO_CHECK_FAST(thr) do { \
5003 		duk_refzero_check_fast((thr)); \
5004 	} while (0)
5005 #define DUK_REFZERO_CHECK_SLOW(thr) do { \
5006 		duk_refzero_check_slow((thr)); \
5007 	} while (0)
5008 #else  /* DUK_USE_FINALIZER_SUPPORT */
5009 #define DUK_REFZERO_CHECK_FAST(thr) do { } while (0)
5010 #define DUK_REFZERO_CHECK_SLOW(thr) do { } while (0)
5011 #endif  /* DUK_USE_FINALIZER_SUPPORT */
5012 
5013 /*
5014  *  Macros to set a duk_tval and update refcount of the target (decref the
5015  *  old value and incref the new value if necessary).  This is both performance
5016  *  and footprint critical; any changes made should be measured for size/speed.
5017  */
5018 
5019 #define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \
5020 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5021 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5022 		DUK_TVAL_SET_UNDEFINED(tv__dst); \
5023 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5024 	} while (0)
5025 
5026 #define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ_ALT0(thr,tvptr_dst) do { \
5027 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5028 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5029 		DUK_TVAL_SET_UNDEFINED(tv__dst); \
5030 		DUK_TVAL_DECREF_NORZ((thr), &tv__tmp); \
5031 	} while (0)
5032 
5033 #define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \
5034 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5035 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5036 		DUK_TVAL_SET_UNUSED(tv__dst); \
5037 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5038 	} while (0)
5039 
5040 #define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \
5041 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5042 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5043 		DUK_TVAL_SET_NULL(tv__dst); \
5044 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5045 	} while (0)
5046 
5047 #define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5048 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5049 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5050 		DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \
5051 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5052 	} while (0)
5053 
5054 #define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5055 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5056 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5057 		DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \
5058 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5059 	} while (0)
5060 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5061 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5062 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5063 		DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv__dst, (newval)); \
5064 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5065 	} while (0)
5066 #define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5067 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5068 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5069 		DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \
5070 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5071 	} while (0)
5072 #define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \
5073 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5074 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5075 		DUK_TVAL_SET_NAN(tv__dst); \
5076 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5077 	} while (0)
5078 #if defined(DUK_USE_FASTINT)
5079 #define DUK_TVAL_SET_I48_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5080 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5081 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5082 		DUK_TVAL_SET_I48(tv__dst, (newval)); \
5083 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5084 	} while (0)
5085 #define DUK_TVAL_SET_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5086 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5087 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5088 		DUK_TVAL_SET_I32(tv__dst, (newval)); \
5089 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5090 	} while (0)
5091 #define DUK_TVAL_SET_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5092 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5093 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5094 		DUK_TVAL_SET_U32(tv__dst, (newval)); \
5095 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5096 	} while (0)
5097 #else
5098 #define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \
5099 	DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval))
5100 #endif  /* DUK_USE_FASTINT */
5101 
5102 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \
5103 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5104 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5105 		DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \
5106 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5107 	} while (0)
5108 
5109 #define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5110 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5111 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5112 		DUK_TVAL_SET_STRING(tv__dst, (newval)); \
5113 		DUK_HSTRING_INCREF((thr), (newval)); \
5114 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5115 	} while (0)
5116 
5117 #define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5118 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5119 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5120 		DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \
5121 		DUK_HOBJECT_INCREF((thr), (newval)); \
5122 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5123 	} while (0)
5124 
5125 #define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5126 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5127 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5128 		DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \
5129 		DUK_HBUFFER_INCREF((thr), (newval)); \
5130 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5131 	} while (0)
5132 
5133 #define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5134 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5135 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5136 		DUK_TVAL_SET_POINTER(tv__dst, (newval)); \
5137 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5138 	} while (0)
5139 
5140 /* DUK_TVAL_SET_TVAL_UPDREF() is used a lot in executor, property lookups,
5141  * etc, so it's very important for performance.  Measure when changing.
5142  *
5143  * NOTE: the source and destination duk_tval pointers may be the same, and
5144  * the macros MUST deal with that correctly.
5145  */
5146 
5147 /* Original idiom used, minimal code size. */
5148 #define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \
5149 		duk_tval *tv__dst, *tv__src; duk_tval tv__tmp; \
5150 		tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
5151 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5152 		DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
5153 		DUK_TVAL_INCREF((thr), tv__src); \
5154 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5155 	} while (0)
5156 
5157 /* Faster alternative: avoid making a temporary copy of tvptr_dst and use
5158  * fast incref/decref macros.
5159  */
5160 #define DUK_TVAL_SET_TVAL_UPDREF_ALT1(thr,tvptr_dst,tvptr_src) do { \
5161 		duk_tval *tv__dst, *tv__src; duk_heaphdr *h__obj; \
5162 		tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
5163 		DUK_TVAL_INCREF_FAST((thr), tv__src); \
5164 		if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv__dst)) { \
5165 			h__obj = DUK_TVAL_GET_HEAPHDR(tv__dst); \
5166 			DUK_ASSERT(h__obj != NULL); \
5167 			DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
5168 			DUK_HEAPHDR_DECREF_FAST((thr), h__obj);  /* side effects */ \
5169 		} else { \
5170 			DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
5171 		} \
5172 	} while (0)
5173 
5174 /* XXX: no optimized variants yet */
5175 #define DUK_TVAL_SET_UNDEFINED_UPDREF         DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
5176 #define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ    DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ_ALT0
5177 #define DUK_TVAL_SET_UNUSED_UPDREF            DUK_TVAL_SET_UNUSED_UPDREF_ALT0
5178 #define DUK_TVAL_SET_NULL_UPDREF              DUK_TVAL_SET_NULL_UPDREF_ALT0
5179 #define DUK_TVAL_SET_BOOLEAN_UPDREF           DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
5180 #define DUK_TVAL_SET_NUMBER_UPDREF            DUK_TVAL_SET_NUMBER_UPDREF_ALT0
5181 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF    DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
5182 #define DUK_TVAL_SET_DOUBLE_UPDREF            DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
5183 #define DUK_TVAL_SET_NAN_UPDREF               DUK_TVAL_SET_NAN_UPDREF_ALT0
5184 #if defined(DUK_USE_FASTINT)
5185 #define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_I48_UPDREF_ALT0
5186 #define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_I32_UPDREF_ALT0
5187 #define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_U32_UPDREF_ALT0
5188 #else
5189 #define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF  /* XXX: fast int-to-double */
5190 #define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF
5191 #define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF
5192 #endif  /* DUK_USE_FASTINT */
5193 #define DUK_TVAL_SET_FASTINT_UPDREF           DUK_TVAL_SET_I48_UPDREF  /* convenience */
5194 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF         DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
5195 #define DUK_TVAL_SET_STRING_UPDREF            DUK_TVAL_SET_STRING_UPDREF_ALT0
5196 #define DUK_TVAL_SET_OBJECT_UPDREF            DUK_TVAL_SET_OBJECT_UPDREF_ALT0
5197 #define DUK_TVAL_SET_BUFFER_UPDREF            DUK_TVAL_SET_BUFFER_UPDREF_ALT0
5198 #define DUK_TVAL_SET_POINTER_UPDREF           DUK_TVAL_SET_POINTER_UPDREF_ALT0
5199 
5200 #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
5201 /* Optimized for speed. */
5202 #define DUK_TVAL_SET_TVAL_UPDREF              DUK_TVAL_SET_TVAL_UPDREF_ALT1
5203 #define DUK_TVAL_SET_TVAL_UPDREF_FAST         DUK_TVAL_SET_TVAL_UPDREF_ALT1
5204 #define DUK_TVAL_SET_TVAL_UPDREF_SLOW         DUK_TVAL_SET_TVAL_UPDREF_ALT0
5205 #else
5206 /* Optimized for size. */
5207 #define DUK_TVAL_SET_TVAL_UPDREF              DUK_TVAL_SET_TVAL_UPDREF_ALT0
5208 #define DUK_TVAL_SET_TVAL_UPDREF_FAST         DUK_TVAL_SET_TVAL_UPDREF_ALT0
5209 #define DUK_TVAL_SET_TVAL_UPDREF_SLOW         DUK_TVAL_SET_TVAL_UPDREF_ALT0
5210 #endif
5211 
5212 #else  /* DUK_USE_REFERENCE_COUNTING */
5213 
5214 #define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)     0
5215 #define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h)   0
5216 
5217 #define DUK_TVAL_INCREF_FAST(thr,v)            do {} while (0) /* nop */
5218 #define DUK_TVAL_DECREF_FAST(thr,v)            do {} while (0) /* nop */
5219 #define DUK_TVAL_DECREF_NORZ_FAST(thr,v)       do {} while (0) /* nop */
5220 #define DUK_TVAL_INCREF_SLOW(thr,v)            do {} while (0) /* nop */
5221 #define DUK_TVAL_DECREF_SLOW(thr,v)            do {} while (0) /* nop */
5222 #define DUK_TVAL_DECREF_NORZ_SLOW(thr,v)       do {} while (0) /* nop */
5223 #define DUK_TVAL_INCREF(thr,v)                 do {} while (0) /* nop */
5224 #define DUK_TVAL_DECREF(thr,v)                 do {} while (0) /* nop */
5225 #define DUK_TVAL_DECREF_NORZ(thr,v)            do {} while (0) /* nop */
5226 #define DUK_HEAPHDR_INCREF_FAST(thr,h)         do {} while (0) /* nop */
5227 #define DUK_HEAPHDR_DECREF_FAST(thr,h)         do {} while (0) /* nop */
5228 #define DUK_HEAPHDR_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */
5229 #define DUK_HEAPHDR_INCREF_SLOW(thr,h)         do {} while (0) /* nop */
5230 #define DUK_HEAPHDR_DECREF_SLOW(thr,h)         do {} while (0) /* nop */
5231 #define DUK_HEAPHDR_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */
5232 #define DUK_HEAPHDR_INCREF(thr,h)              do {} while (0) /* nop */
5233 #define DUK_HEAPHDR_DECREF(thr,h)              do {} while (0) /* nop */
5234 #define DUK_HEAPHDR_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5235 #define DUK_HSTRING_INCREF_FAST(thr,h)         do {} while (0) /* nop */
5236 #define DUK_HSTRING_DECREF_FAST(thr,h)         do {} while (0) /* nop */
5237 #define DUK_HSTRING_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */
5238 #define DUK_HSTRING_INCREF_SLOW(thr,h)         do {} while (0) /* nop */
5239 #define DUK_HSTRING_DECREF_SLOW(thr,h)         do {} while (0) /* nop */
5240 #define DUK_HSTRING_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */
5241 #define DUK_HSTRING_INCREF(thr,h)              do {} while (0) /* nop */
5242 #define DUK_HSTRING_DECREF(thr,h)              do {} while (0) /* nop */
5243 #define DUK_HSTRING_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5244 #define DUK_HOBJECT_INCREF_FAST(thr,h)         do {} while (0) /* nop */
5245 #define DUK_HOBJECT_DECREF_FAST(thr,h)         do {} while (0) /* nop */
5246 #define DUK_HOBJECT_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */
5247 #define DUK_HOBJECT_INCREF_SLOW(thr,h)         do {} while (0) /* nop */
5248 #define DUK_HOBJECT_DECREF_SLOW(thr,h)         do {} while (0) /* nop */
5249 #define DUK_HOBJECT_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */
5250 #define DUK_HOBJECT_INCREF(thr,h)              do {} while (0) /* nop */
5251 #define DUK_HOBJECT_DECREF(thr,h)              do {} while (0) /* nop */
5252 #define DUK_HOBJECT_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5253 #define DUK_HBUFFER_INCREF_FAST(thr,h)         do {} while (0) /* nop */
5254 #define DUK_HBUFFER_DECREF_FAST(thr,h)         do {} while (0) /* nop */
5255 #define DUK_HBUFFER_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */
5256 #define DUK_HBUFFER_INCREF_SLOW(thr,h)         do {} while (0) /* nop */
5257 #define DUK_HBUFFER_DECREF_SLOW(thr,h)         do {} while (0) /* nop */
5258 #define DUK_HBUFFER_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */
5259 #define DUK_HBUFFER_INCREF(thr,h)              do {} while (0) /* nop */
5260 #define DUK_HBUFFER_DECREF(thr,h)              do {} while (0) /* nop */
5261 #define DUK_HBUFFER_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5262 
5263 #define DUK_HCOMPFUNC_INCREF(thr,h)            do {} while (0) /* nop */
5264 #define DUK_HCOMPFUNC_DECREF(thr,h)            do {} while (0) /* nop */
5265 #define DUK_HCOMPFUNC_DECREF_NORZ(thr,h)       do {} while (0) /* nop */
5266 #define DUK_HNATFUNC_INCREF(thr,h)             do {} while (0) /* nop */
5267 #define DUK_HNATFUNC_DECREF(thr,h)             do {} while (0) /* nop */
5268 #define DUK_HNATFUNC_DECREF_NORZ(thr,h)        do {} while (0) /* nop */
5269 #define DUK_HBUFOBJ_INCREF(thr,h)              do {} while (0) /* nop */
5270 #define DUK_HBUFOBJ_DECREF(thr,h)              do {} while (0) /* nop */
5271 #define DUK_HBUFOBJ_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5272 #define DUK_HTHREAD_INCREF(thr,h)              do {} while (0) /* nop */
5273 #define DUK_HTHREAD_DECREF(thr,h)              do {} while (0) /* nop */
5274 #define DUK_HTHREAD_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5275 #define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
5276 #define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
5277 #define DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr,h)  do {} while (0) /* nop */
5278 #define DUK_HBUFFER_INCREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
5279 #define DUK_HBUFFER_DECREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
5280 #define DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr,h)  do {} while (0) /* nop */
5281 
5282 #define DUK_REFZERO_CHECK_FAST(thr)            do {} while (0) /* nop */
5283 #define DUK_REFZERO_CHECK_SLOW(thr)            do {} while (0) /* nop */
5284 
5285 #define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \
5286 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5287 		DUK_TVAL_SET_UNDEFINED(tv__dst); \
5288 		DUK_UNREF((thr)); \
5289 	} while (0)
5290 
5291 #define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \
5292 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5293 		DUK_TVAL_SET_UNUSED(tv__dst); \
5294 		DUK_UNREF((thr)); \
5295 	} while (0)
5296 
5297 #define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \
5298 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5299 		DUK_TVAL_SET_NULL(tv__dst); \
5300 		DUK_UNREF((thr)); \
5301 	} while (0)
5302 
5303 #define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5304 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5305 		DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \
5306 		DUK_UNREF((thr)); \
5307 	} while (0)
5308 
5309 #define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5310 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5311 		DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \
5312 		DUK_UNREF((thr)); \
5313 	} while (0)
5314 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5315 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5316 		DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv__dst, (newval)); \
5317 		DUK_UNREF((thr)); \
5318 	} while (0)
5319 #define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5320 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5321 		DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \
5322 		DUK_UNREF((thr)); \
5323 	} while (0)
5324 #define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \
5325 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5326 		DUK_TVAL_SET_NAN(tv__dst); \
5327 		DUK_UNREF((thr)); \
5328 	} while (0)
5329 #if defined(DUK_USE_FASTINT)
5330 #define DUK_TVAL_SET_I48_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5331 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5332 		DUK_TVAL_SET_I48(tv__dst, (newval)); \
5333 		DUK_UNREF((thr)); \
5334 	} while (0)
5335 #define DUK_TVAL_SET_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5336 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5337 		DUK_TVAL_SET_I32(tv__dst, (newval)); \
5338 		DUK_UNREF((thr)); \
5339 	} while (0)
5340 #define DUK_TVAL_SET_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5341 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5342 		DUK_TVAL_SET_U32(tv__dst, (newval)); \
5343 		DUK_UNREF((thr)); \
5344 	} while (0)
5345 #else
5346 #define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \
5347 	DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval))
5348 #endif  /* DUK_USE_FASTINT */
5349 
5350 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \
5351 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5352 		DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \
5353 		DUK_UNREF((thr)); \
5354 	} while (0)
5355 
5356 #define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5357 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5358 		DUK_TVAL_SET_STRING(tv__dst, (newval)); \
5359 		DUK_UNREF((thr)); \
5360 	} while (0)
5361 
5362 #define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5363 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5364 		DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \
5365 		DUK_UNREF((thr)); \
5366 	} while (0)
5367 
5368 #define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5369 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5370 		DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \
5371 		DUK_UNREF((thr)); \
5372 	} while (0)
5373 
5374 #define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5375 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5376 		DUK_TVAL_SET_POINTER(tv__dst, (newval)); \
5377 		DUK_UNREF((thr)); \
5378 	} while (0)
5379 
5380 #define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \
5381 		duk_tval *tv__dst, *tv__src; \
5382 		tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
5383 		DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
5384 		DUK_UNREF((thr)); \
5385 	} while (0)
5386 
5387 #define DUK_TVAL_SET_UNDEFINED_UPDREF         DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
5388 #define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ    DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
5389 #define DUK_TVAL_SET_UNUSED_UPDREF            DUK_TVAL_SET_UNUSED_UPDREF_ALT0
5390 #define DUK_TVAL_SET_NULL_UPDREF              DUK_TVAL_SET_NULL_UPDREF_ALT0
5391 #define DUK_TVAL_SET_BOOLEAN_UPDREF           DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
5392 #define DUK_TVAL_SET_NUMBER_UPDREF            DUK_TVAL_SET_NUMBER_UPDREF_ALT0
5393 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF    DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
5394 #define DUK_TVAL_SET_DOUBLE_UPDREF            DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
5395 #define DUK_TVAL_SET_NAN_UPDREF               DUK_TVAL_SET_NAN_UPDREF_ALT0
5396 #if defined(DUK_USE_FASTINT)
5397 #define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_I48_UPDREF_ALT0
5398 #define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_I32_UPDREF_ALT0
5399 #define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_U32_UPDREF_ALT0
5400 #else
5401 #define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF  /* XXX: fast-int-to-double */
5402 #define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF
5403 #define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF
5404 #endif  /* DUK_USE_FASTINT */
5405 #define DUK_TVAL_SET_FASTINT_UPDREF           DUK_TVAL_SET_I48_UPDREF  /* convenience */
5406 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF         DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
5407 #define DUK_TVAL_SET_STRING_UPDREF            DUK_TVAL_SET_STRING_UPDREF_ALT0
5408 #define DUK_TVAL_SET_OBJECT_UPDREF            DUK_TVAL_SET_OBJECT_UPDREF_ALT0
5409 #define DUK_TVAL_SET_BUFFER_UPDREF            DUK_TVAL_SET_BUFFER_UPDREF_ALT0
5410 #define DUK_TVAL_SET_POINTER_UPDREF           DUK_TVAL_SET_POINTER_UPDREF_ALT0
5411 
5412 #define DUK_TVAL_SET_TVAL_UPDREF              DUK_TVAL_SET_TVAL_UPDREF_ALT0
5413 #define DUK_TVAL_SET_TVAL_UPDREF_FAST         DUK_TVAL_SET_TVAL_UPDREF_ALT0
5414 #define DUK_TVAL_SET_TVAL_UPDREF_SLOW         DUK_TVAL_SET_TVAL_UPDREF_ALT0
5415 
5416 #endif  /* DUK_USE_REFERENCE_COUNTING */
5417 
5418 /*
5419  *  Some convenience macros that don't have optimized implementations now.
5420  */
5421 
5422 #define DUK_TVAL_SET_TVAL_UPDREF_NORZ(thr,tv_dst,tv_src) do { \
5423 		duk_hthread *duk__thr = (thr); \
5424 		duk_tval *duk__dst = (tv_dst); \
5425 		duk_tval *duk__src = (tv_src); \
5426 		DUK_UNREF(duk__thr); \
5427 		DUK_TVAL_DECREF_NORZ(thr, duk__dst); \
5428 		DUK_TVAL_SET_TVAL(duk__dst, duk__src); \
5429 		DUK_TVAL_INCREF(thr, duk__dst); \
5430 	} while (0)
5431 
5432 #define DUK_TVAL_SET_U32_UPDREF_NORZ(thr,tv_dst,val) do { \
5433 		duk_hthread *duk__thr = (thr); \
5434 		duk_tval *duk__dst = (tv_dst); \
5435 		duk_uint32_t duk__val = (duk_uint32_t) (val); \
5436 		DUK_UNREF(duk__thr); \
5437 		DUK_TVAL_DECREF_NORZ(thr, duk__dst); \
5438 		DUK_TVAL_SET_U32(duk__dst, duk__val); \
5439 	} while (0)
5440 
5441 /*
5442  *  Prototypes
5443  */
5444 
5445 #if defined(DUK_USE_REFERENCE_COUNTING)
5446 #if defined(DUK_USE_FINALIZER_SUPPORT)
5447 DUK_INTERNAL_DECL void duk_refzero_check_slow(duk_hthread *thr);
5448 DUK_INTERNAL_DECL void duk_refzero_check_fast(duk_hthread *thr);
5449 #endif
5450 DUK_INTERNAL_DECL void duk_heaphdr_refcount_finalize_norz(duk_heap *heap, duk_heaphdr *hdr);
5451 DUK_INTERNAL_DECL void duk_hobject_refcount_finalize_norz(duk_heap *heap, duk_hobject *h);
5452 #if 0  /* Not needed: fast path handles inline; slow path uses duk_heaphdr_decref() which is needed anyway. */
5453 DUK_INTERNAL_DECL void duk_hstring_decref(duk_hthread *thr, duk_hstring *h);
5454 DUK_INTERNAL_DECL void duk_hstring_decref_norz(duk_hthread *thr, duk_hstring *h);
5455 DUK_INTERNAL_DECL void duk_hbuffer_decref(duk_hthread *thr, duk_hbuffer *h);
5456 DUK_INTERNAL_DECL void duk_hbuffer_decref_norz(duk_hthread *thr, duk_hbuffer *h);
5457 DUK_INTERNAL_DECL void duk_hobject_decref(duk_hthread *thr, duk_hobject *h);
5458 DUK_INTERNAL_DECL void duk_hobject_decref_norz(duk_hthread *thr, duk_hobject *h);
5459 #endif
5460 DUK_INTERNAL_DECL void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h);
5461 DUK_INTERNAL_DECL void duk_heaphdr_refzero_norz(duk_hthread *thr, duk_heaphdr *h);
5462 #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
5463 DUK_INTERNAL_DECL void duk_hstring_refzero(duk_hthread *thr, duk_hstring *h);  /* no 'norz' variant */
5464 DUK_INTERNAL_DECL void duk_hbuffer_refzero(duk_hthread *thr, duk_hbuffer *h);  /* no 'norz' variant */
5465 DUK_INTERNAL_DECL void duk_hobject_refzero(duk_hthread *thr, duk_hobject *h);
5466 DUK_INTERNAL_DECL void duk_hobject_refzero_norz(duk_hthread *thr, duk_hobject *h);
5467 #else
5468 DUK_INTERNAL_DECL void duk_tval_incref(duk_tval *tv);
5469 DUK_INTERNAL_DECL void duk_tval_decref(duk_hthread *thr, duk_tval *tv);
5470 DUK_INTERNAL_DECL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv);
5471 DUK_INTERNAL_DECL void duk_heaphdr_incref(duk_heaphdr *h);
5472 DUK_INTERNAL_DECL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h);
5473 DUK_INTERNAL_DECL void duk_heaphdr_decref_norz(duk_hthread *thr, duk_heaphdr *h);
5474 #endif
5475 #else  /* DUK_USE_REFERENCE_COUNTING */
5476 /* no refcounting */
5477 #endif  /* DUK_USE_REFERENCE_COUNTING */
5478 
5479 #endif  /* DUK_REFCOUNT_H_INCLUDED */
5480 /* #include duk_api_internal.h */
5481 /*
5482  *  Internal API calls which have (stack and other) semantics similar
5483  *  to the public API.
5484  */
5485 
5486 #if !defined(DUK_API_INTERNAL_H_INCLUDED)
5487 #define DUK_API_INTERNAL_H_INCLUDED
5488 
5489 /* Inline macro helpers. */
5490 #if defined(DUK_USE_PREFER_SIZE)
5491 #define DUK_INLINE_PERF
5492 #define DUK_ALWAYS_INLINE_PERF
5493 #define DUK_NOINLINE_PERF
5494 #else
5495 #define DUK_INLINE_PERF DUK_INLINE
5496 #define DUK_ALWAYS_INLINE_PERF DUK_ALWAYS_INLINE
5497 #define DUK_NOINLINE_PERF DUK_NOINLINE
5498 #endif
5499 
5500 /* Inline macro helpers, for bytecode executor. */
5501 #if defined(DUK_USE_EXEC_PREFER_SIZE)
5502 #define DUK_EXEC_INLINE_PERF
5503 #define DUK_EXEC_ALWAYS_INLINE_PERF
5504 #define DUK_EXEC_NOINLINE_PERF
5505 #else
5506 #define DUK_EXEC_INLINE_PERF DUK_INLINE
5507 #define DUK_EXEC_ALWAYS_INLINE_PERF DUK_ALWAYS_INLINE
5508 #define DUK_EXEC_NOINLINE_PERF DUK_NOINLINE
5509 #endif
5510 
5511 /* duk_push_sprintf constants */
5512 #define DUK_PUSH_SPRINTF_INITIAL_SIZE  256L
5513 #define DUK_PUSH_SPRINTF_SANITY_LIMIT  (1L * 1024L * 1024L * 1024L)
5514 
5515 /* Flag ORed to err_code to indicate __FILE__ / __LINE__ is not
5516  * blamed as source of error for error fileName / lineNumber.
5517  */
5518 #define DUK_ERRCODE_FLAG_NOBLAME_FILELINE  (1L << 24)
5519 
5520 /* Current convention is to use duk_size_t for value stack sizes and global indices,
5521  * and duk_idx_t for local frame indices.
5522  */
5523 DUK_INTERNAL_DECL void duk_valstack_grow_check_throw(duk_hthread *thr, duk_size_t min_bytes);
5524 DUK_INTERNAL_DECL duk_bool_t duk_valstack_grow_check_nothrow(duk_hthread *thr, duk_size_t min_bytes);
5525 DUK_INTERNAL_DECL void duk_valstack_shrink_check_nothrow(duk_hthread *thr, duk_bool_t snug);
5526 
5527 DUK_INTERNAL_DECL void duk_copy_tvals_incref(duk_hthread *thr, duk_tval *tv_dst, duk_tval *tv_src, duk_size_t count);
5528 
5529 DUK_INTERNAL_DECL duk_tval *duk_reserve_gap(duk_hthread *thr, duk_idx_t idx_base, duk_idx_t count);
5530 
5531 DUK_INTERNAL_DECL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx);
5532 DUK_INTERNAL_DECL void duk_set_top_and_wipe(duk_hthread *thr, duk_idx_t top, duk_idx_t idx_wipe_start);
5533 
5534 DUK_INTERNAL_DECL void duk_dup_0(duk_hthread *thr);
5535 DUK_INTERNAL_DECL void duk_dup_1(duk_hthread *thr);
5536 DUK_INTERNAL_DECL void duk_dup_2(duk_hthread *thr);
5537 /* duk_dup_m1() would be same as duk_dup_top() */
5538 DUK_INTERNAL_DECL void duk_dup_m2(duk_hthread *thr);
5539 DUK_INTERNAL_DECL void duk_dup_m3(duk_hthread *thr);
5540 DUK_INTERNAL_DECL void duk_dup_m4(duk_hthread *thr);
5541 
5542 DUK_INTERNAL_DECL void duk_remove_unsafe(duk_hthread *thr, duk_idx_t idx);
5543 DUK_INTERNAL_DECL void duk_remove_m2(duk_hthread *thr);
5544 DUK_INTERNAL_DECL void duk_remove_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count);
5545 DUK_INTERNAL_DECL void duk_remove_n_unsafe(duk_hthread *thr, duk_idx_t idx, duk_idx_t count);
5546 
5547 DUK_INTERNAL_DECL duk_int_t duk_get_type_tval(duk_tval *tv);
5548 DUK_INTERNAL_DECL duk_uint_t duk_get_type_mask_tval(duk_tval *tv);
5549 
5550 #if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)
5551 DUK_INTERNAL_DECL const char *duk_get_type_name(duk_hthread *thr, duk_idx_t idx);
5552 #endif
5553 DUK_INTERNAL_DECL duk_small_uint_t duk_get_class_number(duk_hthread *thr, duk_idx_t idx);
5554 
5555 DUK_INTERNAL_DECL duk_tval *duk_get_tval(duk_hthread *thr, duk_idx_t idx);
5556 DUK_INTERNAL_DECL duk_tval *duk_get_tval_or_unused(duk_hthread *thr, duk_idx_t idx);
5557 DUK_INTERNAL_DECL duk_tval *duk_require_tval(duk_hthread *thr, duk_idx_t idx);
5558 DUK_INTERNAL_DECL void duk_push_tval(duk_hthread *thr, duk_tval *tv);
5559 
5560 /* Push the current 'this' binding; throw TypeError if binding is not object
5561  * coercible (CheckObjectCoercible).
5562  */
5563 DUK_INTERNAL_DECL void duk_push_this_check_object_coercible(duk_hthread *thr);
5564 
5565 /* duk_push_this() + CheckObjectCoercible() + duk_to_object() */
5566 DUK_INTERNAL_DECL duk_hobject *duk_push_this_coercible_to_object(duk_hthread *thr);
5567 
5568 /* duk_push_this() + CheckObjectCoercible() + duk_to_string() */
5569 DUK_INTERNAL_DECL duk_hstring *duk_push_this_coercible_to_string(duk_hthread *thr);
5570 
5571 DUK_INTERNAL_DECL duk_hstring *duk_push_uint_to_hstring(duk_hthread *thr, duk_uint_t i);
5572 
5573 /* Get a borrowed duk_tval pointer to the current 'this' binding.  Caller must
5574  * make sure there's an active callstack entry.  Note that the returned pointer
5575  * is unstable with regards to side effects.
5576  */
5577 DUK_INTERNAL_DECL duk_tval *duk_get_borrowed_this_tval(duk_hthread *thr);
5578 
5579 /* XXX: add fastint support? */
5580 #define duk_push_u64(thr,val) \
5581 	duk_push_number((thr), (duk_double_t) (val))
5582 #define duk_push_i64(thr,val) \
5583 	duk_push_number((thr), (duk_double_t) (val))
5584 
5585 /* duk_push_(u)int() is guaranteed to support at least (un)signed 32-bit range */
5586 #define duk_push_u32(thr,val) \
5587 	duk_push_uint((thr), (duk_uint_t) (val))
5588 #define duk_push_i32(thr,val) \
5589 	duk_push_int((thr), (duk_int_t) (val))
5590 
5591 /* sometimes stack and array indices need to go on the stack */
5592 #define duk_push_idx(thr,val) \
5593 	duk_push_int((thr), (duk_int_t) (val))
5594 #define duk_push_uarridx(thr,val) \
5595 	duk_push_uint((thr), (duk_uint_t) (val))
5596 #define duk_push_size_t(thr,val) \
5597 	duk_push_uint((thr), (duk_uint_t) (val))  /* XXX: assumed to fit for now */
5598 
5599 DUK_INTERNAL_DECL duk_bool_t duk_is_string_notsymbol(duk_hthread *thr, duk_idx_t idx);
5600 
5601 DUK_INTERNAL_DECL duk_bool_t duk_is_callable_tval(duk_hthread *thr, duk_tval *tv);
5602 
5603 DUK_INTERNAL_DECL duk_bool_t duk_is_bare_object(duk_hthread *thr, duk_idx_t idx);
5604 
5605 DUK_INTERNAL_DECL duk_hstring *duk_get_hstring(duk_hthread *thr, duk_idx_t idx);
5606 DUK_INTERNAL_DECL duk_hstring *duk_get_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx);
5607 DUK_INTERNAL_DECL const char *duk_get_string_notsymbol(duk_hthread *thr, duk_idx_t idx);
5608 DUK_INTERNAL_DECL duk_hobject *duk_get_hobject(duk_hthread *thr, duk_idx_t idx);
5609 DUK_INTERNAL_DECL duk_hbuffer *duk_get_hbuffer(duk_hthread *thr, duk_idx_t idx);
5610 DUK_INTERNAL_DECL duk_hthread *duk_get_hthread(duk_hthread *thr, duk_idx_t idx);
5611 DUK_INTERNAL_DECL duk_hcompfunc *duk_get_hcompfunc(duk_hthread *thr, duk_idx_t idx);
5612 DUK_INTERNAL_DECL duk_hnatfunc *duk_get_hnatfunc(duk_hthread *thr, duk_idx_t idx);
5613 
5614 DUK_INTERNAL_DECL void *duk_get_buffer_data_raw(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_len, duk_bool_t throw_flag, duk_bool_t *out_isbuffer);
5615 
5616 DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum);
5617 
5618 DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask);
5619 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask);
5620 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_accept_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask);
5621 #define duk_require_hobject_promote_lfunc(thr,idx) \
5622 	duk_require_hobject_promote_mask((thr), (idx), DUK_TYPE_MASK_LIGHTFUNC)
5623 #define duk_get_hobject_promote_lfunc(thr,idx) \
5624 	duk_get_hobject_promote_mask((thr), (idx), DUK_TYPE_MASK_LIGHTFUNC)
5625 
5626 #if 0  /*unused*/
5627 DUK_INTERNAL_DECL void *duk_get_voidptr(duk_hthread *thr, duk_idx_t idx);
5628 #endif
5629 
5630 DUK_INTERNAL_DECL duk_hstring *duk_known_hstring(duk_hthread *thr, duk_idx_t idx);
5631 DUK_INTERNAL_DECL duk_hobject *duk_known_hobject(duk_hthread *thr, duk_idx_t idx);
5632 DUK_INTERNAL_DECL duk_hbuffer *duk_known_hbuffer(duk_hthread *thr, duk_idx_t idx);
5633 DUK_INTERNAL_DECL duk_hcompfunc *duk_known_hcompfunc(duk_hthread *thr, duk_idx_t idx);
5634 DUK_INTERNAL_DECL duk_hnatfunc *duk_known_hnatfunc(duk_hthread *thr, duk_idx_t idx);
5635 
5636 DUK_INTERNAL_DECL duk_double_t duk_to_number_tval(duk_hthread *thr, duk_tval *tv);
5637 
5638 DUK_INTERNAL_DECL duk_hstring *duk_to_hstring(duk_hthread *thr, duk_idx_t idx);
5639 DUK_INTERNAL_DECL duk_hstring *duk_to_hstring_m1(duk_hthread *thr);
5640 DUK_INTERNAL_DECL duk_hstring *duk_to_hstring_acceptsymbol(duk_hthread *thr, duk_idx_t idx);
5641 
5642 DUK_INTERNAL_DECL duk_hobject *duk_to_hobject(duk_hthread *thr, duk_idx_t idx);
5643 
5644 DUK_INTERNAL_DECL duk_double_t duk_to_number_m1(duk_hthread *thr);
5645 DUK_INTERNAL_DECL duk_double_t duk_to_number_m2(duk_hthread *thr);
5646 
5647 DUK_INTERNAL_DECL duk_bool_t duk_to_boolean_top_pop(duk_hthread *thr);
5648 
5649 #if defined(DUK_USE_DEBUGGER_SUPPORT)  /* only needed by debugger for now */
5650 DUK_INTERNAL_DECL duk_hstring *duk_safe_to_hstring(duk_hthread *thr, duk_idx_t idx);
5651 #endif
5652 DUK_INTERNAL_DECL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv, duk_bool_t avoid_side_effects);
5653 
5654 DUK_INTERNAL_DECL duk_int_t duk_to_int_clamped_raw(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval, duk_bool_t *out_clamped);  /* out_clamped=NULL, RangeError if outside range */
5655 DUK_INTERNAL_DECL duk_int_t duk_to_int_clamped(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval);
5656 DUK_INTERNAL_DECL duk_int_t duk_to_int_check_range(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval);
5657 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
5658 DUK_INTERNAL_DECL duk_uint8_t duk_to_uint8clamped(duk_hthread *thr, duk_idx_t idx);
5659 #endif
5660 DUK_INTERNAL_DECL duk_hstring *duk_to_property_key_hstring(duk_hthread *thr, duk_idx_t idx);
5661 
5662 DUK_INTERNAL_DECL duk_hstring *duk_require_hstring(duk_hthread *thr, duk_idx_t idx);
5663 DUK_INTERNAL_DECL duk_hstring *duk_require_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx);
5664 DUK_INTERNAL_DECL const char *duk_require_lstring_notsymbol(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len);
5665 DUK_INTERNAL_DECL const char *duk_require_string_notsymbol(duk_hthread *thr, duk_idx_t idx);
5666 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject(duk_hthread *thr, duk_idx_t idx);
5667 DUK_INTERNAL_DECL duk_hbuffer *duk_require_hbuffer(duk_hthread *thr, duk_idx_t idx);
5668 DUK_INTERNAL_DECL duk_hthread *duk_require_hthread(duk_hthread *thr, duk_idx_t idx);
5669 DUK_INTERNAL_DECL duk_hcompfunc *duk_require_hcompfunc(duk_hthread *thr, duk_idx_t idx);
5670 DUK_INTERNAL_DECL duk_hnatfunc *duk_require_hnatfunc(duk_hthread *thr, duk_idx_t idx);
5671 
5672 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum);
5673 
5674 DUK_INTERNAL_DECL void duk_push_hstring(duk_hthread *thr, duk_hstring *h);
5675 DUK_INTERNAL_DECL void duk_push_hstring_stridx(duk_hthread *thr, duk_small_uint_t stridx);
5676 DUK_INTERNAL_DECL void duk_push_hstring_empty(duk_hthread *thr);
5677 DUK_INTERNAL_DECL void duk_push_hobject(duk_hthread *thr, duk_hobject *h);
5678 DUK_INTERNAL_DECL void duk_push_hbuffer(duk_hthread *thr, duk_hbuffer *h);
5679 #define duk_push_hthread(thr,h) \
5680 	duk_push_hobject((thr), (duk_hobject *) (h))
5681 #define duk_push_hnatfunc(thr,h) \
5682 	duk_push_hobject((thr), (duk_hobject *) (h))
5683 DUK_INTERNAL_DECL void duk_push_hobject_bidx(duk_hthread *thr, duk_small_int_t builtin_idx);
5684 DUK_INTERNAL_DECL duk_hobject *duk_push_object_helper(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx);
5685 DUK_INTERNAL_DECL duk_hobject *duk_push_object_helper_proto(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_hobject *proto);
5686 DUK_INTERNAL_DECL duk_hcompfunc *duk_push_hcompfunc(duk_hthread *thr);
5687 DUK_INTERNAL_DECL duk_hboundfunc *duk_push_hboundfunc(duk_hthread *thr);
5688 DUK_INTERNAL_DECL void duk_push_c_function_builtin(duk_hthread *thr, duk_c_function func, duk_int_t nargs);
5689 DUK_INTERNAL_DECL void duk_push_c_function_builtin_noconstruct(duk_hthread *thr, duk_c_function func, duk_int_t nargs);
5690 
5691 /* XXX: duk_push_harray() and duk_push_hcompfunc() are inconsistent with
5692  * duk_push_hobject() etc which don't create a new value.
5693  */
5694 DUK_INTERNAL_DECL duk_harray *duk_push_harray(duk_hthread *thr);
5695 DUK_INTERNAL_DECL duk_harray *duk_push_harray_with_size(duk_hthread *thr, duk_uint32_t size);
5696 DUK_INTERNAL_DECL duk_tval *duk_push_harray_with_size_outptr(duk_hthread *thr, duk_uint32_t size);
5697 
5698 DUK_INTERNAL_DECL void duk_push_string_funcptr(duk_hthread *thr, duk_uint8_t *ptr, duk_size_t sz);
5699 DUK_INTERNAL_DECL void duk_push_lightfunc_name_raw(duk_hthread *thr, duk_c_function func, duk_small_uint_t lf_flags);
5700 DUK_INTERNAL_DECL void duk_push_lightfunc_name(duk_hthread *thr, duk_tval *tv);
5701 DUK_INTERNAL_DECL void duk_push_lightfunc_tostring(duk_hthread *thr, duk_tval *tv);
5702 #if 0  /* not used yet */
5703 DUK_INTERNAL_DECL void duk_push_hnatfunc_name(duk_hthread *thr, duk_hnatfunc *h);
5704 #endif
5705 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
5706 DUK_INTERNAL_DECL duk_hbufobj *duk_push_bufobj_raw(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx);
5707 #endif
5708 
5709 DUK_INTERNAL_DECL void *duk_push_fixed_buffer_nozero(duk_hthread *thr, duk_size_t len);
5710 DUK_INTERNAL_DECL void *duk_push_fixed_buffer_zero(duk_hthread *thr, duk_size_t len);
5711 
5712 DUK_INTERNAL_DECL const char *duk_push_string_readable(duk_hthread *thr, duk_idx_t idx);
5713 DUK_INTERNAL_DECL const char *duk_push_string_tval_readable(duk_hthread *thr, duk_tval *tv);
5714 DUK_INTERNAL_DECL const char *duk_push_string_tval_readable_error(duk_hthread *thr, duk_tval *tv);
5715 
5716 /* The duk_xxx_prop_stridx_short() variants expect their arguments to be short
5717  * enough to be packed into a single 32-bit integer argument.  Argument limits
5718  * vary per call; typically 16 bits are assigned to the signed value stack index
5719  * and the stridx.  In practice these work well for footprint with constant
5720  * arguments and such call sites are also easiest to verify to be correct.
5721  */
5722 
5723 DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [] -> [val] */
5724 DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5725 #define duk_get_prop_stridx_short(thr,obj_idx,stridx) \
5726 	(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \
5727 	 DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
5728 	 duk_get_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
5729 DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx_boolean(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_bool_t *out_has_prop);  /* [] -> [] */
5730 
5731 DUK_INTERNAL_DECL duk_bool_t duk_xget_owndataprop(duk_hthread *thr, duk_idx_t obj_idx);
5732 DUK_INTERNAL_DECL duk_bool_t duk_xget_owndataprop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);
5733 DUK_INTERNAL_DECL duk_bool_t duk_xget_owndataprop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5734 #define duk_xget_owndataprop_stridx_short(thr,obj_idx,stridx) \
5735 	(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \
5736 	 DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
5737 	 duk_xget_owndataprop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
5738 
5739 DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [val] -> [] */
5740 DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5741 #define duk_put_prop_stridx_short(thr,obj_idx,stridx) \
5742 	(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \
5743 	 DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
5744 	 duk_put_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
5745 
5746 DUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [] -> [] */
5747 #if 0  /* Too few call sites to be useful. */
5748 DUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5749 #define duk_del_prop_stridx_short(thr,obj_idx,stridx) \
5750 	(DUK_ASSERT_EXPR((obj_idx) >= -0x8000L && (obj_idx) <= 0x7fffL), \
5751 	 DUK_ASSERT_EXPR((stridx) >= 0 && (stridx) <= 0xffffL), \
5752 	 duk_del_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
5753 #endif
5754 #define duk_del_prop_stridx_short(thr,obj_idx,stridx) \
5755 	duk_del_prop_stridx((thr), (obj_idx), (stridx))
5756 
5757 DUK_INTERNAL_DECL duk_bool_t duk_has_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [] -> [] */
5758 #if 0  /* Too few call sites to be useful. */
5759 DUK_INTERNAL_DECL duk_bool_t duk_has_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5760 #define duk_has_prop_stridx_short(thr,obj_idx,stridx) \
5761 	(DUK_ASSERT_EXPR((obj_idx) >= -0x8000L && (obj_idx) <= 0x7fffL), \
5762 	 DUK_ASSERT_EXPR((stridx) >= 0 && (stridx) <= 0xffffL), \
5763 	 duk_has_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
5764 #endif
5765 #define duk_has_prop_stridx_short(thr,obj_idx,stridx) \
5766 	duk_has_prop_stridx((thr), (obj_idx), (stridx))
5767 
5768 DUK_INTERNAL_DECL void duk_xdef_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t desc_flags);  /* [key val] -> [] */
5769 
5770 DUK_INTERNAL_DECL void duk_xdef_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx, duk_small_uint_t desc_flags);  /* [val] -> [] */
5771 
5772 /* XXX: Because stridx and desc_flags have a limited range, this call could
5773  * always pack stridx and desc_flags into a single argument.
5774  */
5775 DUK_INTERNAL_DECL void duk_xdef_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_small_uint_t desc_flags);  /* [val] -> [] */
5776 DUK_INTERNAL_DECL void duk_xdef_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5777 #define duk_xdef_prop_stridx_short(thr,obj_idx,stridx,desc_flags) \
5778 	(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x80L && (duk_int_t) (obj_idx) <= 0x7fL), \
5779 	 DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
5780 	 DUK_ASSERT_EXPR((duk_int_t) (desc_flags) >= 0 && (duk_int_t) (desc_flags) <= 0xffL), \
5781 	 duk_xdef_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 24) + (((duk_uint_t) (stridx)) << 8) + (duk_uint_t) (desc_flags)))
5782 
5783 #define duk_xdef_prop_wec(thr,obj_idx) \
5784 	duk_xdef_prop((thr), (obj_idx), DUK_PROPDESC_FLAGS_WEC)
5785 #define duk_xdef_prop_index_wec(thr,obj_idx,arr_idx) \
5786 	duk_xdef_prop_index((thr), (obj_idx), (arr_idx), DUK_PROPDESC_FLAGS_WEC)
5787 #define duk_xdef_prop_stridx_wec(thr,obj_idx,stridx) \
5788 	duk_xdef_prop_stridx((thr), (obj_idx), (stridx), DUK_PROPDESC_FLAGS_WEC)
5789 #define duk_xdef_prop_stridx_short_wec(thr,obj_idx,stridx) \
5790 	duk_xdef_prop_stridx_short((thr), (obj_idx), (stridx), DUK_PROPDESC_FLAGS_WEC)
5791 
5792 #if 0  /*unused*/
5793 DUK_INTERNAL_DECL void duk_xdef_prop_stridx_builtin(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_small_int_t builtin_idx, duk_small_uint_t desc_flags);  /* [] -> [] */
5794 #endif
5795 
5796 DUK_INTERNAL_DECL void duk_xdef_prop_stridx_thrower(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);  /* [] -> [] */
5797 
5798 DUK_INTERNAL_DECL duk_bool_t duk_get_method_stridx(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t stridx);
5799 
5800 DUK_INTERNAL_DECL void duk_pack(duk_hthread *thr, duk_idx_t count);
5801 DUK_INTERNAL_DECL duk_idx_t duk_unpack_array_like(duk_hthread *thr, duk_idx_t idx);
5802 #if 0
5803 DUK_INTERNAL_DECL void duk_unpack(duk_hthread *thr);
5804 #endif
5805 
5806 DUK_INTERNAL_DECL void duk_push_symbol_descriptive_string(duk_hthread *thr, duk_hstring *h);
5807 
5808 DUK_INTERNAL_DECL void duk_resolve_nonbound_function(duk_hthread *thr);
5809 
5810 DUK_INTERNAL_DECL duk_idx_t duk_get_top_require_min(duk_hthread *thr, duk_idx_t min_top);
5811 DUK_INTERNAL_DECL duk_idx_t duk_get_top_index_unsafe(duk_hthread *thr);
5812 
5813 DUK_INTERNAL_DECL void duk_pop_n_unsafe(duk_hthread *thr, duk_idx_t count);
5814 DUK_INTERNAL_DECL void duk_pop_unsafe(duk_hthread *thr);
5815 DUK_INTERNAL_DECL void duk_pop_2_unsafe(duk_hthread *thr);
5816 DUK_INTERNAL_DECL void duk_pop_3_unsafe(duk_hthread *thr);
5817 DUK_INTERNAL_DECL void duk_pop_n_nodecref_unsafe(duk_hthread *thr, duk_idx_t count);
5818 DUK_INTERNAL_DECL void duk_pop_nodecref_unsafe(duk_hthread *thr);
5819 DUK_INTERNAL_DECL void duk_pop_2_nodecref_unsafe(duk_hthread *thr);
5820 DUK_INTERNAL_DECL void duk_pop_3_nodecref_unsafe(duk_hthread *thr);
5821 DUK_INTERNAL_DECL void duk_pop_undefined(duk_hthread *thr);
5822 
5823 DUK_INTERNAL_DECL void duk_compact_m1(duk_hthread *thr);
5824 
5825 DUK_INTERNAL_DECL void duk_seal_freeze_raw(duk_hthread *thr, duk_idx_t obj_idx, duk_bool_t is_freeze);
5826 
5827 DUK_INTERNAL_DECL void duk_insert_undefined(duk_hthread *thr, duk_idx_t idx);
5828 DUK_INTERNAL_DECL void duk_insert_undefined_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count);
5829 
5830 DUK_INTERNAL_DECL void duk_concat_2(duk_hthread *thr);
5831 
5832 DUK_INTERNAL_DECL duk_int_t duk_pcall_method_flags(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags);
5833 
5834 #if defined(DUK_USE_SYMBOL_BUILTIN)
5835 DUK_INTERNAL_DECL void duk_to_primitive_ordinary(duk_hthread *thr, duk_idx_t idx, duk_int_t hint);
5836 #endif
5837 
5838 DUK_INTERNAL_DECL void duk_clear_prototype(duk_hthread *thr, duk_idx_t idx);
5839 
5840 /* Raw internal valstack access macros: access is unsafe so call site
5841  * must have a guarantee that the index is valid.  When that is the case,
5842  * using these macro results in faster and smaller code than duk_get_tval().
5843  * Both 'ctx' and 'idx' are evaluted multiple times, but only for asserts.
5844  */
5845 #define DUK_ASSERT_VALID_NEGIDX(thr,idx) \
5846 	(DUK_ASSERT_EXPR((duk_int_t) (idx) < 0), DUK_ASSERT_EXPR(duk_is_valid_index((thr), (idx))))
5847 #define DUK_ASSERT_VALID_POSIDX(thr,idx) \
5848 	(DUK_ASSERT_EXPR((duk_int_t) (idx) >= 0), DUK_ASSERT_EXPR(duk_is_valid_index((thr), (idx))))
5849 #define DUK_GET_TVAL_NEGIDX(thr,idx) \
5850 	(DUK_ASSERT_VALID_NEGIDX((thr),(idx)), ((duk_hthread *) (thr))->valstack_top + (idx))
5851 #define DUK_GET_TVAL_POSIDX(thr,idx) \
5852 	(DUK_ASSERT_VALID_POSIDX((thr),(idx)), ((duk_hthread *) (thr))->valstack_bottom + (idx))
5853 #define DUK_GET_HOBJECT_NEGIDX(thr,idx) \
5854 	(DUK_ASSERT_VALID_NEGIDX((thr),(idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (thr))->valstack_top + (idx)))
5855 #define DUK_GET_HOBJECT_POSIDX(thr,idx) \
5856 	(DUK_ASSERT_VALID_POSIDX((thr),(idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (thr))->valstack_bottom + (idx)))
5857 
5858 #define DUK_GET_THIS_TVAL_PTR(thr) \
5859 	(DUK_ASSERT_EXPR((thr)->valstack_bottom > (thr)->valstack), \
5860 	 (thr)->valstack_bottom - 1)
5861 
5862 DUK_INTERNAL_DECL duk_double_t duk_time_get_ecmascript_time(duk_hthread *thr);
5863 DUK_INTERNAL_DECL duk_double_t duk_time_get_ecmascript_time_nofrac(duk_hthread *thr);
5864 DUK_INTERNAL_DECL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr);
5865 
5866 #endif  /* DUK_API_INTERNAL_H_INCLUDED */
5867 /* #include duk_hstring.h */
5868 /*
5869  *  Heap string representation.
5870  *
5871  *  Strings are byte sequences ordinarily stored in extended UTF-8 format,
5872  *  allowing values larger than the official UTF-8 range (used internally)
5873  *  and also allowing UTF-8 encoding of surrogate pairs (CESU-8 format).
5874  *  Strings may also be invalid UTF-8 altogether which is the case e.g. with
5875  *  strings used as internal property names and raw buffers converted to
5876  *  strings.  In such cases the 'clen' field contains an inaccurate value.
5877  *
5878  *  ECMAScript requires support for 32-bit long strings.  However, since each
5879  *  16-bit codepoint can take 3 bytes in CESU-8, this representation can only
5880  *  support about 1.4G codepoint long strings in extreme cases.  This is not
5881  *  really a practical issue.
5882  */
5883 
5884 #if !defined(DUK_HSTRING_H_INCLUDED)
5885 #define DUK_HSTRING_H_INCLUDED
5886 
5887 /* Impose a maximum string length for now.  Restricted artificially to
5888  * ensure adding a heap header length won't overflow size_t.  The limit
5889  * should be synchronized with DUK_HBUFFER_MAX_BYTELEN.
5890  *
5891  * E5.1 makes provisions to support strings longer than 4G characters.
5892  * This limit should be eliminated on 64-bit platforms (and increased
5893  * closer to maximum support on 32-bit platforms).
5894  */
5895 
5896 #if defined(DUK_USE_STRLEN16)
5897 #define DUK_HSTRING_MAX_BYTELEN                     (0x0000ffffUL)
5898 #else
5899 #define DUK_HSTRING_MAX_BYTELEN                     (0x7fffffffUL)
5900 #endif
5901 
5902 /* XXX: could add flags for "is valid CESU-8" (ECMAScript compatible strings),
5903  * "is valid UTF-8", "is valid extended UTF-8" (internal strings are not,
5904  * regexp bytecode is), and "contains non-BMP characters".  These are not
5905  * needed right now.
5906  */
5907 
5908 /* With lowmem builds the high 16 bits of duk_heaphdr are used for other
5909  * purposes, so this leaves 7 duk_heaphdr flags and 9 duk_hstring flags.
5910  */
5911 #define DUK_HSTRING_FLAG_ASCII                      DUK_HEAPHDR_USER_FLAG(0)  /* string is ASCII, clen == blen */
5912 #define DUK_HSTRING_FLAG_ARRIDX                     DUK_HEAPHDR_USER_FLAG(1)  /* string is a valid array index */
5913 #define DUK_HSTRING_FLAG_SYMBOL                     DUK_HEAPHDR_USER_FLAG(2)  /* string is a symbol (invalid utf-8) */
5914 #define DUK_HSTRING_FLAG_HIDDEN                     DUK_HEAPHDR_USER_FLAG(3)  /* string is a hidden symbol (implies symbol, Duktape 1.x internal string) */
5915 #define DUK_HSTRING_FLAG_RESERVED_WORD              DUK_HEAPHDR_USER_FLAG(4)  /* string is a reserved word (non-strict) */
5916 #define DUK_HSTRING_FLAG_STRICT_RESERVED_WORD       DUK_HEAPHDR_USER_FLAG(5)  /* string is a reserved word (strict) */
5917 #define DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS          DUK_HEAPHDR_USER_FLAG(6)  /* string is 'eval' or 'arguments' */
5918 #define DUK_HSTRING_FLAG_EXTDATA                    DUK_HEAPHDR_USER_FLAG(7)  /* string data is external (duk_hstring_external) */
5919 #define DUK_HSTRING_FLAG_PINNED_LITERAL             DUK_HEAPHDR_USER_FLAG(8)  /* string is a literal, and pinned */
5920 
5921 #define DUK_HSTRING_HAS_ASCII(x)                    DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
5922 #define DUK_HSTRING_HAS_ARRIDX(x)                   DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
5923 #define DUK_HSTRING_HAS_SYMBOL(x)                   DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
5924 #define DUK_HSTRING_HAS_HIDDEN(x)                   DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
5925 #define DUK_HSTRING_HAS_RESERVED_WORD(x)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
5926 #define DUK_HSTRING_HAS_STRICT_RESERVED_WORD(x)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
5927 #define DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(x)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
5928 #define DUK_HSTRING_HAS_EXTDATA(x)                  DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
5929 #define DUK_HSTRING_HAS_PINNED_LITERAL(x)           DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_PINNED_LITERAL)
5930 
5931 #define DUK_HSTRING_SET_ASCII(x)                    DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
5932 #define DUK_HSTRING_SET_ARRIDX(x)                   DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
5933 #define DUK_HSTRING_SET_SYMBOL(x)                   DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
5934 #define DUK_HSTRING_SET_HIDDEN(x)                   DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
5935 #define DUK_HSTRING_SET_RESERVED_WORD(x)            DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
5936 #define DUK_HSTRING_SET_STRICT_RESERVED_WORD(x)     DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
5937 #define DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(x)        DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
5938 #define DUK_HSTRING_SET_EXTDATA(x)                  DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
5939 #define DUK_HSTRING_SET_PINNED_LITERAL(x)           DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_PINNED_LITERAL)
5940 
5941 #define DUK_HSTRING_CLEAR_ASCII(x)                  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
5942 #define DUK_HSTRING_CLEAR_ARRIDX(x)                 DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
5943 #define DUK_HSTRING_CLEAR_SYMBOL(x)                 DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
5944 #define DUK_HSTRING_CLEAR_HIDDEN(x)                 DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
5945 #define DUK_HSTRING_CLEAR_RESERVED_WORD(x)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
5946 #define DUK_HSTRING_CLEAR_STRICT_RESERVED_WORD(x)   DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
5947 #define DUK_HSTRING_CLEAR_EVAL_OR_ARGUMENTS(x)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
5948 #define DUK_HSTRING_CLEAR_EXTDATA(x)                DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
5949 #define DUK_HSTRING_CLEAR_PINNED_LITERAL(x)         DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_PINNED_LITERAL)
5950 
5951 #if 0  /* Slightly smaller code without explicit flag, but explicit flag
5952         * is very useful when 'clen' is dropped.
5953         */
5954 #define DUK_HSTRING_IS_ASCII(x)                     (DUK_HSTRING_GET_BYTELEN((x)) == DUK_HSTRING_GET_CHARLEN((x)))
5955 #endif
5956 #define DUK_HSTRING_IS_ASCII(x)                     DUK_HSTRING_HAS_ASCII((x))  /* lazily set! */
5957 #define DUK_HSTRING_IS_EMPTY(x)                     (DUK_HSTRING_GET_BYTELEN((x)) == 0)
5958 
5959 #if defined(DUK_USE_STRHASH16)
5960 #define DUK_HSTRING_GET_HASH(x)                     ((x)->hdr.h_flags >> 16)
5961 #define DUK_HSTRING_SET_HASH(x,v) do { \
5962 		(x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | ((v) << 16); \
5963 	} while (0)
5964 #else
5965 #define DUK_HSTRING_GET_HASH(x)                     ((x)->hash)
5966 #define DUK_HSTRING_SET_HASH(x,v) do { \
5967 		(x)->hash = (v); \
5968 	} while (0)
5969 #endif
5970 
5971 #if defined(DUK_USE_STRLEN16)
5972 #define DUK_HSTRING_GET_BYTELEN(x)                  ((x)->hdr.h_strextra16)
5973 #define DUK_HSTRING_SET_BYTELEN(x,v) do { \
5974 		(x)->hdr.h_strextra16 = (v); \
5975 	} while (0)
5976 #if defined(DUK_USE_HSTRING_CLEN)
5977 #define DUK_HSTRING_GET_CHARLEN(x)                  duk_hstring_get_charlen((x))
5978 #define DUK_HSTRING_SET_CHARLEN(x,v) do { \
5979 		(x)->clen16 = (v); \
5980 	} while (0)
5981 #else
5982 #define DUK_HSTRING_GET_CHARLEN(x)                  duk_hstring_get_charlen((x))
5983 #define DUK_HSTRING_SET_CHARLEN(x,v) do { \
5984 		DUK_ASSERT(0);  /* should never be called */ \
5985 	} while (0)
5986 #endif
5987 #else
5988 #define DUK_HSTRING_GET_BYTELEN(x)                  ((x)->blen)
5989 #define DUK_HSTRING_SET_BYTELEN(x,v) do { \
5990 		(x)->blen = (v); \
5991 	} while (0)
5992 #define DUK_HSTRING_GET_CHARLEN(x)                  duk_hstring_get_charlen((x))
5993 #define DUK_HSTRING_SET_CHARLEN(x,v) do { \
5994 		(x)->clen = (v); \
5995 	} while (0)
5996 #endif
5997 
5998 #if defined(DUK_USE_HSTRING_EXTDATA)
5999 #define DUK_HSTRING_GET_EXTDATA(x) \
6000 	((x)->extdata)
6001 #define DUK_HSTRING_GET_DATA(x) \
6002 	(DUK_HSTRING_HAS_EXTDATA((x)) ? \
6003 		DUK_HSTRING_GET_EXTDATA((const duk_hstring_external *) (x)) : ((const duk_uint8_t *) ((x) + 1)))
6004 #else
6005 #define DUK_HSTRING_GET_DATA(x) \
6006 	((const duk_uint8_t *) ((x) + 1))
6007 #endif
6008 
6009 #define DUK_HSTRING_GET_DATA_END(x) \
6010 	(DUK_HSTRING_GET_DATA((x)) + (x)->blen)
6011 
6012 /* Marker value; in E5 2^32-1 is not a valid array index (2^32-2 is highest
6013  * valid).
6014  */
6015 #define DUK_HSTRING_NO_ARRAY_INDEX  (0xffffffffUL)
6016 
6017 #if defined(DUK_USE_HSTRING_ARRIDX)
6018 #define DUK_HSTRING_GET_ARRIDX_FAST(h)  ((h)->arridx)
6019 #define DUK_HSTRING_GET_ARRIDX_SLOW(h)  ((h)->arridx)
6020 #else
6021 /* Get array index related to string (or return DUK_HSTRING_NO_ARRAY_INDEX);
6022  * avoids helper call if string has no array index value.
6023  */
6024 #define DUK_HSTRING_GET_ARRIDX_FAST(h)  \
6025 	(DUK_HSTRING_HAS_ARRIDX((h)) ? duk_js_to_arrayindex_hstring_fast_known((h)) : DUK_HSTRING_NO_ARRAY_INDEX)
6026 
6027 /* Slower but more compact variant. */
6028 #define DUK_HSTRING_GET_ARRIDX_SLOW(h)  \
6029 	(duk_js_to_arrayindex_hstring_fast((h)))
6030 #endif
6031 
6032 /* XXX: these actually fit into duk_hstring */
6033 #define DUK_SYMBOL_TYPE_HIDDEN 0
6034 #define DUK_SYMBOL_TYPE_GLOBAL 1
6035 #define DUK_SYMBOL_TYPE_LOCAL 2
6036 #define DUK_SYMBOL_TYPE_WELLKNOWN 3
6037 
6038 /* Assertion for duk_hstring validity. */
6039 #if defined(DUK_USE_ASSERTIONS)
6040 DUK_INTERNAL_DECL void duk_hstring_assert_valid(duk_hstring *h);
6041 #define DUK_HSTRING_ASSERT_VALID(h)  do { duk_hstring_assert_valid((h)); } while (0)
6042 #else
6043 #define DUK_HSTRING_ASSERT_VALID(h)  do {} while (0)
6044 #endif
6045 
6046 /*
6047  *  Misc
6048  */
6049 
6050 struct duk_hstring {
6051 	/* Smaller heaphdr than for other objects, because strings are held
6052 	 * in string intern table which requires no link pointers.  Much of
6053 	 * the 32-bit flags field is unused by flags, so we can stuff a 16-bit
6054 	 * field in there.
6055 	 */
6056 	duk_heaphdr_string hdr;
6057 
6058 	/* String hash. */
6059 #if defined(DUK_USE_STRHASH16)
6060 	/* If 16-bit hash is in use, stuff it into duk_heaphdr_string flags. */
6061 #else
6062 	duk_uint32_t hash;
6063 #endif
6064 
6065 	/* Precomputed array index (or DUK_HSTRING_NO_ARRAY_INDEX). */
6066 #if defined(DUK_USE_HSTRING_ARRIDX)
6067 	duk_uarridx_t arridx;
6068 #endif
6069 
6070 	/* Length in bytes (not counting NUL term). */
6071 #if defined(DUK_USE_STRLEN16)
6072 	/* placed in duk_heaphdr_string */
6073 #else
6074 	duk_uint32_t blen;
6075 #endif
6076 
6077 	/* Length in codepoints (must be E5 compatible). */
6078 #if defined(DUK_USE_STRLEN16)
6079 #if defined(DUK_USE_HSTRING_CLEN)
6080 	duk_uint16_t clen16;
6081 #else
6082 	/* computed live */
6083 #endif
6084 #else
6085 	duk_uint32_t clen;
6086 #endif
6087 
6088 	/*
6089 	 *  String data of 'blen+1' bytes follows (+1 for NUL termination
6090 	 *  convenience for C API).  No alignment needs to be guaranteed
6091 	 *  for strings, but fields above should guarantee alignment-by-4
6092 	 *  (but not alignment-by-8).
6093 	 */
6094 };
6095 
6096 /* The external string struct is defined even when the feature is inactive. */
6097 struct duk_hstring_external {
6098 	duk_hstring str;
6099 
6100 	/*
6101 	 *  For an external string, the NUL-terminated string data is stored
6102 	 *  externally.  The user must guarantee that data behind this pointer
6103 	 *  doesn't change while it's used.
6104 	 */
6105 
6106 	const duk_uint8_t *extdata;
6107 };
6108 
6109 /*
6110  *  Prototypes
6111  */
6112 
6113 DUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h, duk_uint_t pos, duk_bool_t surrogate_aware);
6114 DUK_INTERNAL_DECL duk_bool_t duk_hstring_equals_ascii_cstring(duk_hstring *h, const char *cstr);
6115 DUK_INTERNAL_DECL duk_size_t duk_hstring_get_charlen(duk_hstring *h);
6116 #if !defined(DUK_USE_HSTRING_LAZY_CLEN)
6117 DUK_INTERNAL_DECL void duk_hstring_init_charlen(duk_hstring *h);
6118 #endif
6119 
6120 #endif  /* DUK_HSTRING_H_INCLUDED */
6121 /* #include duk_hobject.h */
6122 /*
6123  *  Heap object representation.
6124  *
6125  *  Heap objects are used for ECMAScript objects, arrays, and functions,
6126  *  but also for internal control like declarative and object environment
6127  *  records.  Compiled functions, native functions, and threads are also
6128  *  objects but with an extended C struct.
6129  *
6130  *  Objects provide the required ECMAScript semantics and exotic behaviors
6131  *  especially for property access.
6132  *
6133  *  Properties are stored in three conceptual parts:
6134  *
6135  *    1. A linear 'entry part' contains ordered key-value-attributes triples
6136  *       and is the main method of string properties.
6137  *
6138  *    2. An optional linear 'array part' is used for array objects to store a
6139  *       (dense) range of [0,N[ array indexed entries with default attributes
6140  *       (writable, enumerable, configurable).  If the array part would become
6141  *       sparse or non-default attributes are required, the array part is
6142  *       abandoned and moved to the 'entry part'.
6143  *
6144  *    3. An optional 'hash part' is used to optimize lookups of the entry
6145  *       part; it is used only for objects with sufficiently many properties
6146  *       and can be abandoned without loss of information.
6147  *
6148  *  These three conceptual parts are stored in a single memory allocated area.
6149  *  This minimizes memory allocation overhead but also means that all three
6150  *  parts are resized together, and makes property access a bit complicated.
6151  */
6152 
6153 #if !defined(DUK_HOBJECT_H_INCLUDED)
6154 #define DUK_HOBJECT_H_INCLUDED
6155 
6156 /* Object flags.  Make sure this stays in sync with debugger object
6157  * inspection code.
6158  */
6159 
6160 /* XXX: some flags are object subtype specific (e.g. common to all function
6161  * subtypes, duk_harray, etc) and could be reused for different subtypes.
6162  */
6163 #define DUK_HOBJECT_FLAG_EXTENSIBLE            DUK_HEAPHDR_USER_FLAG(0)   /* object is extensible */
6164 #define DUK_HOBJECT_FLAG_CONSTRUCTABLE         DUK_HEAPHDR_USER_FLAG(1)   /* object is constructable */
6165 #define DUK_HOBJECT_FLAG_CALLABLE              DUK_HEAPHDR_USER_FLAG(2)   /* object is callable */
6166 #define DUK_HOBJECT_FLAG_BOUNDFUNC             DUK_HEAPHDR_USER_FLAG(3)   /* object established using Function.prototype.bind() */
6167 #define DUK_HOBJECT_FLAG_COMPFUNC              DUK_HEAPHDR_USER_FLAG(4)   /* object is a compiled function (duk_hcompfunc) */
6168 #define DUK_HOBJECT_FLAG_NATFUNC               DUK_HEAPHDR_USER_FLAG(5)   /* object is a native function (duk_hnatfunc) */
6169 #define DUK_HOBJECT_FLAG_BUFOBJ                DUK_HEAPHDR_USER_FLAG(6)   /* object is a buffer object (duk_hbufobj) (always exotic) */
6170 #define DUK_HOBJECT_FLAG_FASTREFS              DUK_HEAPHDR_USER_FLAG(7)   /* object has no fields needing DECREF/marking beyond base duk_hobject header */
6171 #define DUK_HOBJECT_FLAG_ARRAY_PART            DUK_HEAPHDR_USER_FLAG(8)   /* object has an array part (a_size may still be 0) */
6172 #define DUK_HOBJECT_FLAG_STRICT                DUK_HEAPHDR_USER_FLAG(9)   /* function: function object is strict */
6173 #define DUK_HOBJECT_FLAG_NOTAIL                DUK_HEAPHDR_USER_FLAG(10)  /* function: function must not be tail called */
6174 #define DUK_HOBJECT_FLAG_NEWENV                DUK_HEAPHDR_USER_FLAG(11)  /* function: create new environment when called (see duk_hcompfunc) */
6175 #define DUK_HOBJECT_FLAG_NAMEBINDING           DUK_HEAPHDR_USER_FLAG(12)  /* function: create binding for func name (function templates only, used for named function expressions) */
6176 #define DUK_HOBJECT_FLAG_CREATEARGS            DUK_HEAPHDR_USER_FLAG(13)  /* function: create an arguments object on function call */
6177 #define DUK_HOBJECT_FLAG_HAVE_FINALIZER        DUK_HEAPHDR_USER_FLAG(14)  /* object has a callable (own) finalizer property */
6178 #define DUK_HOBJECT_FLAG_EXOTIC_ARRAY          DUK_HEAPHDR_USER_FLAG(15)  /* 'Array' object, array length and index exotic behavior */
6179 #define DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ      DUK_HEAPHDR_USER_FLAG(16)  /* 'String' object, array index exotic behavior */
6180 #define DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS      DUK_HEAPHDR_USER_FLAG(17)  /* 'Arguments' object and has arguments exotic behavior (non-strict callee) */
6181 #define DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ       DUK_HEAPHDR_USER_FLAG(18)  /* 'Proxy' object */
6182 #define DUK_HOBJECT_FLAG_SPECIAL_CALL          DUK_HEAPHDR_USER_FLAG(19)  /* special casing in call behavior, for .call(), .apply(), etc. */
6183 
6184 #define DUK_HOBJECT_FLAG_CLASS_BASE            DUK_HEAPHDR_USER_FLAG_NUMBER(20)
6185 #define DUK_HOBJECT_FLAG_CLASS_BITS            5
6186 
6187 #define DUK_HOBJECT_GET_CLASS_NUMBER(h)        \
6188 	DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS)
6189 #define DUK_HOBJECT_SET_CLASS_NUMBER(h,v)      \
6190 	DUK_HEAPHDR_SET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS, (v))
6191 
6192 #define DUK_HOBJECT_GET_CLASS_MASK(h)          \
6193 	(1UL << DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS))
6194 
6195 /* Macro for creating flag initializer from a class number.
6196  * Unsigned type cast is needed to avoid warnings about coercing
6197  * a signed integer to an unsigned one; the largest class values
6198  * have the highest bit (bit 31) set which causes this.
6199  */
6200 #define DUK_HOBJECT_CLASS_AS_FLAGS(v)          (((duk_uint_t) (v)) << DUK_HOBJECT_FLAG_CLASS_BASE)
6201 
6202 /* E5 Section 8.6.2 + custom classes */
6203 #define DUK_HOBJECT_CLASS_NONE                 0
6204 #define DUK_HOBJECT_CLASS_OBJECT               1
6205 #define DUK_HOBJECT_CLASS_ARRAY                2
6206 #define DUK_HOBJECT_CLASS_FUNCTION             3
6207 #define DUK_HOBJECT_CLASS_ARGUMENTS            4
6208 #define DUK_HOBJECT_CLASS_BOOLEAN              5
6209 #define DUK_HOBJECT_CLASS_DATE                 6
6210 #define DUK_HOBJECT_CLASS_ERROR                7
6211 #define DUK_HOBJECT_CLASS_JSON                 8
6212 #define DUK_HOBJECT_CLASS_MATH                 9
6213 #define DUK_HOBJECT_CLASS_NUMBER               10
6214 #define DUK_HOBJECT_CLASS_REGEXP               11
6215 #define DUK_HOBJECT_CLASS_STRING               12
6216 #define DUK_HOBJECT_CLASS_GLOBAL               13
6217 #define DUK_HOBJECT_CLASS_SYMBOL               14
6218 #define DUK_HOBJECT_CLASS_OBJENV               15  /* custom */
6219 #define DUK_HOBJECT_CLASS_DECENV               16  /* custom */
6220 #define DUK_HOBJECT_CLASS_POINTER              17  /* custom */
6221 #define DUK_HOBJECT_CLASS_THREAD               18  /* custom; implies DUK_HOBJECT_IS_THREAD */
6222 #define DUK_HOBJECT_CLASS_BUFOBJ_MIN           19
6223 #define DUK_HOBJECT_CLASS_ARRAYBUFFER          19  /* implies DUK_HOBJECT_IS_BUFOBJ */
6224 #define DUK_HOBJECT_CLASS_DATAVIEW             20
6225 #define DUK_HOBJECT_CLASS_INT8ARRAY            21
6226 #define DUK_HOBJECT_CLASS_UINT8ARRAY           22
6227 #define DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY    23
6228 #define DUK_HOBJECT_CLASS_INT16ARRAY           24
6229 #define DUK_HOBJECT_CLASS_UINT16ARRAY          25
6230 #define DUK_HOBJECT_CLASS_INT32ARRAY           26
6231 #define DUK_HOBJECT_CLASS_UINT32ARRAY          27
6232 #define DUK_HOBJECT_CLASS_FLOAT32ARRAY         28
6233 #define DUK_HOBJECT_CLASS_FLOAT64ARRAY         29
6234 #define DUK_HOBJECT_CLASS_BUFOBJ_MAX           29
6235 #define DUK_HOBJECT_CLASS_MAX                  29
6236 
6237 /* Class masks. */
6238 #define DUK_HOBJECT_CMASK_ALL                  ((1UL << (DUK_HOBJECT_CLASS_MAX + 1)) - 1UL)
6239 #define DUK_HOBJECT_CMASK_NONE                 (1UL << DUK_HOBJECT_CLASS_NONE)
6240 #define DUK_HOBJECT_CMASK_ARGUMENTS            (1UL << DUK_HOBJECT_CLASS_ARGUMENTS)
6241 #define DUK_HOBJECT_CMASK_ARRAY                (1UL << DUK_HOBJECT_CLASS_ARRAY)
6242 #define DUK_HOBJECT_CMASK_BOOLEAN              (1UL << DUK_HOBJECT_CLASS_BOOLEAN)
6243 #define DUK_HOBJECT_CMASK_DATE                 (1UL << DUK_HOBJECT_CLASS_DATE)
6244 #define DUK_HOBJECT_CMASK_ERROR                (1UL << DUK_HOBJECT_CLASS_ERROR)
6245 #define DUK_HOBJECT_CMASK_FUNCTION             (1UL << DUK_HOBJECT_CLASS_FUNCTION)
6246 #define DUK_HOBJECT_CMASK_JSON                 (1UL << DUK_HOBJECT_CLASS_JSON)
6247 #define DUK_HOBJECT_CMASK_MATH                 (1UL << DUK_HOBJECT_CLASS_MATH)
6248 #define DUK_HOBJECT_CMASK_NUMBER               (1UL << DUK_HOBJECT_CLASS_NUMBER)
6249 #define DUK_HOBJECT_CMASK_OBJECT               (1UL << DUK_HOBJECT_CLASS_OBJECT)
6250 #define DUK_HOBJECT_CMASK_REGEXP               (1UL << DUK_HOBJECT_CLASS_REGEXP)
6251 #define DUK_HOBJECT_CMASK_STRING               (1UL << DUK_HOBJECT_CLASS_STRING)
6252 #define DUK_HOBJECT_CMASK_GLOBAL               (1UL << DUK_HOBJECT_CLASS_GLOBAL)
6253 #define DUK_HOBJECT_CMASK_SYMBOL               (1UL << DUK_HOBJECT_CLASS_SYMBOL)
6254 #define DUK_HOBJECT_CMASK_OBJENV               (1UL << DUK_HOBJECT_CLASS_OBJENV)
6255 #define DUK_HOBJECT_CMASK_DECENV               (1UL << DUK_HOBJECT_CLASS_DECENV)
6256 #define DUK_HOBJECT_CMASK_POINTER              (1UL << DUK_HOBJECT_CLASS_POINTER)
6257 #define DUK_HOBJECT_CMASK_ARRAYBUFFER          (1UL << DUK_HOBJECT_CLASS_ARRAYBUFFER)
6258 #define DUK_HOBJECT_CMASK_DATAVIEW             (1UL << DUK_HOBJECT_CLASS_DATAVIEW)
6259 #define DUK_HOBJECT_CMASK_INT8ARRAY            (1UL << DUK_HOBJECT_CLASS_INT8ARRAY)
6260 #define DUK_HOBJECT_CMASK_UINT8ARRAY           (1UL << DUK_HOBJECT_CLASS_UINT8ARRAY)
6261 #define DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY    (1UL << DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY)
6262 #define DUK_HOBJECT_CMASK_INT16ARRAY           (1UL << DUK_HOBJECT_CLASS_INT16ARRAY)
6263 #define DUK_HOBJECT_CMASK_UINT16ARRAY          (1UL << DUK_HOBJECT_CLASS_UINT16ARRAY)
6264 #define DUK_HOBJECT_CMASK_INT32ARRAY           (1UL << DUK_HOBJECT_CLASS_INT32ARRAY)
6265 #define DUK_HOBJECT_CMASK_UINT32ARRAY          (1UL << DUK_HOBJECT_CLASS_UINT32ARRAY)
6266 #define DUK_HOBJECT_CMASK_FLOAT32ARRAY         (1UL << DUK_HOBJECT_CLASS_FLOAT32ARRAY)
6267 #define DUK_HOBJECT_CMASK_FLOAT64ARRAY         (1UL << DUK_HOBJECT_CLASS_FLOAT64ARRAY)
6268 
6269 #define DUK_HOBJECT_CMASK_ALL_BUFOBJS \
6270 	(DUK_HOBJECT_CMASK_ARRAYBUFFER | \
6271 	 DUK_HOBJECT_CMASK_DATAVIEW | \
6272 	 DUK_HOBJECT_CMASK_INT8ARRAY | \
6273 	 DUK_HOBJECT_CMASK_UINT8ARRAY | \
6274 	 DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY | \
6275 	 DUK_HOBJECT_CMASK_INT16ARRAY | \
6276 	 DUK_HOBJECT_CMASK_UINT16ARRAY | \
6277 	 DUK_HOBJECT_CMASK_INT32ARRAY | \
6278 	 DUK_HOBJECT_CMASK_UINT32ARRAY | \
6279 	 DUK_HOBJECT_CMASK_FLOAT32ARRAY | \
6280 	 DUK_HOBJECT_CMASK_FLOAT64ARRAY)
6281 
6282 #define DUK_HOBJECT_IS_OBJENV(h)               (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_OBJENV)
6283 #define DUK_HOBJECT_IS_DECENV(h)               (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DECENV)
6284 #define DUK_HOBJECT_IS_ENV(h)                  (DUK_HOBJECT_IS_OBJENV((h)) || DUK_HOBJECT_IS_DECENV((h)))
6285 #define DUK_HOBJECT_IS_ARRAY(h)                DUK_HOBJECT_HAS_EXOTIC_ARRAY((h))  /* Rely on class Array <=> exotic Array */
6286 #define DUK_HOBJECT_IS_BOUNDFUNC(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
6287 #define DUK_HOBJECT_IS_COMPFUNC(h)             DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
6288 #define DUK_HOBJECT_IS_NATFUNC(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
6289 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6290 #define DUK_HOBJECT_IS_BUFOBJ(h)               DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
6291 #else
6292 #define DUK_HOBJECT_IS_BUFOBJ(h)               0
6293 #endif
6294 #define DUK_HOBJECT_IS_THREAD(h)               (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_THREAD)
6295 #if defined(DUK_USE_ES6_PROXY)
6296 #define DUK_HOBJECT_IS_PROXY(h)                DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ((h))
6297 #else
6298 #define DUK_HOBJECT_IS_PROXY(h)                0
6299 #endif
6300 
6301 #define DUK_HOBJECT_IS_NONBOUND_FUNCTION(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
6302                                                         DUK_HOBJECT_FLAG_COMPFUNC | \
6303                                                         DUK_HOBJECT_FLAG_NATFUNC)
6304 
6305 #define DUK_HOBJECT_IS_FUNCTION(h)             DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
6306                                                         DUK_HOBJECT_FLAG_BOUNDFUNC | \
6307                                                         DUK_HOBJECT_FLAG_COMPFUNC | \
6308                                                         DUK_HOBJECT_FLAG_NATFUNC)
6309 
6310 #define DUK_HOBJECT_IS_CALLABLE(h)             DUK_HOBJECT_HAS_CALLABLE((h))
6311 
6312 /* Object has any exotic behavior(s). */
6313 #define DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS      (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
6314                                                 DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS | \
6315                                                 DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \
6316                                                 DUK_HOBJECT_FLAG_BUFOBJ | \
6317                                                 DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
6318 #define DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(h)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS)
6319 
6320 /* Object has any virtual properties (not counting Proxy behavior). */
6321 #define DUK_HOBJECT_VIRTUAL_PROPERTY_FLAGS     (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
6322                                                 DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \
6323                                                 DUK_HOBJECT_FLAG_BUFOBJ)
6324 #define DUK_HOBJECT_HAS_VIRTUAL_PROPERTIES(h)  DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_VIRTUAL_PROPERTY_FLAGS)
6325 
6326 #define DUK_HOBJECT_HAS_EXTENSIBLE(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
6327 #define DUK_HOBJECT_HAS_CONSTRUCTABLE(h)       DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
6328 #define DUK_HOBJECT_HAS_CALLABLE(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)
6329 #define DUK_HOBJECT_HAS_BOUNDFUNC(h)           DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
6330 #define DUK_HOBJECT_HAS_COMPFUNC(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
6331 #define DUK_HOBJECT_HAS_NATFUNC(h)             DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
6332 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6333 #define DUK_HOBJECT_HAS_BUFOBJ(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
6334 #else
6335 #define DUK_HOBJECT_HAS_BUFOBJ(h)              0
6336 #endif
6337 #define DUK_HOBJECT_HAS_FASTREFS(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)
6338 #define DUK_HOBJECT_HAS_ARRAY_PART(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
6339 #define DUK_HOBJECT_HAS_STRICT(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
6340 #define DUK_HOBJECT_HAS_NOTAIL(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
6341 #define DUK_HOBJECT_HAS_NEWENV(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
6342 #define DUK_HOBJECT_HAS_NAMEBINDING(h)         DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
6343 #define DUK_HOBJECT_HAS_CREATEARGS(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
6344 #define DUK_HOBJECT_HAS_HAVE_FINALIZER(h)      DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)
6345 #define DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
6346 #define DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
6347 #define DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
6348 #if defined(DUK_USE_ES6_PROXY)
6349 #define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
6350 #else
6351 #define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)     0
6352 #endif
6353 #define DUK_HOBJECT_HAS_SPECIAL_CALL(h)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)
6354 
6355 #define DUK_HOBJECT_SET_EXTENSIBLE(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
6356 #define DUK_HOBJECT_SET_CONSTRUCTABLE(h)       DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
6357 #define DUK_HOBJECT_SET_CALLABLE(h)            DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)
6358 #define DUK_HOBJECT_SET_BOUNDFUNC(h)           DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
6359 #define DUK_HOBJECT_SET_COMPFUNC(h)            DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
6360 #define DUK_HOBJECT_SET_NATFUNC(h)             DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
6361 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6362 #define DUK_HOBJECT_SET_BUFOBJ(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
6363 #endif
6364 #define DUK_HOBJECT_SET_FASTREFS(h)            DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)
6365 #define DUK_HOBJECT_SET_ARRAY_PART(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
6366 #define DUK_HOBJECT_SET_STRICT(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
6367 #define DUK_HOBJECT_SET_NOTAIL(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
6368 #define DUK_HOBJECT_SET_NEWENV(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
6369 #define DUK_HOBJECT_SET_NAMEBINDING(h)         DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
6370 #define DUK_HOBJECT_SET_CREATEARGS(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
6371 #define DUK_HOBJECT_SET_HAVE_FINALIZER(h)      DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)
6372 #define DUK_HOBJECT_SET_EXOTIC_ARRAY(h)        DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
6373 #define DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h)    DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
6374 #define DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(h)    DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
6375 #if defined(DUK_USE_ES6_PROXY)
6376 #define DUK_HOBJECT_SET_EXOTIC_PROXYOBJ(h)     DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
6377 #endif
6378 #define DUK_HOBJECT_SET_SPECIAL_CALL(h)        DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)
6379 
6380 #define DUK_HOBJECT_CLEAR_EXTENSIBLE(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
6381 #define DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h)     DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
6382 #define DUK_HOBJECT_CLEAR_CALLABLE(h)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)
6383 #define DUK_HOBJECT_CLEAR_BOUNDFUNC(h)         DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
6384 #define DUK_HOBJECT_CLEAR_COMPFUNC(h)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
6385 #define DUK_HOBJECT_CLEAR_NATFUNC(h)           DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
6386 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6387 #define DUK_HOBJECT_CLEAR_BUFOBJ(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
6388 #endif
6389 #define DUK_HOBJECT_CLEAR_FASTREFS(h)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)
6390 #define DUK_HOBJECT_CLEAR_ARRAY_PART(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
6391 #define DUK_HOBJECT_CLEAR_STRICT(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
6392 #define DUK_HOBJECT_CLEAR_NOTAIL(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
6393 #define DUK_HOBJECT_CLEAR_NEWENV(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
6394 #define DUK_HOBJECT_CLEAR_NAMEBINDING(h)       DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
6395 #define DUK_HOBJECT_CLEAR_CREATEARGS(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
6396 #define DUK_HOBJECT_CLEAR_HAVE_FINALIZER(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)
6397 #define DUK_HOBJECT_CLEAR_EXOTIC_ARRAY(h)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
6398 #define DUK_HOBJECT_CLEAR_EXOTIC_STRINGOBJ(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
6399 #define DUK_HOBJECT_CLEAR_EXOTIC_ARGUMENTS(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
6400 #if defined(DUK_USE_ES6_PROXY)
6401 #define DUK_HOBJECT_CLEAR_EXOTIC_PROXYOBJ(h)   DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
6402 #endif
6403 #define DUK_HOBJECT_CLEAR_SPECIAL_CALL(h)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)
6404 
6405 /* Object can/cannot use FASTREFS, i.e. has no strong reference fields beyond
6406  * duk_hobject base header.  This is used just for asserts so doesn't need to
6407  * be optimized.
6408  */
6409 #define DUK_HOBJECT_PROHIBITS_FASTREFS(h) \
6410 	(DUK_HOBJECT_IS_COMPFUNC((h)) || DUK_HOBJECT_IS_DECENV((h)) || DUK_HOBJECT_IS_OBJENV((h)) || \
6411 	 DUK_HOBJECT_IS_BUFOBJ((h)) || DUK_HOBJECT_IS_THREAD((h)) || DUK_HOBJECT_IS_PROXY((h)) || \
6412 	 DUK_HOBJECT_IS_BOUNDFUNC((h)))
6413 #define DUK_HOBJECT_ALLOWS_FASTREFS(h) (!DUK_HOBJECT_PROHIBITS_FASTREFS((h)))
6414 
6415 /* Flags used for property attributes in duk_propdesc and packed flags.
6416  * Must fit into 8 bits.
6417  */
6418 #define DUK_PROPDESC_FLAG_WRITABLE              (1U << 0)    /* E5 Section 8.6.1 */
6419 #define DUK_PROPDESC_FLAG_ENUMERABLE            (1U << 1)    /* E5 Section 8.6.1 */
6420 #define DUK_PROPDESC_FLAG_CONFIGURABLE          (1U << 2)    /* E5 Section 8.6.1 */
6421 #define DUK_PROPDESC_FLAG_ACCESSOR              (1U << 3)    /* accessor */
6422 #define DUK_PROPDESC_FLAG_VIRTUAL               (1U << 4)    /* property is virtual: used in duk_propdesc, never stored
6423                                                              * (used by e.g. buffer virtual properties)
6424                                                              */
6425 #define DUK_PROPDESC_FLAGS_MASK                 (DUK_PROPDESC_FLAG_WRITABLE | \
6426                                                  DUK_PROPDESC_FLAG_ENUMERABLE | \
6427                                                  DUK_PROPDESC_FLAG_CONFIGURABLE | \
6428                                                  DUK_PROPDESC_FLAG_ACCESSOR)
6429 
6430 /* Additional flags which are passed in the same flags argument as property
6431  * flags but are not stored in object properties.
6432  */
6433 #define DUK_PROPDESC_FLAG_NO_OVERWRITE          (1U << 4)    /* internal define property: skip write silently if exists */
6434 
6435 /* Convenience defines for property attributes. */
6436 #define DUK_PROPDESC_FLAGS_NONE                 0
6437 #define DUK_PROPDESC_FLAGS_W                    (DUK_PROPDESC_FLAG_WRITABLE)
6438 #define DUK_PROPDESC_FLAGS_E                    (DUK_PROPDESC_FLAG_ENUMERABLE)
6439 #define DUK_PROPDESC_FLAGS_C                    (DUK_PROPDESC_FLAG_CONFIGURABLE)
6440 #define DUK_PROPDESC_FLAGS_WE                   (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ENUMERABLE)
6441 #define DUK_PROPDESC_FLAGS_WC                   (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
6442 #define DUK_PROPDESC_FLAGS_EC                   (DUK_PROPDESC_FLAG_ENUMERABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
6443 #define DUK_PROPDESC_FLAGS_WEC                  (DUK_PROPDESC_FLAG_WRITABLE | \
6444                                                  DUK_PROPDESC_FLAG_ENUMERABLE | \
6445                                                  DUK_PROPDESC_FLAG_CONFIGURABLE)
6446 
6447 /* Flags for duk_hobject_get_own_propdesc() and variants. */
6448 #define DUK_GETDESC_FLAG_PUSH_VALUE          (1U << 0)  /* push value to stack */
6449 #define DUK_GETDESC_FLAG_IGNORE_PROTOLOOP    (1U << 1)  /* don't throw for prototype loop */
6450 
6451 /*
6452  *  Macro for object validity check
6453  *
6454  *  Assert for currently guaranteed relations between flags, for instance.
6455  */
6456 
6457 #if defined(DUK_USE_ASSERTIONS)
6458 DUK_INTERNAL_DECL void duk_hobject_assert_valid(duk_hobject *h);
6459 #define DUK_HOBJECT_ASSERT_VALID(h)  do { duk_hobject_assert_valid((h)); } while (0)
6460 #else
6461 #define DUK_HOBJECT_ASSERT_VALID(h)  do {} while (0)
6462 #endif
6463 
6464 /*
6465  *  Macros to access the 'props' allocation.
6466  */
6467 
6468 #if defined(DUK_USE_HEAPPTR16)
6469 #define DUK_HOBJECT_GET_PROPS(heap,h) \
6470 	((duk_uint8_t *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (h))->h_extra16))
6471 #define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \
6472 		((duk_heaphdr *) (h))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
6473 	} while (0)
6474 #else
6475 #define DUK_HOBJECT_GET_PROPS(heap,h) \
6476 	((h)->props)
6477 #define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \
6478 		(h)->props = (duk_uint8_t *) (x); \
6479 	} while (0)
6480 #endif
6481 
6482 #if defined(DUK_USE_HOBJECT_LAYOUT_1)
6483 /* LAYOUT 1 */
6484 #define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
6485 	((duk_hstring **) (void *) ( \
6486 		DUK_HOBJECT_GET_PROPS((heap), (h)) \
6487 	))
6488 #define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
6489 	((duk_propvalue *) (void *) ( \
6490 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6491 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_hstring *) \
6492 	))
6493 #define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
6494 	((duk_uint8_t *) (void *) ( \
6495 		DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
6496 	))
6497 #define DUK_HOBJECT_A_GET_BASE(heap,h) \
6498 	((duk_tval *) (void *) ( \
6499 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6500 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) \
6501 	))
6502 #define DUK_HOBJECT_H_GET_BASE(heap,h) \
6503 	((duk_uint32_t *) (void *) ( \
6504 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6505 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6506 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
6507 	))
6508 #define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
6509 	( \
6510 		(n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6511 		(n_arr) * sizeof(duk_tval) + \
6512 		(n_hash) * sizeof(duk_uint32_t) \
6513 	)
6514 #define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base,set_e_k,set_e_pv,set_e_f,set_a,set_h,n_ent,n_arr,n_hash)  do { \
6515 		(set_e_k) = (duk_hstring **) (void *) (p_base); \
6516 		(set_e_pv) = (duk_propvalue *) (void *) ((set_e_k) + (n_ent)); \
6517 		(set_e_f) = (duk_uint8_t *) (void *) ((set_e_pv) + (n_ent)); \
6518 		(set_a) = (duk_tval *) (void *) ((set_e_f) + (n_ent)); \
6519 		(set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \
6520 	} while (0)
6521 #elif defined(DUK_USE_HOBJECT_LAYOUT_2)
6522 /* LAYOUT 2 */
6523 #if (DUK_USE_ALIGN_BY == 4)
6524 #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((4 - (e_sz)) & 0x03)
6525 #elif (DUK_USE_ALIGN_BY == 8)
6526 #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((8 - (e_sz)) & 0x07)
6527 #elif (DUK_USE_ALIGN_BY == 1)
6528 #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) 0
6529 #else
6530 #error invalid DUK_USE_ALIGN_BY
6531 #endif
6532 #define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
6533 	((duk_hstring **) (void *) ( \
6534 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6535 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \
6536 	))
6537 #define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
6538 	((duk_propvalue *) (void *) ( \
6539 		DUK_HOBJECT_GET_PROPS((heap), (h)) \
6540 	))
6541 #define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
6542 	((duk_uint8_t *) (void *) ( \
6543 		DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
6544 	))
6545 #define DUK_HOBJECT_A_GET_BASE(heap,h) \
6546 	((duk_tval *) (void *) ( \
6547 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6548 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6549 			DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) \
6550 	))
6551 #define DUK_HOBJECT_H_GET_BASE(heap,h) \
6552 	((duk_uint32_t *) (void *) ( \
6553 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6554 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6555 			DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) + \
6556 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
6557 	))
6558 #define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
6559 	( \
6560 		(n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6561 		DUK_HOBJECT_E_FLAG_PADDING((n_ent)) + \
6562 		(n_arr) * sizeof(duk_tval) + \
6563 		(n_hash) * sizeof(duk_uint32_t) \
6564 	)
6565 #define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base,set_e_k,set_e_pv,set_e_f,set_a,set_h,n_ent,n_arr,n_hash)  do { \
6566 		(set_e_pv) = (duk_propvalue *) (void *) (p_base); \
6567 		(set_e_k) = (duk_hstring **) (void *) ((set_e_pv) + (n_ent)); \
6568 		(set_e_f) = (duk_uint8_t *) (void *) ((set_e_k) + (n_ent)); \
6569 		(set_a) = (duk_tval *) (void *) (((duk_uint8_t *) (set_e_f)) + \
6570 		                                 sizeof(duk_uint8_t) * (n_ent) + \
6571 		                                 DUK_HOBJECT_E_FLAG_PADDING((n_ent))); \
6572 		(set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \
6573 	} while (0)
6574 #elif defined(DUK_USE_HOBJECT_LAYOUT_3)
6575 /* LAYOUT 3 */
6576 #define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
6577 	((duk_hstring **) (void *) ( \
6578 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6579 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) + \
6580 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
6581 	))
6582 #define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
6583 	((duk_propvalue *) (void *) ( \
6584 		DUK_HOBJECT_GET_PROPS((heap), (h)) \
6585 	))
6586 #define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
6587 	((duk_uint8_t *) (void *) ( \
6588 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6589 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
6590 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) + \
6591 			DUK_HOBJECT_GET_HSIZE((h)) * sizeof(duk_uint32_t) \
6592 	))
6593 #define DUK_HOBJECT_A_GET_BASE(heap,h) \
6594 	((duk_tval *) (void *) ( \
6595 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6596 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \
6597 	))
6598 #define DUK_HOBJECT_H_GET_BASE(heap,h) \
6599 	((duk_uint32_t *) (void *) ( \
6600 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6601 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
6602 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
6603 	))
6604 #define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
6605 	( \
6606 		(n_ent) * (sizeof(duk_propvalue) + sizeof(duk_hstring *) + sizeof(duk_uint8_t)) + \
6607 		(n_arr) * sizeof(duk_tval) + \
6608 		(n_hash) * sizeof(duk_uint32_t) \
6609 	)
6610 #define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base,set_e_k,set_e_pv,set_e_f,set_a,set_h,n_ent,n_arr,n_hash)  do { \
6611 		(set_e_pv) = (duk_propvalue *) (void *) (p_base); \
6612 		(set_a) = (duk_tval *) (void *) ((set_e_pv) + (n_ent)); \
6613 		(set_e_k) = (duk_hstring **) (void *) ((set_a) + (n_arr)); \
6614 		(set_h) = (duk_uint32_t *) (void *) ((set_e_k) + (n_ent)); \
6615 		(set_e_f) = (duk_uint8_t *) (void *) ((set_h) + (n_hash)); \
6616 	} while (0)
6617 #else
6618 #error invalid hobject layout defines
6619 #endif  /* hobject property layout */
6620 
6621 #define DUK_HOBJECT_P_ALLOC_SIZE(h) \
6622 	DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE((h)), DUK_HOBJECT_GET_ASIZE((h)), DUK_HOBJECT_GET_HSIZE((h)))
6623 
6624 #define DUK_HOBJECT_E_GET_KEY(heap,h,i)              (DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
6625 #define DUK_HOBJECT_E_GET_KEY_PTR(heap,h,i)          (&DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
6626 #define DUK_HOBJECT_E_GET_VALUE(heap,h,i)            (DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
6627 #define DUK_HOBJECT_E_GET_VALUE_PTR(heap,h,i)        (&DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
6628 #define DUK_HOBJECT_E_GET_VALUE_TVAL(heap,h,i)       (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
6629 #define DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap,h,i)   (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
6630 #define DUK_HOBJECT_E_GET_VALUE_GETTER(heap,h,i)     (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
6631 #define DUK_HOBJECT_E_GET_VALUE_GETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
6632 #define DUK_HOBJECT_E_GET_VALUE_SETTER(heap,h,i)     (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
6633 #define DUK_HOBJECT_E_GET_VALUE_SETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
6634 #define DUK_HOBJECT_E_GET_FLAGS(heap,h,i)            (DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
6635 #define DUK_HOBJECT_E_GET_FLAGS_PTR(heap,h,i)        (&DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
6636 #define DUK_HOBJECT_A_GET_VALUE(heap,h,i)            (DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
6637 #define DUK_HOBJECT_A_GET_VALUE_PTR(heap,h,i)        (&DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
6638 #define DUK_HOBJECT_H_GET_INDEX(heap,h,i)            (DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
6639 #define DUK_HOBJECT_H_GET_INDEX_PTR(heap,h,i)        (&DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
6640 
6641 #define DUK_HOBJECT_E_SET_KEY(heap,h,i,k)  do { \
6642 		DUK_HOBJECT_E_GET_KEY((heap), (h), (i)) = (k); \
6643 	} while (0)
6644 #define DUK_HOBJECT_E_SET_VALUE(heap,h,i,v)  do { \
6645 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)) = (v); \
6646 	} while (0)
6647 #define DUK_HOBJECT_E_SET_VALUE_TVAL(heap,h,i,v)  do { \
6648 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v = (v); \
6649 	} while (0)
6650 #define DUK_HOBJECT_E_SET_VALUE_GETTER(heap,h,i,v)  do { \
6651 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get = (v); \
6652 	} while (0)
6653 #define DUK_HOBJECT_E_SET_VALUE_SETTER(heap,h,i,v)  do { \
6654 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set = (v); \
6655 	} while (0)
6656 #define DUK_HOBJECT_E_SET_FLAGS(heap,h,i,f)  do { \
6657 		DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) = (duk_uint8_t) (f); \
6658 	} while (0)
6659 #define DUK_HOBJECT_A_SET_VALUE(heap,h,i,v)  do { \
6660 		DUK_HOBJECT_A_GET_VALUE((heap), (h), (i)) = (v); \
6661 	} while (0)
6662 #define DUK_HOBJECT_A_SET_VALUE_TVAL(heap,h,i,v) \
6663 	DUK_HOBJECT_A_SET_VALUE((heap), (h), (i), (v))  /* alias for above */
6664 #define DUK_HOBJECT_H_SET_INDEX(heap,h,i,v)  do { \
6665 		DUK_HOBJECT_H_GET_INDEX((heap), (h), (i)) = (v); \
6666 	} while (0)
6667 
6668 #define DUK_HOBJECT_E_SET_FLAG_BITS(heap,h,i,mask)  do { \
6669 		DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] |= (mask); \
6670 	} while (0)
6671 
6672 #define DUK_HOBJECT_E_CLEAR_FLAG_BITS(heap,h,i,mask)  do { \
6673 		DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] &= ~(mask); \
6674 	} while (0)
6675 
6676 #define DUK_HOBJECT_E_SLOT_IS_WRITABLE(heap,h,i)     ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_WRITABLE) != 0)
6677 #define DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(heap,h,i)   ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
6678 #define DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
6679 #define DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap,h,i)     ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
6680 
6681 #define DUK_HOBJECT_E_SLOT_SET_WRITABLE(heap,h,i)        DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)
6682 #define DUK_HOBJECT_E_SLOT_SET_ENUMERABLE(heap,h,i)      DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)
6683 #define DUK_HOBJECT_E_SLOT_SET_CONFIGURABLE(heap,h,i)    DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)
6684 #define DUK_HOBJECT_E_SLOT_SET_ACCESSOR(heap,h,i)        DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)
6685 
6686 #define DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(heap,h,i)      DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)
6687 #define DUK_HOBJECT_E_SLOT_CLEAR_ENUMERABLE(heap,h,i)    DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)
6688 #define DUK_HOBJECT_E_SLOT_CLEAR_CONFIGURABLE(heap,h,i)  DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)
6689 #define DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(heap,h,i)      DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)
6690 
6691 #define DUK_PROPDESC_IS_WRITABLE(p)             (((p)->flags & DUK_PROPDESC_FLAG_WRITABLE) != 0)
6692 #define DUK_PROPDESC_IS_ENUMERABLE(p)           (((p)->flags & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
6693 #define DUK_PROPDESC_IS_CONFIGURABLE(p)         (((p)->flags & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
6694 #define DUK_PROPDESC_IS_ACCESSOR(p)             (((p)->flags & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
6695 
6696 #define DUK_HOBJECT_HASHIDX_UNUSED              0xffffffffUL
6697 #define DUK_HOBJECT_HASHIDX_DELETED             0xfffffffeUL
6698 
6699 /*
6700  *  Macros for accessing size fields
6701  */
6702 
6703 #if defined(DUK_USE_OBJSIZES16)
6704 #define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size16)
6705 #define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size16 = (v); } while (0)
6706 #define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next16)
6707 #define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next16 = (v); } while (0)
6708 #define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next16++)
6709 #define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size16)
6710 #define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size16 = (v); } while (0)
6711 #if defined(DUK_USE_HOBJECT_HASH_PART)
6712 #define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size16)
6713 #define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size16 = (v); } while (0)
6714 #else
6715 #define DUK_HOBJECT_GET_HSIZE(h) 0
6716 #define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)
6717 #endif
6718 #else
6719 #define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size)
6720 #define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size = (v); } while (0)
6721 #define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next)
6722 #define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next = (v); } while (0)
6723 #define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next++)
6724 #define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size)
6725 #define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size = (v); } while (0)
6726 #if defined(DUK_USE_HOBJECT_HASH_PART)
6727 #define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size)
6728 #define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size = (v); } while (0)
6729 #else
6730 #define DUK_HOBJECT_GET_HSIZE(h) 0
6731 #define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)
6732 #endif
6733 #endif
6734 
6735 /*
6736  *  Misc
6737  */
6738 
6739 /* Maximum prototype traversal depth.  Sanity limit which handles e.g.
6740  * prototype loops (even complex ones like 1->2->3->4->2->3->4->2->3->4).
6741  */
6742 #define DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY      10000L
6743 
6744 /*
6745  *  ECMAScript [[Class]]
6746  */
6747 
6748 /* range check not necessary because all 4-bit values are mapped */
6749 #define DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(n)  duk_class_number_to_stridx[(n)]
6750 
6751 #define DUK_HOBJECT_GET_CLASS_STRING(heap,h)          \
6752 	DUK_HEAP_GET_STRING( \
6753 		(heap), \
6754 		DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(DUK_HOBJECT_GET_CLASS_NUMBER((h))) \
6755 	)
6756 
6757 /*
6758  *  Macros for property handling
6759  */
6760 
6761 #if defined(DUK_USE_HEAPPTR16)
6762 #define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \
6763 	((duk_hobject *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->prototype16))
6764 #define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \
6765 		(h)->prototype16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
6766 	} while (0)
6767 #else
6768 #define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \
6769 	((h)->prototype)
6770 #define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \
6771 		(h)->prototype = (x); \
6772 	} while (0)
6773 #endif
6774 
6775 /* Set prototype, DECREF earlier value, INCREF new value (tolerating NULLs). */
6776 #define DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr,h,p)       duk_hobject_set_prototype_updref((thr), (h), (p))
6777 
6778 /* Set initial prototype, assume NULL previous prototype, INCREF new value,
6779  * tolerate NULL.
6780  */
6781 #define DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr,h,proto) do { \
6782 		duk_hthread *duk__thr = (thr); \
6783 		duk_hobject *duk__obj = (h); \
6784 		duk_hobject *duk__proto = (proto); \
6785 		DUK_UNREF(duk__thr); \
6786 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(duk__thr->heap, duk__obj) == NULL); \
6787 		DUK_HOBJECT_SET_PROTOTYPE(duk__thr->heap, duk__obj, duk__proto); \
6788 		DUK_HOBJECT_INCREF_ALLOWNULL(duk__thr, duk__proto); \
6789 	} while (0)
6790 
6791 /*
6792  *  Finalizer check
6793  */
6794 
6795 #if defined(DUK_USE_HEAPPTR16)
6796 #define DUK_HOBJECT_HAS_FINALIZER_FAST(heap,h) duk_hobject_has_finalizer_fast_raw((heap), (h))
6797 #else
6798 #define DUK_HOBJECT_HAS_FINALIZER_FAST(heap,h) duk_hobject_has_finalizer_fast_raw((h))
6799 #endif
6800 
6801 /*
6802  *  Resizing and hash behavior
6803  */
6804 
6805 /* Sanity limit on max number of properties (allocated, not necessarily used).
6806  * This is somewhat arbitrary, but if we're close to 2**32 properties some
6807  * algorithms will fail (e.g. hash size selection, next prime selection).
6808  * Also, we use negative array/entry table indices to indicate 'not found',
6809  * so anything above 0x80000000 will cause trouble now.
6810  */
6811 #if defined(DUK_USE_OBJSIZES16)
6812 #define DUK_HOBJECT_MAX_PROPERTIES       0x0000ffffUL
6813 #else
6814 #define DUK_HOBJECT_MAX_PROPERTIES       0x3fffffffUL   /* 2**30-1 ~= 1G properties */
6815 #endif
6816 
6817 /* internal align target for props allocation, must be 2*n for some n */
6818 #if (DUK_USE_ALIGN_BY == 4)
6819 #define DUK_HOBJECT_ALIGN_TARGET         4
6820 #elif (DUK_USE_ALIGN_BY == 8)
6821 #define DUK_HOBJECT_ALIGN_TARGET         8
6822 #elif (DUK_USE_ALIGN_BY == 1)
6823 #define DUK_HOBJECT_ALIGN_TARGET         1
6824 #else
6825 #error invalid DUK_USE_ALIGN_BY
6826 #endif
6827 
6828 /*
6829  *  PC-to-line constants
6830  */
6831 
6832 #define DUK_PC2LINE_SKIP    64
6833 
6834 /* maximum length for a SKIP-1 diffstream: 35 bits per entry, rounded up to bytes */
6835 #define DUK_PC2LINE_MAX_DIFF_LENGTH    (((DUK_PC2LINE_SKIP - 1) * 35 + 7) / 8)
6836 
6837 /*
6838  *  Struct defs
6839  */
6840 
6841 struct duk_propaccessor {
6842 	duk_hobject *get;
6843 	duk_hobject *set;
6844 };
6845 
6846 union duk_propvalue {
6847 	/* The get/set pointers could be 16-bit pointer compressed but it
6848 	 * would make no difference on 32-bit platforms because duk_tval is
6849 	 * 8 bytes or more anyway.
6850 	 */
6851 	duk_tval v;
6852 	duk_propaccessor a;
6853 };
6854 
6855 struct duk_propdesc {
6856 	/* read-only values 'lifted' for ease of use */
6857 	duk_small_uint_t flags;
6858 	duk_hobject *get;
6859 	duk_hobject *set;
6860 
6861 	/* for updating (all are set to < 0 for virtual properties) */
6862 	duk_int_t e_idx;  /* prop index in 'entry part', < 0 if not there */
6863 	duk_int_t h_idx;  /* prop index in 'hash part', < 0 if not there */
6864 	duk_int_t a_idx;  /* prop index in 'array part', < 0 if not there */
6865 };
6866 
6867 struct duk_hobject {
6868 	duk_heaphdr hdr;
6869 
6870 	/*
6871 	 *  'props' contains {key,value,flags} entries, optional array entries, and
6872 	 *  an optional hash lookup table for non-array entries in a single 'sliced'
6873 	 *  allocation.  There are several layout options, which differ slightly in
6874 	 *  generated code size/speed and alignment/padding; duk_features.h selects
6875 	 *  the layout used.
6876 	 *
6877 	 *  Layout 1 (DUK_USE_HOBJECT_LAYOUT_1):
6878 	 *
6879 	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)
6880 	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)
6881 	 *    e_size * sizeof(duk_uint8_t)           bytes of   entry flags (e_next gc reachable)
6882 	 *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)
6883 	 *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),
6884 	 *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted
6885 	 *
6886 	 *  Layout 2 (DUK_USE_HOBJECT_LAYOUT_2):
6887 	 *
6888 	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)
6889 	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)
6890 	 *    e_size * sizeof(duk_uint8_t) + pad     bytes of   entry flags (e_next gc reachable)
6891 	 *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)
6892 	 *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),
6893 	 *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted
6894 	 *
6895 	 *  Layout 3 (DUK_USE_HOBJECT_LAYOUT_3):
6896 	 *
6897 	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)
6898 	 *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)
6899 	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)
6900 	 *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),
6901 	 *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted
6902 	 *    e_size * sizeof(duk_uint8_t)           bytes of   entry flags (e_next gc reachable)
6903 	 *
6904 	 *  In layout 1, the 'e_next' count is rounded to 4 or 8 on platforms
6905 	 *  requiring 4 or 8 byte alignment.  This ensures proper alignment
6906 	 *  for the entries, at the cost of memory footprint.  However, it's
6907 	 *  probably preferable to use another layout on such platforms instead.
6908 	 *
6909 	 *  In layout 2, the key and value parts are swapped to avoid padding
6910 	 *  the key array on platforms requiring alignment by 8.  The flags part
6911 	 *  is padded to get alignment for array entries.  The 'e_next' count does
6912 	 *  not need to be rounded as in layout 1.
6913 	 *
6914 	 *  In layout 3, entry values and array values are always aligned properly,
6915 	 *  and assuming pointers are at most 8 bytes, so are the entry keys.  Hash
6916 	 *  indices will be properly aligned (assuming pointers are at least 4 bytes).
6917 	 *  Finally, flags don't need additional alignment.  This layout provides
6918 	 *  compact allocations without padding (even on platforms with alignment
6919 	 *  requirements) at the cost of a bit slower lookups.
6920 	 *
6921 	 *  Objects with few keys don't have a hash index; keys are looked up linearly,
6922 	 *  which is cache efficient because the keys are consecutive.  Larger objects
6923 	 *  have a hash index part which contains integer indexes to the entries part.
6924 	 *
6925 	 *  A single allocation reduces memory allocation overhead but requires more
6926 	 *  work when any part needs to be resized.  A sliced allocation for entries
6927 	 *  makes linear key matching faster on most platforms (more locality) and
6928 	 *  skimps on flags size (which would be followed by 3 bytes of padding in
6929 	 *  most architectures if entries were placed in a struct).
6930 	 *
6931 	 *  'props' also contains internal properties distinguished with a non-BMP
6932 	 *  prefix.  Often used properties should be placed early in 'props' whenever
6933 	 *  possible to make accessing them as fast a possible.
6934 	 */
6935 
6936 #if defined(DUK_USE_HEAPPTR16)
6937 	/* Located in duk_heaphdr h_extra16.  Subclasses of duk_hobject (like
6938 	 * duk_hcompfunc) are not free to use h_extra16 for this reason.
6939 	 */
6940 #else
6941 	duk_uint8_t *props;
6942 #endif
6943 
6944 	/* prototype: the only internal property lifted outside 'e' as it is so central */
6945 #if defined(DUK_USE_HEAPPTR16)
6946 	duk_uint16_t prototype16;
6947 #else
6948 	duk_hobject *prototype;
6949 #endif
6950 
6951 #if defined(DUK_USE_OBJSIZES16)
6952 	duk_uint16_t e_size16;
6953 	duk_uint16_t e_next16;
6954 	duk_uint16_t a_size16;
6955 #if defined(DUK_USE_HOBJECT_HASH_PART)
6956 	duk_uint16_t h_size16;
6957 #endif
6958 #else
6959 	duk_uint32_t e_size;  /* entry part size */
6960 	duk_uint32_t e_next;  /* index for next new key ([0,e_next[ are gc reachable) */
6961 	duk_uint32_t a_size;  /* array part size (entirely gc reachable) */
6962 #if defined(DUK_USE_HOBJECT_HASH_PART)
6963 	duk_uint32_t h_size;  /* hash part size or 0 if unused */
6964 #endif
6965 #endif
6966 };
6967 
6968 /*
6969  *  Exposed data
6970  */
6971 
6972 #if !defined(DUK_SINGLE_FILE)
6973 DUK_INTERNAL_DECL duk_uint8_t duk_class_number_to_stridx[32];
6974 #endif  /* !DUK_SINGLE_FILE */
6975 
6976 /*
6977  *  Prototypes
6978  */
6979 
6980 /* alloc and init */
6981 DUK_INTERNAL_DECL duk_hobject *duk_hobject_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags);
6982 DUK_INTERNAL_DECL duk_hobject *duk_hobject_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6983 DUK_INTERNAL_DECL duk_harray *duk_harray_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6984 DUK_INTERNAL_DECL duk_hcompfunc *duk_hcompfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6985 DUK_INTERNAL_DECL duk_hnatfunc *duk_hnatfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6986 DUK_INTERNAL_DECL duk_hboundfunc *duk_hboundfunc_alloc(duk_heap *heap, duk_uint_t hobject_flags);
6987 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6988 DUK_INTERNAL_DECL duk_hbufobj *duk_hbufobj_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6989 #endif
6990 DUK_INTERNAL_DECL duk_hthread *duk_hthread_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags);
6991 DUK_INTERNAL_DECL duk_hthread *duk_hthread_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6992 DUK_INTERNAL_DECL duk_hdecenv *duk_hdecenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6993 DUK_INTERNAL_DECL duk_hobjenv *duk_hobjenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6994 DUK_INTERNAL_DECL duk_hproxy *duk_hproxy_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6995 
6996 /* resize */
6997 DUK_INTERNAL_DECL void duk_hobject_realloc_props(duk_hthread *thr,
6998                                                  duk_hobject *obj,
6999                                                  duk_uint32_t new_e_size,
7000                                                  duk_uint32_t new_a_size,
7001                                                  duk_uint32_t new_h_size,
7002                                                  duk_bool_t abandon_array);
7003 DUK_INTERNAL_DECL void duk_hobject_resize_entrypart(duk_hthread *thr,
7004                                                     duk_hobject *obj,
7005                                                     duk_uint32_t new_e_size);
7006 #if 0  /*unused*/
7007 DUK_INTERNAL_DECL void duk_hobject_resize_arraypart(duk_hthread *thr,
7008                                                     duk_hobject *obj,
7009                                                     duk_uint32_t new_a_size);
7010 #endif
7011 
7012 /* low-level property functions */
7013 DUK_INTERNAL_DECL duk_bool_t duk_hobject_find_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx);
7014 DUK_INTERNAL_DECL duk_tval *duk_hobject_find_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key);
7015 DUK_INTERNAL_DECL duk_tval *duk_hobject_find_entry_tval_ptr_stridx(duk_heap *heap, duk_hobject *obj, duk_small_uint_t stridx);
7016 DUK_INTERNAL_DECL duk_tval *duk_hobject_find_entry_tval_ptr_and_attrs(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_uint_t *out_attrs);
7017 DUK_INTERNAL_DECL duk_tval *duk_hobject_find_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i);
7018 DUK_INTERNAL_DECL duk_bool_t duk_hobject_get_own_propdesc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags);
7019 
7020 /* core property functions */
7021 DUK_INTERNAL_DECL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);
7022 DUK_INTERNAL_DECL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_tval *tv_val, duk_bool_t throw_flag);
7023 DUK_INTERNAL_DECL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_bool_t throw_flag);
7024 DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);
7025 
7026 /* internal property functions */
7027 #define DUK_DELPROP_FLAG_THROW  (1U << 0)
7028 #define DUK_DELPROP_FLAG_FORCE  (1U << 1)
7029 DUK_INTERNAL_DECL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags);
7030 DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key);
7031 DUK_INTERNAL_DECL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags);
7032 DUK_INTERNAL_DECL void duk_hobject_define_property_internal_arridx(duk_hthread *thr, duk_hobject *obj, duk_uarridx_t arr_idx, duk_small_uint_t flags);
7033 DUK_INTERNAL_DECL duk_size_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj);
7034 #if defined(DUK_USE_HEAPPTR16)
7035 DUK_INTERNAL_DECL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_heap *heap, duk_hobject *obj);
7036 #else
7037 DUK_INTERNAL_DECL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_hobject *obj);
7038 #endif
7039 
7040 /* helpers for defineProperty() and defineProperties() */
7041 DUK_INTERNAL_DECL void duk_hobject_prepare_property_descriptor(duk_hthread *thr,
7042                                                                duk_idx_t idx_in,
7043                                                                duk_uint_t *out_defprop_flags,
7044                                                                duk_idx_t *out_idx_value,
7045                                                                duk_hobject **out_getter,
7046                                                                duk_hobject **out_setter);
7047 DUK_INTERNAL_DECL duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
7048                                                                 duk_uint_t defprop_flags,
7049                                                                 duk_hobject *obj,
7050                                                                 duk_hstring *key,
7051                                                                 duk_idx_t idx_value,
7052                                                                 duk_hobject *get,
7053                                                                 duk_hobject *set,
7054                                                                 duk_bool_t throw_flag);
7055 
7056 /* Object built-in methods */
7057 DUK_INTERNAL_DECL void duk_hobject_object_get_own_property_descriptor(duk_hthread *thr, duk_idx_t obj_idx);
7058 DUK_INTERNAL_DECL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_freeze);
7059 DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_frozen);
7060 DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_ownprop_helper(duk_hthread *thr, duk_small_uint_t required_desc_flags);
7061 
7062 /* internal properties */
7063 DUK_INTERNAL_DECL duk_tval *duk_hobject_get_internal_value_tval_ptr(duk_heap *heap, duk_hobject *obj);
7064 DUK_INTERNAL_DECL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj);
7065 DUK_INTERNAL_DECL duk_harray *duk_hobject_get_formals(duk_hthread *thr, duk_hobject *obj);
7066 DUK_INTERNAL_DECL duk_hobject *duk_hobject_get_varmap(duk_hthread *thr, duk_hobject *obj);
7067 
7068 /* hobject management functions */
7069 DUK_INTERNAL_DECL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj);
7070 
7071 /* ES2015 proxy */
7072 #if defined(DUK_USE_ES6_PROXY)
7073 DUK_INTERNAL_DECL duk_bool_t duk_hobject_proxy_check(duk_hobject *obj, duk_hobject **out_target, duk_hobject **out_handler);
7074 DUK_INTERNAL_DECL duk_hobject *duk_hobject_resolve_proxy_target(duk_hobject *obj);
7075 #endif
7076 
7077 /* enumeration */
7078 DUK_INTERNAL_DECL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint_t enum_flags);
7079 DUK_INTERNAL_DECL duk_ret_t duk_hobject_get_enumerated_keys(duk_hthread *thr, duk_small_uint_t enum_flags);
7080 DUK_INTERNAL_DECL duk_bool_t duk_hobject_enumerator_next(duk_hthread *thr, duk_bool_t get_value);
7081 
7082 /* macros */
7083 DUK_INTERNAL_DECL void duk_hobject_set_prototype_updref(duk_hthread *thr, duk_hobject *h, duk_hobject *p);
7084 
7085 /* pc2line */
7086 #if defined(DUK_USE_PC2LINE)
7087 DUK_INTERNAL_DECL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_uint_fast32_t length);
7088 DUK_INTERNAL_DECL duk_uint_fast32_t duk_hobject_pc2line_query(duk_hthread *thr, duk_idx_t idx_func, duk_uint_fast32_t pc);
7089 #endif
7090 
7091 /* misc */
7092 DUK_INTERNAL_DECL duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *thr, duk_hobject *h, duk_hobject *p, duk_bool_t ignore_loop);
7093 
7094 #if !defined(DUK_USE_OBJECT_BUILTIN)
7095 /* These declarations are needed when related built-in is disabled and
7096  * genbuiltins.py won't automatically emit the declerations.
7097  */
7098 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_string(duk_hthread *thr);
7099 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_hthread *thr);
7100 #endif
7101 
7102 #endif  /* DUK_HOBJECT_H_INCLUDED */
7103 /* #include duk_hcompfunc.h */
7104 /*
7105  *  Heap compiled function (ECMAScript function) representation.
7106  *
7107  *  There is a single data buffer containing the ECMAScript function's
7108  *  bytecode, constants, and inner functions.
7109  */
7110 
7111 #if !defined(DUK_HCOMPFUNC_H_INCLUDED)
7112 #define DUK_HCOMPFUNC_H_INCLUDED
7113 
7114 /*
7115  *  Field accessor macros
7116  */
7117 
7118 /* XXX: casts could be improved, especially for GET/SET DATA */
7119 
7120 #if defined(DUK_USE_HEAPPTR16)
7121 #define DUK_HCOMPFUNC_GET_DATA(heap,h) \
7122 	((duk_hbuffer_fixed *) (void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->data16))
7123 #define DUK_HCOMPFUNC_SET_DATA(heap,h,v) do { \
7124 		(h)->data16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7125 	} while (0)
7126 #define DUK_HCOMPFUNC_GET_FUNCS(heap,h)  \
7127 	((duk_hobject **) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->funcs16)))
7128 #define DUK_HCOMPFUNC_SET_FUNCS(heap,h,v)  do { \
7129 		(h)->funcs16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7130 	} while (0)
7131 #define DUK_HCOMPFUNC_GET_BYTECODE(heap,h)  \
7132 	((duk_instr_t *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->bytecode16)))
7133 #define DUK_HCOMPFUNC_SET_BYTECODE(heap,h,v)  do { \
7134 		(h)->bytecode16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7135 	} while (0)
7136 #define DUK_HCOMPFUNC_GET_LEXENV(heap,h)  \
7137 	((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->lex_env16)))
7138 #define DUK_HCOMPFUNC_SET_LEXENV(heap,h,v)  do { \
7139 		(h)->lex_env16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7140 	} while (0)
7141 #define DUK_HCOMPFUNC_GET_VARENV(heap,h)  \
7142 	((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->var_env16)))
7143 #define DUK_HCOMPFUNC_SET_VARENV(heap,h,v)  do { \
7144 		(h)->var_env16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7145 	} while (0)
7146 #else
7147 #define DUK_HCOMPFUNC_GET_DATA(heap,h)  ((duk_hbuffer_fixed *) (void *) (h)->data)
7148 #define DUK_HCOMPFUNC_SET_DATA(heap,h,v) do { \
7149 		(h)->data = (duk_hbuffer *) (v); \
7150 	} while (0)
7151 #define DUK_HCOMPFUNC_GET_FUNCS(heap,h)  ((h)->funcs)
7152 #define DUK_HCOMPFUNC_SET_FUNCS(heap,h,v)  do { \
7153 		(h)->funcs = (v); \
7154 	} while (0)
7155 #define DUK_HCOMPFUNC_GET_BYTECODE(heap,h)  ((h)->bytecode)
7156 #define DUK_HCOMPFUNC_SET_BYTECODE(heap,h,v)  do { \
7157 		(h)->bytecode = (v); \
7158 	} while (0)
7159 #define DUK_HCOMPFUNC_GET_LEXENV(heap,h)  ((h)->lex_env)
7160 #define DUK_HCOMPFUNC_SET_LEXENV(heap,h,v)  do { \
7161 		(h)->lex_env = (v); \
7162 	} while (0)
7163 #define DUK_HCOMPFUNC_GET_VARENV(heap,h)  ((h)->var_env)
7164 #define DUK_HCOMPFUNC_SET_VARENV(heap,h,v)  do { \
7165 		(h)->var_env = (v); \
7166 	} while (0)
7167 #endif
7168 
7169 /*
7170  *  Accessor macros for function specific data areas
7171  */
7172 
7173 /* Note: assumes 'data' is always a fixed buffer */
7174 #define DUK_HCOMPFUNC_GET_BUFFER_BASE(heap,h)  \
7175 	DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPFUNC_GET_DATA((heap), (h)))
7176 
7177 #define DUK_HCOMPFUNC_GET_CONSTS_BASE(heap,h)  \
7178 	((duk_tval *) (void *) DUK_HCOMPFUNC_GET_BUFFER_BASE((heap), (h)))
7179 
7180 #define DUK_HCOMPFUNC_GET_FUNCS_BASE(heap,h)  \
7181 	DUK_HCOMPFUNC_GET_FUNCS((heap), (h))
7182 
7183 #define DUK_HCOMPFUNC_GET_CODE_BASE(heap,h)  \
7184 	DUK_HCOMPFUNC_GET_BYTECODE((heap), (h))
7185 
7186 #define DUK_HCOMPFUNC_GET_CONSTS_END(heap,h)  \
7187 	((duk_tval *) (void *) DUK_HCOMPFUNC_GET_FUNCS((heap), (h)))
7188 
7189 #define DUK_HCOMPFUNC_GET_FUNCS_END(heap,h)  \
7190 	((duk_hobject **) (void *) DUK_HCOMPFUNC_GET_BYTECODE((heap), (h)))
7191 
7192 /* XXX: double evaluation of DUK_HCOMPFUNC_GET_DATA() */
7193 #define DUK_HCOMPFUNC_GET_CODE_END(heap,h)  \
7194 	((duk_instr_t *) (void *) (DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPFUNC_GET_DATA((heap), (h))) + \
7195 	                DUK_HBUFFER_GET_SIZE((duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA((heap), h))))
7196 
7197 #define DUK_HCOMPFUNC_GET_CONSTS_SIZE(heap,h)  \
7198 	( \
7199 	 (duk_size_t) \
7200 	 ( \
7201 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_END((heap), (h))) - \
7202 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_BASE((heap), (h))) \
7203 	 ) \
7204 	)
7205 
7206 #define DUK_HCOMPFUNC_GET_FUNCS_SIZE(heap,h)  \
7207 	( \
7208 	 (duk_size_t) \
7209 	 ( \
7210 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_END((heap), (h))) - \
7211 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_BASE((heap), (h))) \
7212 	 ) \
7213 	)
7214 
7215 #define DUK_HCOMPFUNC_GET_CODE_SIZE(heap,h)  \
7216 	( \
7217 	 (duk_size_t) \
7218 	 ( \
7219 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_END((heap),(h))) - \
7220 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_BASE((heap),(h))) \
7221 	 ) \
7222 	)
7223 
7224 #define DUK_HCOMPFUNC_GET_CONSTS_COUNT(heap,h)  \
7225 	((duk_size_t) (DUK_HCOMPFUNC_GET_CONSTS_SIZE((heap), (h)) / sizeof(duk_tval)))
7226 
7227 #define DUK_HCOMPFUNC_GET_FUNCS_COUNT(heap,h)  \
7228 	((duk_size_t) (DUK_HCOMPFUNC_GET_FUNCS_SIZE((heap), (h)) / sizeof(duk_hobject *)))
7229 
7230 #define DUK_HCOMPFUNC_GET_CODE_COUNT(heap,h)  \
7231 	((duk_size_t) (DUK_HCOMPFUNC_GET_CODE_SIZE((heap), (h)) / sizeof(duk_instr_t)))
7232 
7233 /*
7234  *  Validity assert
7235  */
7236 
7237 #if defined(DUK_USE_ASSERTIONS)
7238 DUK_INTERNAL_DECL void duk_hcompfunc_assert_valid(duk_hcompfunc *h);
7239 #define DUK_HCOMPFUNC_ASSERT_VALID(h)  do { duk_hcompfunc_assert_valid((h)); } while (0)
7240 #else
7241 #define DUK_HCOMPFUNC_ASSERT_VALID(h)  do {} while (0)
7242 #endif
7243 
7244 /*
7245  *  Main struct
7246  */
7247 
7248 struct duk_hcompfunc {
7249 	/* shared object part */
7250 	duk_hobject obj;
7251 
7252 	/*
7253 	 *  Pointers to function data area for faster access.  Function
7254 	 *  data is a buffer shared between all closures of the same
7255 	 *  "template" function.  The data buffer is always fixed (non-
7256 	 *  dynamic, hence stable), with a layout as follows:
7257 	 *
7258 	 *    constants (duk_tval)
7259 	 *    inner functions (duk_hobject *)
7260 	 *    bytecode (duk_instr_t)
7261 	 *
7262 	 *  Note: bytecode end address can be computed from 'data' buffer
7263 	 *  size.  It is not strictly necessary functionally, assuming
7264 	 *  bytecode never jumps outside its allocated area.  However,
7265 	 *  it's a safety/robustness feature for avoiding the chance of
7266 	 *  executing random data as bytecode due to a compiler error.
7267 	 *
7268 	 *  Note: values in the data buffer must be incref'd (they will
7269 	 *  be decref'd on release) for every compiledfunction referring
7270 	 *  to the 'data' element.
7271 	 */
7272 
7273 	/* Data area, fixed allocation, stable data ptrs. */
7274 #if defined(DUK_USE_HEAPPTR16)
7275 	duk_uint16_t data16;
7276 #else
7277 	duk_hbuffer *data;
7278 #endif
7279 
7280 	/* No need for constants pointer (= same as data).
7281 	 *
7282 	 * When using 16-bit packing alignment to 4 is nice.  'funcs' will be
7283 	 * 4-byte aligned because 'constants' are duk_tvals.  For now the
7284 	 * inner function pointers are not compressed, so that 'bytecode' will
7285 	 * also be 4-byte aligned.
7286 	 */
7287 #if defined(DUK_USE_HEAPPTR16)
7288 	duk_uint16_t funcs16;
7289 	duk_uint16_t bytecode16;
7290 #else
7291 	duk_hobject **funcs;
7292 	duk_instr_t *bytecode;
7293 #endif
7294 
7295 	/* Lexenv: lexical environment of closure, NULL for templates.
7296 	 * Varenv: variable environment of closure, NULL for templates.
7297 	 */
7298 #if defined(DUK_USE_HEAPPTR16)
7299 	duk_uint16_t lex_env16;
7300 	duk_uint16_t var_env16;
7301 #else
7302 	duk_hobject *lex_env;
7303 	duk_hobject *var_env;
7304 #endif
7305 
7306 	/*
7307 	 *  'nregs' registers are allocated on function entry, at most 'nargs'
7308 	 *  are initialized to arguments, and the rest to undefined.  Arguments
7309 	 *  above 'nregs' are not mapped to registers.  All registers in the
7310 	 *  active stack range must be initialized because they are GC reachable.
7311 	 *  'nargs' is needed so that if the function is given more than 'nargs'
7312 	 *  arguments, the additional arguments do not 'clobber' registers
7313 	 *  beyond 'nregs' which must be consistently initialized to undefined.
7314 	 *
7315 	 *  Usually there is no need to know which registers are mapped to
7316 	 *  local variables.  Registers may be allocated to variable in any
7317 	 *  way (even including gaps).  However, a register-variable mapping
7318 	 *  must be the same for the duration of the function execution and
7319 	 *  the register cannot be used for anything else.
7320 	 *
7321 	 *  When looking up variables by name, the '_Varmap' map is used.
7322 	 *  When an activation closes, registers mapped to arguments are
7323 	 *  copied into the environment record based on the same map.  The
7324 	 *  reverse map (from register to variable) is not currently needed
7325 	 *  at run time, except for debugging, so it is not maintained.
7326 	 */
7327 
7328 	duk_uint16_t nregs;                /* regs to allocate */
7329 	duk_uint16_t nargs;                /* number of arguments allocated to regs */
7330 
7331 	/*
7332 	 *  Additional control information is placed into the object itself
7333 	 *  as internal properties to avoid unnecessary fields for the
7334 	 *  majority of functions.  The compiler tries to omit internal
7335 	 *  control fields when possible.
7336 	 *
7337 	 *  Function templates:
7338 	 *
7339 	 *    {
7340 	 *      name: "func",    // declaration, named function expressions
7341 	 *      fileName: <debug info for creating nice errors>
7342 	 *      _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
7343 	 *      _Formals: [ "arg1", "arg2" ],
7344 	 *      _Source: "function func(arg1, arg2) { ... }",
7345 	 *      _Pc2line: <debug info for pc-to-line mapping>,
7346 	 *    }
7347 	 *
7348 	 *  Function instances:
7349 	 *
7350 	 *    {
7351 	 *      length: 2,
7352 	 *      prototype: { constructor: <func> },
7353 	 *      caller: <thrower>,
7354 	 *      arguments: <thrower>,
7355 	 *      name: "func",    // declaration, named function expressions
7356 	 *      fileName: <debug info for creating nice errors>
7357 	 *      _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
7358 	 *      _Formals: [ "arg1", "arg2" ],
7359 	 *      _Source: "function func(arg1, arg2) { ... }",
7360 	 *      _Pc2line: <debug info for pc-to-line mapping>,
7361 	 *    }
7362 	 *
7363 	 *  More detailed description of these properties can be found
7364 	 *  in the documentation.
7365 	 */
7366 
7367 #if defined(DUK_USE_DEBUGGER_SUPPORT)
7368 	/* Line number range for function.  Needed during debugging to
7369 	 * determine active breakpoints.
7370 	 */
7371 	duk_uint32_t start_line;
7372 	duk_uint32_t end_line;
7373 #endif
7374 };
7375 
7376 #endif  /* DUK_HCOMPFUNC_H_INCLUDED */
7377 /* #include duk_hnatfunc.h */
7378 /*
7379  *  Heap native function representation.
7380  */
7381 
7382 #if !defined(DUK_HNATFUNC_H_INCLUDED)
7383 #define DUK_HNATFUNC_H_INCLUDED
7384 
7385 #if defined(DUK_USE_ASSERTIONS)
7386 DUK_INTERNAL_DECL void duk_hnatfunc_assert_valid(duk_hnatfunc *h);
7387 #define DUK_HNATFUNC_ASSERT_VALID(h)  do { duk_hnatfunc_assert_valid((h)); } while (0)
7388 #else
7389 #define DUK_HNATFUNC_ASSERT_VALID(h)  do {} while (0)
7390 #endif
7391 
7392 #define DUK_HNATFUNC_NARGS_VARARGS  ((duk_int16_t) -1)
7393 #define DUK_HNATFUNC_NARGS_MAX      ((duk_int16_t) 0x7fff)
7394 
7395 struct duk_hnatfunc {
7396 	/* shared object part */
7397 	duk_hobject obj;
7398 
7399 	duk_c_function func;
7400 	duk_int16_t nargs;
7401 	duk_int16_t magic;
7402 
7403 	/* The 'magic' field allows an opaque 16-bit field to be accessed by the
7404 	 * Duktape/C function.  This allows, for instance, the same native function
7405 	 * to be used for a set of very similar functions, with the 'magic' field
7406 	 * providing the necessary non-argument flags / values to guide the behavior
7407 	 * of the native function.  The value is signed on purpose: it is easier to
7408 	 * convert a signed value to unsigned (simply AND with 0xffff) than vice
7409 	 * versa.
7410 	 *
7411 	 * Note: cannot place nargs/magic into the heaphdr flags, because
7412 	 * duk_hobject takes almost all flags already.
7413 	 */
7414 };
7415 
7416 #endif  /* DUK_HNATFUNC_H_INCLUDED */
7417 /* #include duk_hboundfunc.h */
7418 /*
7419  *  Bound function representation.
7420  */
7421 
7422 #if !defined(DUK_HBOUNDFUNC_H_INCLUDED)
7423 #define DUK_HBOUNDFUNC_H_INCLUDED
7424 
7425 /* Artificial limit for args length.  Ensures arithmetic won't overflow
7426  * 32 bits when combining bound functions.
7427  */
7428 #define DUK_HBOUNDFUNC_MAX_ARGS 0x20000000UL
7429 
7430 #if defined(DUK_USE_ASSERTIONS)
7431 DUK_INTERNAL_DECL void duk_hboundfunc_assert_valid(duk_hboundfunc *h);
7432 #define DUK_HBOUNDFUNC_ASSERT_VALID(h)  do { duk_hboundfunc_assert_valid((h)); } while (0)
7433 #else
7434 #define DUK_HBOUNDFUNC_ASSERT_VALID(h)  do {} while (0)
7435 #endif
7436 
7437 struct duk_hboundfunc {
7438 	/* Shared object part. */
7439 	duk_hobject obj;
7440 
7441 	/* Final target function, stored as duk_tval so that lightfunc can be
7442 	 * represented too.
7443 	 */
7444 	duk_tval target;
7445 
7446 	/* This binding. */
7447 	duk_tval this_binding;
7448 
7449 	/* Arguments to prepend. */
7450 	duk_tval *args;  /* Separate allocation. */
7451 	duk_idx_t nargs;
7452 };
7453 
7454 #endif  /* DUK_HBOUNDFUNC_H_INCLUDED */
7455 /* #include duk_hbufobj.h */
7456 /*
7457  *  Heap Buffer object representation.  Used for all Buffer variants.
7458  */
7459 
7460 #if !defined(DUK_HBUFOBJ_H_INCLUDED)
7461 #define DUK_HBUFOBJ_H_INCLUDED
7462 
7463 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
7464 
7465 /* All element accessors are host endian now (driven by TypedArray spec). */
7466 #define DUK_HBUFOBJ_ELEM_UINT8           0
7467 #define DUK_HBUFOBJ_ELEM_UINT8CLAMPED    1
7468 #define DUK_HBUFOBJ_ELEM_INT8            2
7469 #define DUK_HBUFOBJ_ELEM_UINT16          3
7470 #define DUK_HBUFOBJ_ELEM_INT16           4
7471 #define DUK_HBUFOBJ_ELEM_UINT32          5
7472 #define DUK_HBUFOBJ_ELEM_INT32           6
7473 #define DUK_HBUFOBJ_ELEM_FLOAT32         7
7474 #define DUK_HBUFOBJ_ELEM_FLOAT64         8
7475 #define DUK_HBUFOBJ_ELEM_MAX             8
7476 
7477 #if defined(DUK_USE_ASSERTIONS)
7478 DUK_INTERNAL_DECL void duk_hbufobj_assert_valid(duk_hbufobj *h);
7479 #define DUK_HBUFOBJ_ASSERT_VALID(h)  do { duk_hbufobj_assert_valid((h)); } while (0)
7480 #else
7481 #define DUK_HBUFOBJ_ASSERT_VALID(h)  do {} while (0)
7482 #endif
7483 
7484 /* Get the current data pointer (caller must ensure buf != NULL) as a
7485  * duk_uint8_t ptr.  Note that the result may be NULL if the underlying
7486  * buffer has zero size and is not a fixed buffer.
7487  */
7488 #define DUK_HBUFOBJ_GET_SLICE_BASE(heap,h) \
7489 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
7490 	(((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR((heap), (h)->buf)) + (h)->offset))
7491 
7492 /* True if slice is full, i.e. offset is zero and length covers the entire
7493  * buffer.  This status may change independently of the duk_hbufobj if
7494  * the underlying buffer is dynamic and changes without the hbufobj
7495  * being changed.
7496  */
7497 #define DUK_HBUFOBJ_FULL_SLICE(h) \
7498 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
7499 	((h)->offset == 0 && (h)->length == DUK_HBUFFER_GET_SIZE((h)->buf)))
7500 
7501 /* Validate that the whole slice [0,length[ is contained in the underlying
7502  * buffer.  Caller must ensure 'buf' != NULL.
7503  */
7504 #define DUK_HBUFOBJ_VALID_SLICE(h) \
7505 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
7506 	((h)->offset + (h)->length <= DUK_HBUFFER_GET_SIZE((h)->buf)))
7507 
7508 /* Validate byte read/write for virtual 'offset', i.e. check that the
7509  * offset, taking into account h->offset, is within the underlying
7510  * buffer size.  This is a safety check which is needed to ensure
7511  * that even a misconfigured duk_hbufobj never causes memory unsafe
7512  * behavior (e.g. if an underlying dynamic buffer changes after being
7513  * setup).  Caller must ensure 'buf' != NULL.
7514  */
7515 #define DUK_HBUFOBJ_VALID_BYTEOFFSET_INCL(h,off) \
7516 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
7517 	((h)->offset + (off) < DUK_HBUFFER_GET_SIZE((h)->buf)))
7518 
7519 #define DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h,off) \
7520 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
7521 	((h)->offset + (off) <= DUK_HBUFFER_GET_SIZE((h)->buf)))
7522 
7523 /* Clamp an input byte length (already assumed to be within the nominal
7524  * duk_hbufobj 'length') to the current dynamic buffer limits to yield
7525  * a byte length limit that's safe for memory accesses.  This value can
7526  * be invalidated by any side effect because it may trigger a user
7527  * callback that resizes the underlying buffer.
7528  */
7529 #define DUK_HBUFOBJ_CLAMP_BYTELENGTH(h,len) \
7530 	(DUK_ASSERT_EXPR((h) != NULL), \
7531 	duk_hbufobj_clamp_bytelength((h), (len)))
7532 
7533 /* Typed arrays have virtual indices, ArrayBuffer and DataView do not. */
7534 #define DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h)  ((h)->is_typedarray)
7535 
7536 struct duk_hbufobj {
7537 	/* Shared object part. */
7538 	duk_hobject obj;
7539 
7540 	/* Underlying buffer (refcounted), may be NULL. */
7541 	duk_hbuffer *buf;
7542 
7543 	/* .buffer reference to an ArrayBuffer, may be NULL. */
7544 	duk_hobject *buf_prop;
7545 
7546 	/* Slice and accessor information.
7547 	 *
7548 	 * Because the underlying buffer may be dynamic, these may be
7549 	 * invalidated by the buffer being modified so that both offset
7550 	 * and length should be validated before every access.  Behavior
7551 	 * when the underlying buffer has changed doesn't need to be clean:
7552 	 * virtual 'length' doesn't need to be affected, reads can return
7553 	 * zero/NaN, and writes can be ignored.
7554 	 *
7555 	 * Note that a data pointer cannot be precomputed because 'buf' may
7556 	 * be dynamic and its pointer unstable.
7557 	 */
7558 
7559 	duk_uint_t offset;       /* byte offset to buf */
7560 	duk_uint_t length;       /* byte index limit for element access, exclusive */
7561 	duk_uint8_t shift;       /* element size shift:
7562 	                          *   0 = u8/i8
7563 	                          *   1 = u16/i16
7564 	                          *   2 = u32/i32/float
7565 	                          *   3 = double
7566 	                          */
7567 	duk_uint8_t elem_type;   /* element type */
7568 	duk_uint8_t is_typedarray;
7569 };
7570 
7571 DUK_INTERNAL_DECL duk_uint_t duk_hbufobj_clamp_bytelength(duk_hbufobj *h_bufobj, duk_uint_t len);
7572 DUK_INTERNAL_DECL void duk_hbufobj_push_uint8array_from_plain(duk_hthread *thr, duk_hbuffer *h_buf);
7573 DUK_INTERNAL_DECL void duk_hbufobj_push_validated_read(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size);
7574 DUK_INTERNAL_DECL void duk_hbufobj_validated_write(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size);
7575 DUK_INTERNAL_DECL void duk_hbufobj_promote_plain(duk_hthread *thr, duk_idx_t idx);
7576 
7577 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
7578 
7579 /* nothing */
7580 
7581 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
7582 #endif  /* DUK_HBUFOBJ_H_INCLUDED */
7583 /* #include duk_hthread.h */
7584 /*
7585  *  Heap thread object representation.
7586  *
7587  *  duk_hthread is also the 'context' for public API functions via a
7588  *  different typedef.  Most API calls operate on the topmost frame
7589  *  of the value stack only.
7590  */
7591 
7592 #if !defined(DUK_HTHREAD_H_INCLUDED)
7593 #define DUK_HTHREAD_H_INCLUDED
7594 
7595 /*
7596  *  Stack constants
7597  */
7598 
7599 /* Initial valstack size, roughly 0.7kiB. */
7600 #define DUK_VALSTACK_INITIAL_SIZE       96U
7601 
7602 /* Internal extra elements assumed on function entry, always added to
7603  * user-defined 'extra' for e.g. the duk_check_stack() call.
7604  */
7605 #define DUK_VALSTACK_INTERNAL_EXTRA     32U
7606 
7607 /* Number of elements guaranteed to be user accessible (in addition to call
7608  * arguments) on Duktape/C function entry.  This is the major public API
7609  * commitment.
7610  */
7611 #define DUK_VALSTACK_API_ENTRY_MINIMUM  DUK_API_ENTRY_STACK
7612 
7613 /*
7614  *  Activation defines
7615  */
7616 
7617 #define DUK_ACT_FLAG_STRICT             (1U << 0)  /* function executes in strict mode */
7618 #define DUK_ACT_FLAG_TAILCALLED         (1U << 1)  /* activation has tail called one or more times */
7619 #define DUK_ACT_FLAG_CONSTRUCT          (1U << 2)  /* function executes as a constructor (called via "new") */
7620 #define DUK_ACT_FLAG_PREVENT_YIELD      (1U << 3)  /* activation prevents yield (native call or "new") */
7621 #define DUK_ACT_FLAG_DIRECT_EVAL        (1U << 4)  /* activation is a direct eval call */
7622 #define DUK_ACT_FLAG_CONSTRUCT_PROXY    (1U << 5)  /* activation is for Proxy 'construct' call, special return value handling */
7623 #define DUK_ACT_FLAG_BREAKPOINT_ACTIVE  (1U << 6)  /* activation has active breakpoint(s) */
7624 
7625 #define DUK_ACT_GET_FUNC(act)           ((act)->func)
7626 
7627 /*
7628  *  Flags for __FILE__ / __LINE__ registered into tracedata
7629  */
7630 
7631 #define DUK_TB_FLAG_NOBLAME_FILELINE    (1U << 0)  /* don't report __FILE__ / __LINE__ as fileName/lineNumber */
7632 
7633 /*
7634  *  Catcher defines
7635  */
7636 
7637 /* XXX: remove catcher type entirely */
7638 
7639 /* flags field: LLLLLLFT, L = label (24 bits), F = flags (4 bits), T = type (4 bits) */
7640 #define DUK_CAT_TYPE_MASK            0x0000000fUL
7641 #define DUK_CAT_TYPE_BITS            4
7642 #define DUK_CAT_LABEL_MASK           0xffffff00UL
7643 #define DUK_CAT_LABEL_BITS           24
7644 #define DUK_CAT_LABEL_SHIFT          8
7645 
7646 #define DUK_CAT_FLAG_CATCH_ENABLED          (1U << 4)   /* catch part will catch */
7647 #define DUK_CAT_FLAG_FINALLY_ENABLED        (1U << 5)   /* finally part will catch */
7648 #define DUK_CAT_FLAG_CATCH_BINDING_ENABLED  (1U << 6)   /* request to create catch binding */
7649 #define DUK_CAT_FLAG_LEXENV_ACTIVE          (1U << 7)   /* catch or with binding is currently active */
7650 
7651 #define DUK_CAT_TYPE_UNKNOWN         0
7652 #define DUK_CAT_TYPE_TCF             1
7653 #define DUK_CAT_TYPE_LABEL           2
7654 
7655 #define DUK_CAT_GET_TYPE(c)          ((c)->flags & DUK_CAT_TYPE_MASK)
7656 #define DUK_CAT_GET_LABEL(c)         (((c)->flags & DUK_CAT_LABEL_MASK) >> DUK_CAT_LABEL_SHIFT)
7657 
7658 #define DUK_CAT_HAS_CATCH_ENABLED(c)           ((c)->flags & DUK_CAT_FLAG_CATCH_ENABLED)
7659 #define DUK_CAT_HAS_FINALLY_ENABLED(c)         ((c)->flags & DUK_CAT_FLAG_FINALLY_ENABLED)
7660 #define DUK_CAT_HAS_CATCH_BINDING_ENABLED(c)   ((c)->flags & DUK_CAT_FLAG_CATCH_BINDING_ENABLED)
7661 #define DUK_CAT_HAS_LEXENV_ACTIVE(c)           ((c)->flags & DUK_CAT_FLAG_LEXENV_ACTIVE)
7662 
7663 #define DUK_CAT_SET_CATCH_ENABLED(c)    do { \
7664 		(c)->flags |= DUK_CAT_FLAG_CATCH_ENABLED; \
7665 	} while (0)
7666 #define DUK_CAT_SET_FINALLY_ENABLED(c)  do { \
7667 		(c)->flags |= DUK_CAT_FLAG_FINALLY_ENABLED; \
7668 	} while (0)
7669 #define DUK_CAT_SET_CATCH_BINDING_ENABLED(c)    do { \
7670 		(c)->flags |= DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \
7671 	} while (0)
7672 #define DUK_CAT_SET_LEXENV_ACTIVE(c)    do { \
7673 		(c)->flags |= DUK_CAT_FLAG_LEXENV_ACTIVE; \
7674 	} while (0)
7675 
7676 #define DUK_CAT_CLEAR_CATCH_ENABLED(c)    do { \
7677 		(c)->flags &= ~DUK_CAT_FLAG_CATCH_ENABLED; \
7678 	} while (0)
7679 #define DUK_CAT_CLEAR_FINALLY_ENABLED(c)  do { \
7680 		(c)->flags &= ~DUK_CAT_FLAG_FINALLY_ENABLED; \
7681 	} while (0)
7682 #define DUK_CAT_CLEAR_CATCH_BINDING_ENABLED(c)    do { \
7683 		(c)->flags &= ~DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \
7684 	} while (0)
7685 #define DUK_CAT_CLEAR_LEXENV_ACTIVE(c)    do { \
7686 		(c)->flags &= ~DUK_CAT_FLAG_LEXENV_ACTIVE; \
7687 	} while (0)
7688 
7689 /*
7690  *  Thread defines
7691  */
7692 
7693 #if defined(DUK_USE_ROM_STRINGS)
7694 #define DUK_HTHREAD_GET_STRING(thr,idx) \
7695 	((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))
7696 #else  /* DUK_USE_ROM_STRINGS */
7697 #if defined(DUK_USE_HEAPPTR16)
7698 #define DUK_HTHREAD_GET_STRING(thr,idx) \
7699 	((duk_hstring *) DUK_USE_HEAPPTR_DEC16((thr)->heap->heap_udata, (thr)->strs16[(idx)]))
7700 #else
7701 #define DUK_HTHREAD_GET_STRING(thr,idx) \
7702 	((thr)->strs[(idx)])
7703 #endif
7704 #endif  /* DUK_USE_ROM_STRINGS */
7705 
7706 /* values for the state field */
7707 #define DUK_HTHREAD_STATE_INACTIVE     1   /* thread not currently running */
7708 #define DUK_HTHREAD_STATE_RUNNING      2   /* thread currently running (only one at a time) */
7709 #define DUK_HTHREAD_STATE_RESUMED      3   /* thread resumed another thread (active but not running) */
7710 #define DUK_HTHREAD_STATE_YIELDED      4   /* thread has yielded */
7711 #define DUK_HTHREAD_STATE_TERMINATED   5   /* thread has terminated */
7712 
7713 /* Executor interrupt default interval when nothing else requires a
7714  * smaller value.  The default interval must be small enough to allow
7715  * for reasonable execution timeout checking but large enough to keep
7716  * impact on execution performance low.
7717  */
7718 #if defined(DUK_USE_INTERRUPT_COUNTER)
7719 #define DUK_HTHREAD_INTCTR_DEFAULT     (256L * 1024L)
7720 #endif
7721 
7722 /*
7723  *  Assert context is valid: non-NULL pointer, fields look sane.
7724  *
7725  *  This is used by public API call entrypoints to catch invalid 'ctx' pointers
7726  *  as early as possible; invalid 'ctx' pointers cause very odd and difficult to
7727  *  diagnose behavior so it's worth checking even when the check is not 100%.
7728  */
7729 
7730 #if defined(DUK_USE_ASSERTIONS)
7731 /* Assertions for internals. */
7732 DUK_INTERNAL_DECL void duk_hthread_assert_valid(duk_hthread *thr);
7733 #define DUK_HTHREAD_ASSERT_VALID(thr)  do { duk_hthread_assert_valid((thr)); } while (0)
7734 
7735 /* Assertions for public API calls; a bit stronger. */
7736 DUK_INTERNAL_DECL void duk_ctx_assert_valid(duk_hthread *thr);
7737 #define DUK_CTX_ASSERT_VALID(thr)  do { duk_ctx_assert_valid((thr)); } while (0)
7738 #else
7739 #define DUK_HTHREAD_ASSERT_VALID(thr)  do {} while (0)
7740 #define DUK_CTX_ASSERT_VALID(thr)  do {} while (0)
7741 #endif
7742 
7743 /* Assertions for API call entry specifically.  Checks 'ctx' but also may
7744  * check internal state (e.g. not in a debugger transport callback).
7745  */
7746 #define DUK_ASSERT_API_ENTRY(thr) do { \
7747 		DUK_CTX_ASSERT_VALID((thr)); \
7748 		DUK_ASSERT((thr)->heap != NULL); \
7749 		DUK_ASSERT((thr)->heap->dbg_calling_transport == 0); \
7750 	} while (0)
7751 
7752 /*
7753  *  Assertion helpers.
7754  */
7755 
7756 #define DUK_ASSERT_STRIDX_VALID(val) \
7757 	DUK_ASSERT((duk_uint_t) (val) < DUK_HEAP_NUM_STRINGS)
7758 
7759 #define DUK_ASSERT_BIDX_VALID(val) \
7760 	DUK_ASSERT((duk_uint_t) (val) < DUK_NUM_BUILTINS)
7761 
7762 /*
7763  *  Misc
7764  */
7765 
7766 /* Fast access to 'this' binding.  Assumes there's a call in progress. */
7767 #define DUK_HTHREAD_THIS_PTR(thr) \
7768 	(DUK_ASSERT_EXPR((thr) != NULL), \
7769 	 DUK_ASSERT_EXPR((thr)->valstack_bottom > (thr)->valstack), \
7770 	 (thr)->valstack_bottom - 1)
7771 
7772 /*
7773  *  Struct defines
7774  */
7775 
7776 /* Fields are ordered for alignment/packing. */
7777 struct duk_activation {
7778 	duk_tval tv_func;       /* borrowed: full duk_tval for function being executed; for lightfuncs */
7779 	duk_hobject *func;      /* borrowed: function being executed; for bound function calls, this is the final, real function, NULL for lightfuncs */
7780 	duk_activation *parent; /* previous (parent) activation (or NULL if none) */
7781 	duk_hobject *var_env;   /* current variable environment (may be NULL if delayed) */
7782 	duk_hobject *lex_env;   /* current lexical environment (may be NULL if delayed) */
7783 	duk_catcher *cat;       /* current catcher (or NULL) */
7784 
7785 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
7786 	/* Previous value of 'func' caller, restored when unwound.  Only in use
7787 	 * when 'func' is non-strict.
7788 	 */
7789 	duk_hobject *prev_caller;
7790 #endif
7791 
7792 	duk_instr_t *curr_pc;   /* next instruction to execute (points to 'func' bytecode, stable pointer), NULL for native calls */
7793 
7794 	/* bottom_byteoff and retval_byteoff are only used for book-keeping
7795 	 * of ECMAScript-initiated calls, to allow returning to an ECMAScript
7796 	 * function properly.
7797 	 */
7798 
7799 	/* Bottom of valstack for this activation, used to reset
7800 	 * valstack_bottom on return; offset is absolute.  There's
7801 	 * no need to track 'top' because native call handling deals
7802 	 * with that using locals, and for ECMAScript returns 'nregs'
7803 	 * indicates the necessary top.
7804 	 */
7805 	duk_size_t bottom_byteoff;
7806 
7807 	/* Return value when returning to this activation (points to caller
7808 	 * reg, not callee reg); offset is absolute (only set if activation is
7809 	 * not topmost).
7810 	 *
7811 	 * Note: bottom_byteoff is always set, while retval_byteoff is only
7812 	 * applicable for activations below the topmost one.  Currently
7813 	 * retval_byteoff for the topmost activation is considered garbage
7814 	 * (and it not initialized on entry or cleared on return; may contain
7815 	 * previous or garbage values).
7816 	 */
7817 	duk_size_t retval_byteoff;
7818 
7819 	/* Current 'this' binding is the value just below bottom.
7820 	 * Previously, 'this' binding was handled with an index to the
7821 	 * (calling) valstack.  This works for everything except tail
7822 	 * calls, which must not "accumulate" valstack temps.
7823 	 */
7824 
7825 	/* Value stack reserve (valstack_end) byte offset to be restored
7826 	 * when returning to this activation.  Only used by the bytecode
7827 	 * executor.
7828 	 */
7829 	duk_size_t reserve_byteoff;
7830 
7831 #if defined(DUK_USE_DEBUGGER_SUPPORT)
7832 	duk_uint32_t prev_line; /* needed for stepping */
7833 #endif
7834 
7835 	duk_small_uint_t flags;
7836 };
7837 
7838 struct duk_catcher {
7839 	duk_catcher *parent;            /* previous (parent) catcher (or NULL if none) */
7840 	duk_hstring *h_varname;         /* borrowed reference to catch variable name (or NULL if none) */
7841 	                                /* (reference is valid as long activation exists) */
7842 	duk_instr_t *pc_base;           /* resume execution from pc_base or pc_base+1 (points to 'func' bytecode, stable pointer) */
7843 	duk_size_t idx_base;            /* idx_base and idx_base+1 get completion value and type */
7844 	duk_uint32_t flags;             /* type and control flags, label number */
7845 	/* XXX: could pack 'flags' and 'idx_base' to same value in practice,
7846 	 * on 32-bit targets this would make duk_catcher 16 bytes.
7847 	 */
7848 };
7849 
7850 struct duk_hthread {
7851 	/* Shared object part */
7852 	duk_hobject obj;
7853 
7854 	/* Pointer to bytecode executor's 'curr_pc' variable.  Used to copy
7855 	 * the current PC back into the topmost activation when activation
7856 	 * state is about to change (or "syncing" is otherwise needed).  This
7857 	 * is rather awkward but important for performance, see execution.rst.
7858 	 */
7859 	duk_instr_t **ptr_curr_pc;
7860 
7861 	/* Backpointers. */
7862 	duk_heap *heap;
7863 
7864 	/* Current strictness flag: affects API calls. */
7865 	duk_uint8_t strict;
7866 
7867 	/* Thread state. */
7868 	duk_uint8_t state;
7869 	duk_uint8_t unused1;
7870 	duk_uint8_t unused2;
7871 
7872 	/* XXX: Valstack and callstack are currently assumed to have non-NULL
7873 	 * pointers.  Relaxing this would not lead to big benefits (except
7874 	 * perhaps for terminated threads).
7875 	 */
7876 
7877 	/* Value stack: these are expressed as pointers for faster stack
7878 	 * manipulation.  [valstack,valstack_top[ is GC-reachable,
7879 	 * [valstack_top,valstack_alloc_end[ is not GC-reachable but kept
7880 	 * initialized as 'undefined'.  [valstack,valstack_end[ is the
7881 	 * guaranteed/reserved space and the valstack cannot be resized to
7882 	 * a smaller size.  [valstack_end,valstack_alloc_end[ is currently
7883 	 * allocated slack that can be used to grow the current guaranteed
7884 	 * space but may be shrunk away without notice.
7885 	 *
7886 	 *
7887 	 * <----------------------- guaranteed --->
7888 	 *                                        <---- slack --->
7889 	 *               <--- frame --->
7890 	 * .-------------+=============+----------+--------------.
7891 	 * |xxxxxxxxxxxxx|yyyyyyyyyyyyy|uuuuuuuuuu|uuuuuuuuuuuuuu|
7892 	 * `-------------+=============+----------+--------------'
7893 	 *
7894 	 * ^             ^             ^          ^              ^
7895 	 * |             |             |          |              |
7896 	 * valstack      bottom        top        end            alloc_end
7897 	 *
7898 	 *     xxx = arbitrary values, below current frame
7899 	 *     yyy = arbitrary values, inside current frame
7900 	 *     uuu = outside active value stack, initialized to 'undefined'
7901 	 */
7902 	duk_tval *valstack;                     /* start of valstack allocation */
7903 	duk_tval *valstack_end;                 /* end of valstack reservation/guarantee (exclusive) */
7904 	duk_tval *valstack_alloc_end;           /* end of valstack allocation */
7905 	duk_tval *valstack_bottom;              /* bottom of current frame */
7906 	duk_tval *valstack_top;                 /* top of current frame (exclusive) */
7907 
7908 	/* Call stack, represented as a linked list starting from the current
7909 	 * activation (or NULL if nothing is active).
7910 	 */
7911 	duk_activation *callstack_curr;         /* current activation (or NULL if none) */
7912 	duk_size_t callstack_top;               /* number of activation records in callstack (0 if none) */
7913 	duk_size_t callstack_preventcount;      /* number of activation records in callstack preventing a yield */
7914 
7915 	/* Yield/resume book-keeping. */
7916 	duk_hthread *resumer;                   /* who resumed us (if any) */
7917 
7918 	/* Current compiler state (if any), used for augmenting SyntaxErrors. */
7919 	duk_compiler_ctx *compile_ctx;
7920 
7921 #if defined(DUK_USE_INTERRUPT_COUNTER)
7922 	/* Interrupt counter for triggering a slow path check for execution
7923 	 * timeout, debugger interaction such as breakpoints, etc.  The value
7924 	 * is valid for the current running thread, and both the init and
7925 	 * counter values are copied whenever a thread switch occurs.  It's
7926 	 * important for the counter to be conveniently accessible for the
7927 	 * bytecode executor inner loop for performance reasons.
7928 	 */
7929 	duk_int_t interrupt_counter;    /* countdown state */
7930 	duk_int_t interrupt_init;       /* start value for current countdown */
7931 #endif
7932 
7933 	/* Builtin-objects; may or may not be shared with other threads,
7934 	 * threads existing in different "compartments" will have different
7935 	 * built-ins.  Must be stored on a per-thread basis because there
7936 	 * is no intermediate structure for a thread group / compartment.
7937 	 * This takes quite a lot of space, currently 43x4 = 172 bytes on
7938 	 * 32-bit platforms.
7939 	 *
7940 	 * In some cases the builtins array could be ROM based, but it's
7941 	 * sometimes edited (e.g. for sandboxing) so it's better to keep
7942 	 * this array in RAM.
7943 	 */
7944 	duk_hobject *builtins[DUK_NUM_BUILTINS];
7945 
7946 	/* Convenience copies from heap/vm for faster access. */
7947 #if defined(DUK_USE_ROM_STRINGS)
7948 	/* No field needed when strings are in ROM. */
7949 #else
7950 #if defined(DUK_USE_HEAPPTR16)
7951 	duk_uint16_t *strs16;
7952 #else
7953 	duk_hstring **strs;
7954 #endif
7955 #endif
7956 };
7957 
7958 /*
7959  *  Prototypes
7960  */
7961 
7962 DUK_INTERNAL_DECL void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to);
7963 DUK_INTERNAL_DECL void duk_hthread_create_builtin_objects(duk_hthread *thr);
7964 DUK_INTERNAL_DECL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr);
7965 DUK_INTERNAL_DECL void duk_hthread_terminate(duk_hthread *thr);
7966 
7967 DUK_INTERNAL_DECL duk_activation *duk_hthread_activation_alloc(duk_hthread *thr);
7968 DUK_INTERNAL_DECL void duk_hthread_activation_free(duk_hthread *thr, duk_activation *act);
7969 DUK_INTERNAL_DECL void duk_hthread_activation_unwind_norz(duk_hthread *thr);
7970 DUK_INTERNAL_DECL void duk_hthread_activation_unwind_reuse_norz(duk_hthread *thr);
7971 DUK_INTERNAL_DECL duk_activation *duk_hthread_get_activation_for_level(duk_hthread *thr, duk_int_t level);
7972 
7973 DUK_INTERNAL_DECL duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr);
7974 DUK_INTERNAL_DECL void duk_hthread_catcher_free(duk_hthread *thr, duk_catcher *cat);
7975 DUK_INTERNAL_DECL void duk_hthread_catcher_unwind_norz(duk_hthread *thr, duk_activation *act);
7976 DUK_INTERNAL_DECL void duk_hthread_catcher_unwind_nolexenv_norz(duk_hthread *thr, duk_activation *act);
7977 
7978 #if defined(DUK_USE_FINALIZER_TORTURE)
7979 DUK_INTERNAL_DECL void duk_hthread_valstack_torture_realloc(duk_hthread *thr);
7980 #endif
7981 
7982 DUK_INTERNAL_DECL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud);  /* indirect allocs */
7983 
7984 #if defined(DUK_USE_DEBUGGER_SUPPORT)
7985 DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act);
7986 #endif
7987 DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_prev_pc(duk_hthread *thr, duk_activation *act);
7988 DUK_INTERNAL_DECL void duk_hthread_sync_currpc(duk_hthread *thr);
7989 DUK_INTERNAL_DECL void duk_hthread_sync_and_null_currpc(duk_hthread *thr);
7990 
7991 #endif  /* DUK_HTHREAD_H_INCLUDED */
7992 /* #include duk_harray.h */
7993 /*
7994  *  Array object representation, used for actual Array instances.
7995  *
7996  *  All objects with the exotic array behavior (which must coincide with having
7997  *  internal class array) MUST be duk_harrays.  No other object can be a
7998  *  duk_harray.  However, duk_harrays may not always have an array part.
7999  */
8000 
8001 #if !defined(DUK_HARRAY_H_INCLUDED)
8002 #define DUK_HARRAY_H_INCLUDED
8003 
8004 #if defined(DUK_USE_ASSERTIONS)
8005 DUK_INTERNAL_DECL void duk_harray_assert_valid(duk_harray *h);
8006 #define DUK_HARRAY_ASSERT_VALID(h)  do { duk_harray_assert_valid((h)); } while (0)
8007 #else
8008 #define DUK_HARRAY_ASSERT_VALID(h)  do {} while (0)
8009 #endif
8010 
8011 #define DUK_HARRAY_LENGTH_WRITABLE(h)         (!(h)->length_nonwritable)
8012 #define DUK_HARRAY_LENGTH_NONWRITABLE(h)      ((h)->length_nonwritable)
8013 #define DUK_HARRAY_SET_LENGTH_WRITABLE(h)     do { (h)->length_nonwritable = 0; } while (0)
8014 #define DUK_HARRAY_SET_LENGTH_NONWRITABLE(h)  do { (h)->length_nonwritable = 1; } while (0)
8015 
8016 struct duk_harray {
8017 	/* Shared object part. */
8018 	duk_hobject obj;
8019 
8020 	/* Array .length.
8021 	 *
8022 	 * At present Array .length may be smaller, equal, or even larger
8023 	 * than the allocated underlying array part.  Fast path code must
8024 	 * always take this into account carefully.
8025 	 */
8026 	duk_uint32_t length;
8027 
8028 	/* Array .length property attributes.  The property is always
8029 	 * non-enumerable and non-configurable.  It's initially writable
8030 	 * but per Object.defineProperty() rules it can be made non-writable
8031 	 * even if it is non-configurable.  Thus we need to track the
8032 	 * writability explicitly.
8033 	 *
8034 	 * XXX: this field to be eliminated and moved into duk_hobject
8035 	 * flags field to save space.
8036 	 */
8037 	duk_bool_t length_nonwritable;
8038 };
8039 
8040 #endif  /* DUK_HARRAY_H_INCLUDED */
8041 /* #include duk_henv.h */
8042 /*
8043  *  Environment object representation.
8044  */
8045 
8046 #if !defined(DUK_HENV_H_INCLUDED)
8047 #define DUK_HENV_H_INCLUDED
8048 
8049 #if defined(DUK_USE_ASSERTIONS)
8050 DUK_INTERNAL_DECL void duk_hdecenv_assert_valid(duk_hdecenv *h);
8051 DUK_INTERNAL_DECL void duk_hobjenv_assert_valid(duk_hobjenv *h);
8052 #define DUK_HDECENV_ASSERT_VALID(h)  do { duk_hdecenv_assert_valid((h)); } while (0)
8053 #define DUK_HOBJENV_ASSERT_VALID(h)  do { duk_hobjenv_assert_valid((h)); } while (0)
8054 #else
8055 #define DUK_HDECENV_ASSERT_VALID(h)  do {} while (0)
8056 #define DUK_HOBJENV_ASSERT_VALID(h)  do {} while (0)
8057 #endif
8058 
8059 struct duk_hdecenv {
8060 	/* Shared object part. */
8061 	duk_hobject obj;
8062 
8063 	/* These control variables provide enough information to access live
8064 	 * variables for a closure that is still open.  If thread == NULL,
8065 	 * the record is closed and the identifiers are in the property table.
8066 	 */
8067 	duk_hthread *thread;
8068 	duk_hobject *varmap;
8069 	duk_size_t regbase_byteoff;
8070 };
8071 
8072 struct duk_hobjenv {
8073 	/* Shared object part. */
8074 	duk_hobject obj;
8075 
8076 	/* Target object and 'this' binding for object binding. */
8077 	duk_hobject *target;
8078 
8079 	/* The 'target' object is used as a this binding in only some object
8080 	 * environments.  For example, the global environment does not provide
8081 	 * a this binding, but a with statement does.
8082 	 */
8083 	duk_bool_t has_this;
8084 };
8085 
8086 #endif  /* DUK_HENV_H_INCLUDED */
8087 /* #include duk_hbuffer.h */
8088 /*
8089  *  Heap buffer representation.
8090  *
8091  *  Heap allocated user data buffer which is either:
8092  *
8093  *    1. A fixed size buffer (data follows header statically)
8094  *    2. A dynamic size buffer (data pointer follows header)
8095  *
8096  *  The data pointer for a variable size buffer of zero size may be NULL.
8097  */
8098 
8099 #if !defined(DUK_HBUFFER_H_INCLUDED)
8100 #define DUK_HBUFFER_H_INCLUDED
8101 
8102 /*
8103  *  Flags
8104  *
8105  *  Fixed buffer:     0
8106  *  Dynamic buffer:   DUK_HBUFFER_FLAG_DYNAMIC
8107  *  External buffer:  DUK_HBUFFER_FLAG_DYNAMIC | DUK_HBUFFER_FLAG_EXTERNAL
8108  */
8109 
8110 #define DUK_HBUFFER_FLAG_DYNAMIC                  DUK_HEAPHDR_USER_FLAG(0)    /* buffer is behind a pointer, dynamic or external */
8111 #define DUK_HBUFFER_FLAG_EXTERNAL                 DUK_HEAPHDR_USER_FLAG(1)    /* buffer pointer is to an externally allocated buffer */
8112 
8113 #define DUK_HBUFFER_HAS_DYNAMIC(x)                DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
8114 #define DUK_HBUFFER_HAS_EXTERNAL(x)               DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
8115 
8116 #define DUK_HBUFFER_SET_DYNAMIC(x)                DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
8117 #define DUK_HBUFFER_SET_EXTERNAL(x)               DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
8118 
8119 #define DUK_HBUFFER_CLEAR_DYNAMIC(x)              DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
8120 #define DUK_HBUFFER_CLEAR_EXTERNAL(x)             DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
8121 
8122 /*
8123  *  Misc defines
8124  */
8125 
8126 /* Impose a maximum buffer length for now.  Restricted artificially to
8127  * ensure resize computations or adding a heap header length won't
8128  * overflow size_t and that a signed duk_int_t can hold a buffer
8129  * length.  The limit should be synchronized with DUK_HSTRING_MAX_BYTELEN.
8130  */
8131 
8132 #if defined(DUK_USE_BUFLEN16)
8133 #define DUK_HBUFFER_MAX_BYTELEN                   (0x0000ffffUL)
8134 #else
8135 /* Intentionally not 0x7fffffffUL; at least JSON code expects that
8136  * 2*len + 2 fits in 32 bits.
8137  */
8138 #define DUK_HBUFFER_MAX_BYTELEN                   (0x7ffffffeUL)
8139 #endif
8140 
8141 /*
8142  *  Field access
8143  */
8144 
8145 #if defined(DUK_USE_BUFLEN16)
8146 /* size stored in duk_heaphdr unused flag bits */
8147 #define DUK_HBUFFER_GET_SIZE(x)     ((x)->hdr.h_flags >> 16)
8148 #define DUK_HBUFFER_SET_SIZE(x,v)   do { \
8149 		duk_size_t duk__v; \
8150 		duk__v = (v); \
8151 		DUK_ASSERT(duk__v <= 0xffffUL); \
8152 		(x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | (((duk_uint32_t) duk__v) << 16); \
8153 	} while (0)
8154 #define DUK_HBUFFER_ADD_SIZE(x,dv)  do { \
8155 		(x)->hdr.h_flags += ((dv) << 16); \
8156 	} while (0)
8157 #define DUK_HBUFFER_SUB_SIZE(x,dv)  do { \
8158 		(x)->hdr.h_flags -= ((dv) << 16); \
8159 	} while (0)
8160 #else
8161 #define DUK_HBUFFER_GET_SIZE(x)     (((duk_hbuffer *) (x))->size)
8162 #define DUK_HBUFFER_SET_SIZE(x,v)   do { \
8163 		((duk_hbuffer *) (x))->size = (v); \
8164 	} while (0)
8165 #define DUK_HBUFFER_ADD_SIZE(x,dv)  do { \
8166 		(x)->size += (dv); \
8167 	} while (0)
8168 #define DUK_HBUFFER_SUB_SIZE(x,dv)  do { \
8169 		(x)->size -= (dv); \
8170 	} while (0)
8171 #endif
8172 
8173 #define DUK_HBUFFER_FIXED_GET_SIZE(x)       DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
8174 #define DUK_HBUFFER_FIXED_SET_SIZE(x,v)     DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x))
8175 
8176 #define DUK_HBUFFER_DYNAMIC_GET_SIZE(x)     DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
8177 #define DUK_HBUFFER_DYNAMIC_SET_SIZE(x,v)   DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
8178 #define DUK_HBUFFER_DYNAMIC_ADD_SIZE(x,dv)  DUK_HBUFFER_ADD_SIZE((duk_hbuffer *) (x), (dv))
8179 #define DUK_HBUFFER_DYNAMIC_SUB_SIZE(x,dv)  DUK_HBUFFER_SUB_SIZE((duk_hbuffer *) (x), (dv))
8180 
8181 #define DUK_HBUFFER_EXTERNAL_GET_SIZE(x)    DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
8182 #define DUK_HBUFFER_EXTERNAL_SET_SIZE(x,v)  DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
8183 
8184 #define DUK_HBUFFER_FIXED_GET_DATA_PTR(heap,x)    ((duk_uint8_t *) (((duk_hbuffer_fixed *) (void *) (x)) + 1))
8185 
8186 #if defined(DUK_USE_HEAPPTR16)
8187 #define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x) \
8188 	((void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (x))->h_extra16))
8189 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v)     do { \
8190 		((duk_heaphdr *) (x))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
8191 	} while (0)
8192 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x)  do { \
8193 		((duk_heaphdr *) (x))->h_extra16 = 0;  /* assume 0 <=> NULL */ \
8194 	} while (0)
8195 #else
8196 #define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x)       ((x)->curr_alloc)
8197 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v)     do { \
8198 		(x)->curr_alloc = (void *) (v); \
8199 	} while (0)
8200 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x)  do { \
8201 		(x)->curr_alloc = (void *) NULL; \
8202 	} while (0)
8203 #endif
8204 
8205 /* No pointer compression because pointer is potentially outside of
8206  * Duktape heap.
8207  */
8208 #if defined(DUK_USE_HEAPPTR16)
8209 #define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \
8210 	((void *) (x)->curr_alloc)
8211 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v)     do { \
8212 		(x)->curr_alloc = (void *) (v); \
8213 	} while (0)
8214 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x)  do { \
8215 		(x)->curr_alloc = (void *) NULL; \
8216 	} while (0)
8217 #else
8218 #define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \
8219 	((void *) (x)->curr_alloc)
8220 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v)     do { \
8221 		(x)->curr_alloc = (void *) (v); \
8222 	} while (0)
8223 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x)  do { \
8224 		(x)->curr_alloc = (void *) NULL; \
8225 	} while (0)
8226 #endif
8227 
8228 /* Get a pointer to the current buffer contents (matching current allocation
8229  * size).  May be NULL for zero size dynamic/external buffer.
8230  */
8231 #if defined(DUK_USE_HEAPPTR16)
8232 #define DUK_HBUFFER_GET_DATA_PTR(heap,x)  ( \
8233 	DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
8234 		( \
8235 			DUK_HBUFFER_HAS_EXTERNAL((x)) ? \
8236 				DUK_HBUFFER_EXTERNAL_GET_DATA_PTR((heap), (duk_hbuffer_external *) (x)) : \
8237 				DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) \
8238 		) : \
8239 		DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (void *) (x)) \
8240 	)
8241 #else
8242 /* Without heap pointer compression duk_hbuffer_dynamic and duk_hbuffer_external
8243  * have the same layout so checking for fixed vs. dynamic (or external) is enough.
8244  */
8245 #define DUK_HBUFFER_GET_DATA_PTR(heap,x)  ( \
8246 	DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
8247 		DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) : \
8248 		DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (void *) (x)) \
8249 	)
8250 #endif
8251 
8252 /* Validity assert. */
8253 #if defined(DUK_USE_ASSERTIONS)
8254 DUK_INTERNAL_DECL void duk_hbuffer_assert_valid(duk_hbuffer *h);
8255 #define DUK_HBUFFER_ASSERT_VALID(h)  do { duk_hbuffer_assert_valid((h)); } while (0)
8256 #else
8257 #define DUK_HBUFFER_ASSERT_VALID(h)  do {} while (0)
8258 #endif
8259 
8260 /*
8261  *  Structs
8262  */
8263 
8264 /* Shared prefix for all buffer types. */
8265 struct duk_hbuffer {
8266 	duk_heaphdr hdr;
8267 
8268 	/* It's not strictly necessary to track the current size, but
8269 	 * it is useful for writing robust native code.
8270 	 */
8271 
8272 	/* Current size. */
8273 #if defined(DUK_USE_BUFLEN16)
8274 	/* Stored in duk_heaphdr unused flags. */
8275 #else
8276 	duk_size_t size;
8277 #endif
8278 
8279 	/*
8280 	 *  Data following the header depends on the DUK_HBUFFER_FLAG_DYNAMIC
8281 	 *  flag.
8282 	 *
8283 	 *  If the flag is clear (the buffer is a fixed size one), the buffer
8284 	 *  data follows the header directly, consisting of 'size' bytes.
8285 	 *
8286 	 *  If the flag is set, the actual buffer is allocated separately, and
8287 	 *  a few control fields follow the header.  Specifically:
8288 	 *
8289 	 *    - a "void *" pointing to the current allocation
8290 	 *    - a duk_size_t indicating the full allocated size (always >= 'size')
8291 	 *
8292 	 *  If DUK_HBUFFER_FLAG_EXTERNAL is set, the buffer has been allocated
8293 	 *  by user code, so that Duktape won't be able to resize it and won't
8294 	 *  free it.  This allows buffers to point to e.g. an externally
8295 	 *  allocated structure such as a frame buffer.
8296 	 *
8297 	 *  Unlike strings, no terminator byte (NUL) is guaranteed after the
8298 	 *  data.  This would be convenient, but would pad aligned user buffers
8299 	 *  unnecessarily upwards in size.  For instance, if user code requested
8300 	 *  a 64-byte dynamic buffer, 65 bytes would actually be allocated which
8301 	 *  would then potentially round upwards to perhaps 68 or 72 bytes.
8302 	 */
8303 };
8304 
8305 /* Fixed buffer; data follows struct, with proper alignment guaranteed by
8306  * struct size.
8307  */
8308 #if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
8309 #pragma pack(push, 8)
8310 #endif
8311 struct duk_hbuffer_fixed {
8312 	/* A union is used here as a portable struct size / alignment trick:
8313 	 * by adding a 32-bit or a 64-bit (unused) union member, the size of
8314 	 * the struct is effectively forced to be a multiple of 4 or 8 bytes
8315 	 * (respectively) without increasing the size of the struct unless
8316 	 * necessary.
8317 	 */
8318 	union {
8319 		struct {
8320 			duk_heaphdr hdr;
8321 #if defined(DUK_USE_BUFLEN16)
8322 			/* Stored in duk_heaphdr unused flags. */
8323 #else
8324 			duk_size_t size;
8325 #endif
8326 		} s;
8327 #if (DUK_USE_ALIGN_BY == 4)
8328 		duk_uint32_t dummy_for_align4;
8329 #elif (DUK_USE_ALIGN_BY == 8)
8330 		duk_double_t dummy_for_align8_1;
8331 #if defined(DUK_USE_64BIT_OPS)
8332 		duk_uint64_t dummy_for_align8_2;
8333 #endif
8334 #elif (DUK_USE_ALIGN_BY == 1)
8335 		/* no extra padding */
8336 #else
8337 #error invalid DUK_USE_ALIGN_BY
8338 #endif
8339 	} u;
8340 
8341 	/*
8342 	 *  Data follows the struct header.  The struct size is padded by the
8343 	 *  compiler based on the struct members.  This guarantees that the
8344 	 *  buffer data will be aligned-by-4 but not necessarily aligned-by-8.
8345 	 *
8346 	 *  On platforms where alignment does not matter, the struct padding
8347 	 *  could be removed (if there is any).  On platforms where alignment
8348 	 *  by 8 is required, the struct size must be forced to be a multiple
8349 	 *  of 8 by some means.  Without it, some user code may break, and also
8350 	 *  Duktape itself breaks (e.g. the compiler stores duk_tvals in a
8351 	 *  dynamic buffer).
8352 	 */
8353 }
8354 #if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_GCC_ATTR)
8355 __attribute__ ((aligned (8)))
8356 #elif (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_CLANG_ATTR)
8357 __attribute__ ((aligned (8)))
8358 #endif
8359 ;
8360 #if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
8361 #pragma pack(pop)
8362 #endif
8363 
8364 /* Dynamic buffer with 'curr_alloc' pointing to a dynamic area allocated using
8365  * heap allocation primitives.  Also used for external buffers when low memory
8366  * options are not used.
8367  */
8368 struct duk_hbuffer_dynamic {
8369 	duk_heaphdr hdr;
8370 
8371 #if defined(DUK_USE_BUFLEN16)
8372 	/* Stored in duk_heaphdr unused flags. */
8373 #else
8374 	duk_size_t size;
8375 #endif
8376 
8377 #if defined(DUK_USE_HEAPPTR16)
8378 	/* Stored in duk_heaphdr h_extra16. */
8379 #else
8380 	void *curr_alloc;  /* may be NULL if alloc_size == 0 */
8381 #endif
8382 
8383 	/*
8384 	 *  Allocation size for 'curr_alloc' is alloc_size.  There is no
8385 	 *  automatic NUL terminator for buffers (see above for rationale).
8386 	 *
8387 	 *  'curr_alloc' is explicitly allocated with heap allocation
8388 	 *  primitives and will thus always have alignment suitable for
8389 	 *  e.g. duk_tval and an IEEE double.
8390 	 */
8391 };
8392 
8393 /* External buffer with 'curr_alloc' managed by user code and pointing to an
8394  * arbitrary address.  When heap pointer compression is not used, this struct
8395  * has the same layout as duk_hbuffer_dynamic.
8396  */
8397 struct duk_hbuffer_external {
8398 	duk_heaphdr hdr;
8399 
8400 #if defined(DUK_USE_BUFLEN16)
8401 	/* Stored in duk_heaphdr unused flags. */
8402 #else
8403 	duk_size_t size;
8404 #endif
8405 
8406 	/* Cannot be compressed as a heap pointer because may point to
8407 	 * an arbitrary address.
8408 	 */
8409 	void *curr_alloc;  /* may be NULL if alloc_size == 0 */
8410 };
8411 
8412 /*
8413  *  Prototypes
8414  */
8415 
8416 DUK_INTERNAL_DECL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata);
8417 DUK_INTERNAL_DECL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud);  /* indirect allocs */
8418 
8419 /* dynamic buffer ops */
8420 DUK_INTERNAL_DECL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size);
8421 DUK_INTERNAL_DECL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf);
8422 
8423 #endif  /* DUK_HBUFFER_H_INCLUDED */
8424 /* #include duk_hproxy.h */
8425 /*
8426  *  Proxy object representation.
8427  */
8428 
8429 #if !defined(DUK_HPROXY_H_INCLUDED)
8430 #define DUK_HPROXY_H_INCLUDED
8431 
8432 #if defined(DUK_USE_ASSERTIONS)
8433 DUK_INTERNAL_DECL void duk_hproxy_assert_valid(duk_hproxy *h);
8434 #define DUK_HPROXY_ASSERT_VALID(h)  do { duk_hproxy_assert_valid((h)); } while (0)
8435 #else
8436 #define DUK_HPROXY_ASSERT_VALID(h)  do {} while (0)
8437 #endif
8438 
8439 struct duk_hproxy {
8440 	/* Shared object part. */
8441 	duk_hobject obj;
8442 
8443 	/* Proxy target object. */
8444 	duk_hobject *target;
8445 
8446 	/* Proxy handlers (traps). */
8447 	duk_hobject *handler;
8448 };
8449 
8450 #endif  /* DUK_HPROXY_H_INCLUDED */
8451 /* #include duk_heap.h */
8452 /*
8453  *  Heap structure.
8454  *
8455  *  Heap contains allocated heap objects, interned strings, and built-in
8456  *  strings for one or more threads.
8457  */
8458 
8459 #if !defined(DUK_HEAP_H_INCLUDED)
8460 #define DUK_HEAP_H_INCLUDED
8461 
8462 /* alloc function typedefs in duktape.h */
8463 
8464 /*
8465  *  Heap flags
8466  */
8467 
8468 #define DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED            (1U << 0)  /* mark-and-sweep marking reached a recursion limit and must use multi-pass marking */
8469 #define DUK_HEAP_FLAG_INTERRUPT_RUNNING                        (1U << 1)  /* executor interrupt running (used to avoid nested interrupts) */
8470 #define DUK_HEAP_FLAG_FINALIZER_NORESCUE                       (1U << 2)  /* heap destruction ongoing, finalizer rescue no longer possible */
8471 #define DUK_HEAP_FLAG_DEBUGGER_PAUSED                          (1U << 3)  /* debugger is paused: talk with debug client until step/resume */
8472 
8473 #define DUK__HEAP_HAS_FLAGS(heap,bits)               ((heap)->flags & (bits))
8474 #define DUK__HEAP_SET_FLAGS(heap,bits)  do { \
8475 		(heap)->flags |= (bits); \
8476 	} while (0)
8477 #define DUK__HEAP_CLEAR_FLAGS(heap,bits)  do { \
8478 		(heap)->flags &= ~(bits); \
8479 	} while (0)
8480 
8481 #define DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap)   DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
8482 #define DUK_HEAP_HAS_INTERRUPT_RUNNING(heap)               DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
8483 #define DUK_HEAP_HAS_FINALIZER_NORESCUE(heap)              DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
8484 #define DUK_HEAP_HAS_DEBUGGER_PAUSED(heap)                 DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
8485 
8486 #define DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap)   DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
8487 #define DUK_HEAP_SET_INTERRUPT_RUNNING(heap)               DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
8488 #define DUK_HEAP_SET_FINALIZER_NORESCUE(heap)              DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
8489 #define DUK_HEAP_SET_DEBUGGER_PAUSED(heap)                 DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
8490 
8491 #define DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
8492 #define DUK_HEAP_CLEAR_INTERRUPT_RUNNING(heap)             DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
8493 #define DUK_HEAP_CLEAR_FINALIZER_NORESCUE(heap)            DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
8494 #define DUK_HEAP_CLEAR_DEBUGGER_PAUSED(heap)               DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
8495 
8496 /*
8497  *  Longjmp types, also double as identifying continuation type for a rethrow (in 'finally')
8498  */
8499 
8500 #define DUK_LJ_TYPE_UNKNOWN      0    /* unused */
8501 #define DUK_LJ_TYPE_THROW        1    /* value1 -> error object */
8502 #define DUK_LJ_TYPE_YIELD        2    /* value1 -> yield value, iserror -> error / normal */
8503 #define DUK_LJ_TYPE_RESUME       3    /* value1 -> resume value, value2 -> resumee thread, iserror -> error/normal */
8504 #define DUK_LJ_TYPE_BREAK        4    /* value1 -> label number, pseudo-type to indicate a break continuation (for ENDFIN) */
8505 #define DUK_LJ_TYPE_CONTINUE     5    /* value1 -> label number, pseudo-type to indicate a continue continuation (for ENDFIN) */
8506 #define DUK_LJ_TYPE_RETURN       6    /* value1 -> return value, pseudo-type to indicate a return continuation (for ENDFIN) */
8507 #define DUK_LJ_TYPE_NORMAL       7    /* no value, pseudo-type to indicate a normal continuation (for ENDFIN) */
8508 
8509 /*
8510  *  Mark-and-sweep flags
8511  *
8512  *  These are separate from heap level flags now but could be merged.
8513  *  The heap structure only contains a 'base mark-and-sweep flags'
8514  *  field and the GC caller can impose further flags.
8515  */
8516 
8517 /* Emergency mark-and-sweep: try extra hard, even at the cost of
8518  * performance.
8519  */
8520 #define DUK_MS_FLAG_EMERGENCY                (1U << 0)
8521 
8522 /* Postpone rescue decisions for reachable objects with FINALIZED set.
8523  * Used during finalize_list processing to avoid incorrect rescue
8524  * decisions due to finalize_list being a reachability root.
8525  */
8526 #define DUK_MS_FLAG_POSTPONE_RESCUE          (1U << 1)
8527 
8528 /* Don't compact objects; needed during object property table resize
8529  * to prevent a recursive resize.  It would suffice to protect only the
8530  * current object being resized, but this is not yet implemented.
8531  */
8532 #define DUK_MS_FLAG_NO_OBJECT_COMPACTION     (1U << 2)
8533 
8534 /*
8535  *  Thread switching
8536  *
8537  *  To switch heap->curr_thread, use the macro below so that interrupt counters
8538  *  get updated correctly.  The macro allows a NULL target thread because that
8539  *  happens e.g. in call handling.
8540  */
8541 
8542 #if defined(DUK_USE_INTERRUPT_COUNTER)
8543 #define DUK_HEAP_SWITCH_THREAD(heap,newthr)  duk_heap_switch_thread((heap), (newthr))
8544 #else
8545 #define DUK_HEAP_SWITCH_THREAD(heap,newthr)  do { \
8546 		(heap)->curr_thread = (newthr); \
8547 	} while (0)
8548 #endif
8549 
8550 /*
8551  *  Stats
8552  */
8553 
8554 #if defined(DUK_USE_DEBUG)
8555 #define DUK_STATS_INC(heap,fieldname) do { \
8556 		(heap)->fieldname += 1; \
8557 	} while (0)
8558 #else
8559 #define DUK_STATS_INC(heap,fieldname) do {} while (0)
8560 #endif
8561 
8562 /*
8563  *  Other heap related defines
8564  */
8565 
8566 /* Mark-and-sweep interval is relative to combined count of objects and
8567  * strings kept in the heap during the latest mark-and-sweep pass.
8568  * Fixed point .8 multiplier and .0 adder.  Trigger count (interval) is
8569  * decreased by each (re)allocation attempt (regardless of size), and each
8570  * refzero processed object.
8571  *
8572  * 'SKIP' indicates how many (re)allocations to wait until a retry if
8573  * GC is skipped because there is no thread do it with yet (happens
8574  * only during init phases).
8575  */
8576 #if defined(DUK_USE_REFERENCE_COUNTING)
8577 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT              12800L  /* 50x heap size */
8578 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD               1024L
8579 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP              256L
8580 #else
8581 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT              256L    /* 1x heap size */
8582 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD               1024L
8583 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP              256L
8584 #endif
8585 
8586 /* GC torture. */
8587 #if defined(DUK_USE_GC_TORTURE)
8588 #define DUK_GC_TORTURE(heap) do { duk_heap_mark_and_sweep((heap), 0); } while (0)
8589 #else
8590 #define DUK_GC_TORTURE(heap) do { } while (0)
8591 #endif
8592 
8593 /* Stringcache is used for speeding up char-offset-to-byte-offset
8594  * translations for non-ASCII strings.
8595  */
8596 #define DUK_HEAP_STRCACHE_SIZE                            4
8597 #define DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT                16  /* strings up to the this length are not cached */
8598 
8599 /* Some list management macros. */
8600 #define DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap,hdr)     duk_heap_insert_into_heap_allocated((heap), (hdr))
8601 #if defined(DUK_USE_REFERENCE_COUNTING)
8602 #define DUK_HEAP_REMOVE_FROM_HEAP_ALLOCATED(heap,hdr)     duk_heap_remove_from_heap_allocated((heap), (hdr))
8603 #endif
8604 #if defined(DUK_USE_FINALIZER_SUPPORT)
8605 #define DUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap,hdr)      duk_heap_insert_into_finalize_list((heap), (hdr))
8606 #define DUK_HEAP_REMOVE_FROM_FINALIZE_LIST(heap,hdr)      duk_heap_remove_from_finalize_list((heap), (hdr))
8607 #endif
8608 
8609 /*
8610  *  Built-in strings
8611  */
8612 
8613 /* heap string indices are autogenerated in duk_strings.h */
8614 #if defined(DUK_USE_ROM_STRINGS)
8615 #define DUK_HEAP_GET_STRING(heap,idx) \
8616 	((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))
8617 #else  /* DUK_USE_ROM_STRINGS */
8618 #if defined(DUK_USE_HEAPPTR16)
8619 #define DUK_HEAP_GET_STRING(heap,idx) \
8620 	((duk_hstring *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (heap)->strs16[(idx)]))
8621 #else
8622 #define DUK_HEAP_GET_STRING(heap,idx) \
8623 	((heap)->strs[(idx)])
8624 #endif
8625 #endif  /* DUK_USE_ROM_STRINGS */
8626 
8627 /*
8628  *  Raw memory calls: relative to heap, but no GC interaction
8629  */
8630 
8631 #define DUK_ALLOC_RAW(heap,size) \
8632 	((heap)->alloc_func((heap)->heap_udata, (size)))
8633 
8634 #define DUK_REALLOC_RAW(heap,ptr,newsize) \
8635 	((heap)->realloc_func((heap)->heap_udata, (void *) (ptr), (newsize)))
8636 
8637 #define DUK_FREE_RAW(heap,ptr) \
8638 	((heap)->free_func((heap)->heap_udata, (void *) (ptr)))
8639 
8640 /*
8641  *  Memory calls: relative to heap, GC interaction, but no error throwing.
8642  *
8643  *  XXX: Currently a mark-and-sweep triggered by memory allocation will run
8644  *  using the heap->heap_thread.  This thread is also used for running
8645  *  mark-and-sweep finalization; this is not ideal because it breaks the
8646  *  isolation between multiple global environments.
8647  *
8648  *  Notes:
8649  *
8650  *    - DUK_FREE() is required to ignore NULL and any other possible return
8651  *      value of a zero-sized alloc/realloc (same as ANSI C free()).
8652  *
8653  *    - There is no DUK_REALLOC_ZEROED because we don't assume to know the
8654  *      old size.  Caller must zero the reallocated memory.
8655  *
8656  *    - DUK_REALLOC_INDIRECT() must be used when a mark-and-sweep triggered
8657  *      by an allocation failure might invalidate the original 'ptr', thus
8658  *      causing a realloc retry to use an invalid pointer.  Example: we're
8659  *      reallocating the value stack and a finalizer resizes the same value
8660  *      stack during mark-and-sweep.  The indirect variant requests for the
8661  *      current location of the pointer being reallocated using a callback
8662  *      right before every realloc attempt; this circuitous approach is used
8663  *      to avoid strict aliasing issues in a more straightforward indirect
8664  *      pointer (void **) approach.  Note: the pointer in the storage
8665  *      location is read but is NOT updated; the caller must do that.
8666  */
8667 
8668 /* callback for indirect reallocs, request for current pointer */
8669 typedef void *(*duk_mem_getptr)(duk_heap *heap, void *ud);
8670 
8671 #define DUK_ALLOC(heap,size)                            duk_heap_mem_alloc((heap), (size))
8672 #define DUK_ALLOC_ZEROED(heap,size)                     duk_heap_mem_alloc_zeroed((heap), (size))
8673 #define DUK_REALLOC(heap,ptr,newsize)                   duk_heap_mem_realloc((heap), (ptr), (newsize))
8674 #define DUK_REALLOC_INDIRECT(heap,cb,ud,newsize)        duk_heap_mem_realloc_indirect((heap), (cb), (ud), (newsize))
8675 #define DUK_FREE(heap,ptr)                              duk_heap_mem_free((heap), (ptr))
8676 
8677 /*
8678  *  Checked allocation, relative to a thread
8679  *
8680  *  DUK_FREE_CHECKED() doesn't actually throw, but accepts a 'thr' argument
8681  *  for convenience.
8682  */
8683 
8684 #define DUK_ALLOC_CHECKED(thr,size)                     duk_heap_mem_alloc_checked((thr), (size))
8685 #define DUK_ALLOC_CHECKED_ZEROED(thr,size)              duk_heap_mem_alloc_checked_zeroed((thr), (size))
8686 #define DUK_FREE_CHECKED(thr,ptr)                       duk_heap_mem_free((thr)->heap, (ptr))
8687 
8688 /*
8689  *  Memory constants
8690  */
8691 
8692 #define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT           10  /* Retry allocation after mark-and-sweep for this
8693                                                               * many times.  A single mark-and-sweep round is
8694                                                               * not guaranteed to free all unreferenced memory
8695                                                               * because of finalization (in fact, ANY number of
8696                                                               * rounds is strictly not enough).
8697                                                               */
8698 
8699 #define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT  3  /* Starting from this round, use emergency mode
8700                                                               * for mark-and-sweep.
8701                                                               */
8702 
8703 /*
8704  *  Debugger support
8705  */
8706 
8707 /* Maximum number of breakpoints.  Only breakpoints that are set are
8708  * consulted so increasing this has no performance impact.
8709  */
8710 #define DUK_HEAP_MAX_BREAKPOINTS          16
8711 
8712 /* Opcode interval for a Date-based status/peek rate limit check.  Only
8713  * relevant when debugger is attached.  Requesting a timestamp may be a
8714  * slow operation on some platforms so this shouldn't be too low.  On the
8715  * other hand a high value makes Duktape react to a pause request slowly.
8716  */
8717 #define DUK_HEAP_DBG_RATELIMIT_OPCODES    4000
8718 
8719 /* Milliseconds between status notify and transport peeks. */
8720 #define DUK_HEAP_DBG_RATELIMIT_MILLISECS  200
8721 
8722 /* Debugger pause flags. */
8723 #define DUK_PAUSE_FLAG_ONE_OPCODE        (1U << 0)   /* pause when a single opcode has been executed */
8724 #define DUK_PAUSE_FLAG_ONE_OPCODE_ACTIVE (1U << 1)   /* one opcode pause actually active; artifact of current implementation */
8725 #define DUK_PAUSE_FLAG_LINE_CHANGE       (1U << 2)   /* pause when current line number changes */
8726 #define DUK_PAUSE_FLAG_FUNC_ENTRY        (1U << 3)   /* pause when entering a function */
8727 #define DUK_PAUSE_FLAG_FUNC_EXIT         (1U << 4)   /* pause when exiting current function */
8728 #define DUK_PAUSE_FLAG_CAUGHT_ERROR      (1U << 5)   /* pause when about to throw an error that is caught */
8729 #define DUK_PAUSE_FLAG_UNCAUGHT_ERROR    (1U << 6)   /* pause when about to throw an error that won't be caught */
8730 
8731 struct duk_breakpoint {
8732 	duk_hstring *filename;
8733 	duk_uint32_t line;
8734 };
8735 
8736 /*
8737  *  String cache should ideally be at duk_hthread level, but that would
8738  *  cause string finalization to slow down relative to the number of
8739  *  threads; string finalization must check the string cache for "weak"
8740  *  references to the string being finalized to avoid dead pointers.
8741  *
8742  *  Thus, string caches are now at the heap level now.
8743  */
8744 
8745 struct duk_strcache_entry {
8746 	duk_hstring *h;
8747 	duk_uint32_t bidx;
8748 	duk_uint32_t cidx;
8749 };
8750 
8751 /*
8752  *  Longjmp state, contains the information needed to perform a longjmp.
8753  *  Longjmp related values are written to value1, value2, and iserror.
8754  */
8755 
8756 struct duk_ljstate {
8757 	duk_jmpbuf *jmpbuf_ptr;   /* current setjmp() catchpoint */
8758 	duk_small_uint_t type;    /* longjmp type */
8759 	duk_bool_t iserror;       /* isError flag for yield */
8760 	duk_tval value1;          /* 1st related value (type specific) */
8761 	duk_tval value2;          /* 2nd related value (type specific) */
8762 };
8763 
8764 #define DUK_ASSERT_LJSTATE_UNSET(heap) do { \
8765 		DUK_ASSERT(heap != NULL); \
8766 		DUK_ASSERT(heap->lj.type == DUK_LJ_TYPE_UNKNOWN); \
8767 		DUK_ASSERT(heap->lj.iserror == 0); \
8768 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&heap->lj.value1)); \
8769 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&heap->lj.value2)); \
8770 	} while (0)
8771 #define DUK_ASSERT_LJSTATE_SET(heap) do { \
8772 		DUK_ASSERT(heap != NULL); \
8773 		DUK_ASSERT(heap->lj.type != DUK_LJ_TYPE_UNKNOWN); \
8774 	} while (0)
8775 
8776 /*
8777  *  Literal intern cache
8778  */
8779 
8780 struct duk_litcache_entry {
8781 	const duk_uint8_t *addr;
8782 	duk_hstring *h;
8783 };
8784 
8785 /*
8786  *  Main heap structure
8787  */
8788 
8789 #if defined(DUK_USE_ASSERTIONS)
8790 DUK_INTERNAL_DECL void duk_heap_assert_valid(duk_heap *heap);
8791 #define DUK_HEAP_ASSERT_VALID(heap)  do { duk_heap_assert_valid((heap)); } while (0)
8792 #else
8793 #define DUK_HEAP_ASSERT_VALID(heap)  do {} while (0)
8794 #endif
8795 
8796 struct duk_heap {
8797 	duk_small_uint_t flags;
8798 
8799 	/* Allocator functions. */
8800 	duk_alloc_function alloc_func;
8801 	duk_realloc_function realloc_func;
8802 	duk_free_function free_func;
8803 
8804 	/* Heap udata, used for allocator functions but also for other heap
8805 	 * level callbacks like fatal function, pointer compression, etc.
8806 	 */
8807 	void *heap_udata;
8808 
8809 	/* Fatal error handling, called e.g. when a longjmp() is needed but
8810 	 * lj.jmpbuf_ptr is NULL.  fatal_func must never return; it's not
8811 	 * declared as "noreturn" because doing that for typedefs is a bit
8812 	 * challenging portability-wise.
8813 	 */
8814 	duk_fatal_function fatal_func;
8815 
8816 	/* Main list of allocated heap objects.  Objects are either here,
8817 	 * in finalize_list waiting for processing, or in refzero_list
8818 	 * temporarily while a DECREF refzero cascade finishes.
8819 	 */
8820 	duk_heaphdr *heap_allocated;
8821 
8822 	/* Temporary work list for freeing a cascade of objects when a DECREF
8823 	 * (or DECREF_NORZ) encounters a zero refcount.  Using a work list
8824 	 * allows fixed C stack size when refcounts go to zero for a chain of
8825 	 * objects.  Outside of DECREF this is always a NULL because DECREF is
8826 	 * processed without side effects (only memory free calls).
8827 	 */
8828 #if defined(DUK_USE_REFERENCE_COUNTING)
8829 	duk_heaphdr *refzero_list;
8830 #endif
8831 
8832 #if defined(DUK_USE_FINALIZER_SUPPORT)
8833 	/* Work list for objects to be finalized. */
8834 	duk_heaphdr *finalize_list;
8835 #if defined(DUK_USE_ASSERTIONS)
8836 	/* Object whose finalizer is executing right now (no nesting). */
8837 	duk_heaphdr *currently_finalizing;
8838 #endif
8839 #endif
8840 
8841 	/* Freelist for duk_activations and duk_catchers. */
8842 #if defined(DUK_USE_CACHE_ACTIVATION)
8843 	duk_activation *activation_free;
8844 #endif
8845 #if defined(DUK_USE_CACHE_CATCHER)
8846 	duk_catcher *catcher_free;
8847 #endif
8848 
8849 	/* Voluntary mark-and-sweep trigger counter.  Intentionally signed
8850 	 * because we continue decreasing the value when voluntary GC cannot
8851 	 * run.
8852 	 */
8853 #if defined(DUK_USE_VOLUNTARY_GC)
8854 	duk_int_t ms_trigger_counter;
8855 #endif
8856 
8857 	/* Mark-and-sweep recursion control: too deep recursion causes
8858 	 * multi-pass processing to avoid growing C stack without bound.
8859 	 */
8860 	duk_uint_t ms_recursion_depth;
8861 
8862 	/* Mark-and-sweep flags automatically active (used for critical sections). */
8863 	duk_small_uint_t ms_base_flags;
8864 
8865 	/* Mark-and-sweep running flag.  Prevents re-entry, and also causes
8866 	 * refzero events to be ignored (= objects won't be queued to refzero_list).
8867 	 *
8868 	 * 0: mark-and-sweep not running
8869 	 * 1: mark-and-sweep is running
8870 	 * 2: heap destruction active or debugger active, prevent mark-and-sweep
8871 	 *    and refzero processing (but mark-and-sweep not itself running)
8872 	 */
8873 	duk_uint_t ms_running;
8874 
8875 	/* Mark-and-sweep prevent count, stacking.  Used to avoid M&S side
8876 	 * effects (besides finalizers which are controlled separately) such
8877 	 * as compacting the string table or object property tables.  This
8878 	 * is also bumped when ms_running is set to prevent recursive re-entry.
8879 	 * Can also be bumped when mark-and-sweep is not running.
8880 	 */
8881 	duk_uint_t ms_prevent_count;
8882 
8883 	/* Finalizer processing prevent count, stacking.  Bumped when finalizers
8884 	 * are processed to prevent recursive finalizer processing (first call site
8885 	 * processing finalizers handles all finalizers until the list is empty).
8886 	 * Can also be bumped explicitly to prevent finalizer execution.
8887 	 */
8888 	duk_uint_t pf_prevent_count;
8889 
8890 	/* When processing finalize_list, don't actually run finalizers but
8891 	 * queue finalizable objects back to heap_allocated as is.  This is
8892 	 * used during heap destruction to deal with finalizers that keep
8893 	 * on creating more finalizable garbage.
8894 	 */
8895 	duk_uint_t pf_skip_finalizers;
8896 
8897 #if defined(DUK_USE_ASSERTIONS)
8898 	/* Set when we're in a critical path where an error throw would cause
8899 	 * e.g. sandboxing/protected call violations or state corruption.  This
8900 	 * is just used for asserts.
8901 	 */
8902 	duk_bool_t error_not_allowed;
8903 #endif
8904 
8905 #if defined(DUK_USE_ASSERTIONS)
8906 	/* Set when heap is still being initialized, helps with writing
8907 	 * some assertions.
8908 	 */
8909 	duk_bool_t heap_initializing;
8910 #endif
8911 
8912 	/* Marker for detecting internal "double faults", errors thrown when
8913 	 * we're trying to create an error object, see duk_error_throw.c.
8914 	 */
8915 	duk_bool_t creating_error;
8916 
8917 	/* Marker for indicating we're calling a user error augmentation
8918 	 * (errCreate/errThrow) function.  Errors created/thrown during
8919 	 * such a call are not augmented.
8920 	 */
8921 #if defined(DUK_USE_AUGMENT_ERROR_THROW) || defined(DUK_USE_AUGMENT_ERROR_CREATE)
8922 	duk_bool_t augmenting_error;
8923 #endif
8924 
8925 	/* Longjmp state. */
8926 	duk_ljstate lj;
8927 
8928 	/* Heap thread, used internally and for finalization. */
8929 	duk_hthread *heap_thread;
8930 
8931 	/* Current running thread. */
8932 	duk_hthread *curr_thread;
8933 
8934 	/* Heap level "stash" object (e.g., various reachability roots). */
8935 	duk_hobject *heap_object;
8936 
8937 	/* duk_handle_call / duk_handle_safe_call recursion depth limiting */
8938 	duk_int_t call_recursion_depth;
8939 	duk_int_t call_recursion_limit;
8940 
8941 	/* Mix-in value for computing string hashes; should be reasonably unpredictable. */
8942 	duk_uint32_t hash_seed;
8943 
8944 	/* Random number state for duk_util_tinyrandom.c. */
8945 #if !defined(DUK_USE_GET_RANDOM_DOUBLE)
8946 #if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)
8947 	duk_uint32_t rnd_state;  /* State for Shamir's three-op algorithm */
8948 #else
8949 	duk_uint64_t rnd_state[2];  /* State for xoroshiro128+ */
8950 #endif
8951 #endif
8952 
8953 	/* Counter for unique local symbol creation. */
8954 	/* XXX: When 64-bit types are available, it would be more efficient to
8955 	 * use a duk_uint64_t at least for incrementing but maybe also for
8956 	 * string formatting in the Symbol constructor.
8957 	 */
8958 	duk_uint32_t sym_counter[2];
8959 
8960 	/* For manual debugging: instruction count based on executor and
8961 	 * interrupt counter book-keeping.  Inspect debug logs to see how
8962 	 * they match up.
8963 	 */
8964 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
8965 	duk_int_t inst_count_exec;
8966 	duk_int_t inst_count_interrupt;
8967 #endif
8968 
8969 	/* Debugger state. */
8970 #if defined(DUK_USE_DEBUGGER_SUPPORT)
8971 	/* Callbacks and udata; dbg_read_cb != NULL is used to indicate attached state. */
8972 	duk_debug_read_function dbg_read_cb;                /* required, NULL implies detached */
8973 	duk_debug_write_function dbg_write_cb;              /* required */
8974 	duk_debug_peek_function dbg_peek_cb;
8975 	duk_debug_read_flush_function dbg_read_flush_cb;
8976 	duk_debug_write_flush_function dbg_write_flush_cb;
8977 	duk_debug_request_function dbg_request_cb;
8978 	duk_debug_detached_function dbg_detached_cb;
8979 	void *dbg_udata;
8980 
8981 	/* The following are only relevant when debugger is attached. */
8982 	duk_bool_t dbg_processing;              /* currently processing messages or breakpoints: don't enter message processing recursively (e.g. no breakpoints when processing debugger eval) */
8983 	duk_bool_t dbg_state_dirty;             /* resend state next time executor is about to run */
8984 	duk_bool_t dbg_force_restart;           /* force executor restart to recheck breakpoints; used to handle function returns (see GH-303) */
8985 	duk_bool_t dbg_detaching;               /* debugger detaching; used to avoid calling detach handler recursively */
8986 	duk_small_uint_t dbg_pause_flags;       /* flags for automatic pause behavior */
8987 	duk_activation *dbg_pause_act;          /* activation related to pause behavior (pause on line change, function entry/exit) */
8988 	duk_uint32_t dbg_pause_startline;       /* starting line number for line change related pause behavior */
8989 	duk_breakpoint dbg_breakpoints[DUK_HEAP_MAX_BREAKPOINTS];  /* breakpoints: [0,breakpoint_count[ gc reachable */
8990 	duk_small_uint_t dbg_breakpoint_count;
8991 	duk_breakpoint *dbg_breakpoints_active[DUK_HEAP_MAX_BREAKPOINTS + 1];  /* currently active breakpoints: NULL term, borrowed pointers */
8992 	/* XXX: make active breakpoints actual copies instead of pointers? */
8993 
8994 	/* These are for rate limiting Status notifications and transport peeking. */
8995 	duk_uint_t dbg_exec_counter;            /* cumulative opcode execution count (overflows are OK) */
8996 	duk_uint_t dbg_last_counter;            /* value of dbg_exec_counter when we last did a Date-based check */
8997 	duk_double_t dbg_last_time;             /* time when status/peek was last done (Date-based rate limit) */
8998 
8999 	/* Used to support single-byte stream lookahead. */
9000 	duk_bool_t dbg_have_next_byte;
9001 	duk_uint8_t dbg_next_byte;
9002 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
9003 #if defined(DUK_USE_ASSERTIONS)
9004 	duk_bool_t dbg_calling_transport;       /* transport call in progress, calling into Duktape forbidden */
9005 #endif
9006 
9007 	/* String intern table (weak refs). */
9008 #if defined(DUK_USE_STRTAB_PTRCOMP)
9009 	duk_uint16_t *strtable16;
9010 #else
9011 	duk_hstring **strtable;
9012 #endif
9013 	duk_uint32_t st_mask;    /* mask for lookup, st_size - 1 */
9014 	duk_uint32_t st_size;    /* stringtable size */
9015 #if (DUK_USE_STRTAB_MINSIZE != DUK_USE_STRTAB_MAXSIZE)
9016 	duk_uint32_t st_count;   /* string count for resize load factor checks */
9017 #endif
9018 	duk_bool_t st_resizing;  /* string table is being resized; avoid recursive resize */
9019 
9020 	/* String access cache (codepoint offset -> byte offset) for fast string
9021 	 * character looping; 'weak' reference which needs special handling in GC.
9022 	 */
9023 	duk_strcache_entry strcache[DUK_HEAP_STRCACHE_SIZE];
9024 
9025 #if defined(DUK_USE_LITCACHE_SIZE)
9026 	/* Literal intern cache.  When enabled, strings interned as literals
9027 	 * (e.g. duk_push_literal()) will be pinned and cached for the lifetime
9028 	 * of the heap.
9029 	 */
9030 	duk_litcache_entry litcache[DUK_USE_LITCACHE_SIZE];
9031 #endif
9032 
9033 	/* Built-in strings. */
9034 #if defined(DUK_USE_ROM_STRINGS)
9035 	/* No field needed when strings are in ROM. */
9036 #else
9037 #if defined(DUK_USE_HEAPPTR16)
9038 	duk_uint16_t strs16[DUK_HEAP_NUM_STRINGS];
9039 #else
9040 	duk_hstring *strs[DUK_HEAP_NUM_STRINGS];
9041 #endif
9042 #endif
9043 
9044 	/* Stats. */
9045 #if defined(DUK_USE_DEBUG)
9046 	duk_int_t stats_exec_opcodes;
9047 	duk_int_t stats_exec_interrupt;
9048 	duk_int_t stats_exec_throw;
9049 	duk_int_t stats_call_all;
9050 	duk_int_t stats_call_tailcall;
9051 	duk_int_t stats_call_ecmatoecma;
9052 	duk_int_t stats_safecall_all;
9053 	duk_int_t stats_safecall_nothrow;
9054 	duk_int_t stats_safecall_throw;
9055 	duk_int_t stats_ms_try_count;
9056 	duk_int_t stats_ms_skip_count;
9057 	duk_int_t stats_ms_emergency_count;
9058 	duk_int_t stats_strtab_intern_hit;
9059 	duk_int_t stats_strtab_intern_miss;
9060 	duk_int_t stats_strtab_resize_check;
9061 	duk_int_t stats_strtab_resize_grow;
9062 	duk_int_t stats_strtab_resize_shrink;
9063 	duk_int_t stats_strtab_litcache_hit;
9064 	duk_int_t stats_strtab_litcache_miss;
9065 	duk_int_t stats_strtab_litcache_pin;
9066 	duk_int_t stats_object_realloc_props;
9067 	duk_int_t stats_object_abandon_array;
9068 	duk_int_t stats_getownpropdesc_count;
9069 	duk_int_t stats_getownpropdesc_hit;
9070 	duk_int_t stats_getownpropdesc_miss;
9071 	duk_int_t stats_getpropdesc_count;
9072 	duk_int_t stats_getpropdesc_hit;
9073 	duk_int_t stats_getpropdesc_miss;
9074 	duk_int_t stats_getprop_all;
9075 	duk_int_t stats_getprop_arrayidx;
9076 	duk_int_t stats_getprop_bufobjidx;
9077 	duk_int_t stats_getprop_bufferidx;
9078 	duk_int_t stats_getprop_bufferlen;
9079 	duk_int_t stats_getprop_stringidx;
9080 	duk_int_t stats_getprop_stringlen;
9081 	duk_int_t stats_getprop_proxy;
9082 	duk_int_t stats_getprop_arguments;
9083 	duk_int_t stats_putprop_all;
9084 	duk_int_t stats_putprop_arrayidx;
9085 	duk_int_t stats_putprop_bufobjidx;
9086 	duk_int_t stats_putprop_bufferidx;
9087 	duk_int_t stats_putprop_proxy;
9088 	duk_int_t stats_getvar_all;
9089 	duk_int_t stats_putvar_all;
9090 	duk_int_t stats_envrec_delayedcreate;
9091 	duk_int_t stats_envrec_create;
9092 	duk_int_t stats_envrec_newenv;
9093 	duk_int_t stats_envrec_oldenv;
9094 	duk_int_t stats_envrec_pushclosure;
9095 #endif
9096 };
9097 
9098 /*
9099  *  Prototypes
9100  */
9101 
9102 DUK_INTERNAL_DECL
9103 duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
9104                          duk_realloc_function realloc_func,
9105                          duk_free_function free_func,
9106                          void *heap_udata,
9107                          duk_fatal_function fatal_func);
9108 DUK_INTERNAL_DECL void duk_heap_free(duk_heap *heap);
9109 DUK_INTERNAL_DECL void duk_free_hobject(duk_heap *heap, duk_hobject *h);
9110 DUK_INTERNAL_DECL void duk_free_hbuffer(duk_heap *heap, duk_hbuffer *h);
9111 DUK_INTERNAL_DECL void duk_free_hstring(duk_heap *heap, duk_hstring *h);
9112 DUK_INTERNAL_DECL void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr);
9113 
9114 DUK_INTERNAL_DECL void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphdr *hdr);
9115 #if defined(DUK_USE_REFERENCE_COUNTING)
9116 DUK_INTERNAL_DECL void duk_heap_remove_from_heap_allocated(duk_heap *heap, duk_heaphdr *hdr);
9117 #endif
9118 #if defined(DUK_USE_FINALIZER_SUPPORT)
9119 DUK_INTERNAL_DECL void duk_heap_insert_into_finalize_list(duk_heap *heap, duk_heaphdr *hdr);
9120 DUK_INTERNAL_DECL void duk_heap_remove_from_finalize_list(duk_heap *heap, duk_heaphdr *hdr);
9121 #endif
9122 #if defined(DUK_USE_ASSERTIONS)
9123 DUK_INTERNAL_DECL duk_bool_t duk_heap_in_heap_allocated(duk_heap *heap, duk_heaphdr *ptr);
9124 #endif
9125 #if defined(DUK_USE_INTERRUPT_COUNTER)
9126 DUK_INTERNAL_DECL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr);
9127 #endif
9128 
9129 DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen);
9130 DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t len);
9131 #if defined(DUK_USE_LITCACHE_SIZE)
9132 DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_literal_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen);
9133 #endif
9134 DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_u32(duk_heap *heap, duk_uint32_t val);
9135 DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_u32_checked(duk_hthread *thr, duk_uint32_t val);
9136 #if defined(DUK_USE_REFERENCE_COUNTING)
9137 DUK_INTERNAL_DECL void duk_heap_strtable_unlink(duk_heap *heap, duk_hstring *h);
9138 #endif
9139 DUK_INTERNAL_DECL void duk_heap_strtable_unlink_prev(duk_heap *heap, duk_hstring *h, duk_hstring *prev);
9140 DUK_INTERNAL_DECL void duk_heap_strtable_force_resize(duk_heap *heap);
9141 DUK_INTERNAL void duk_heap_strtable_free(duk_heap *heap);
9142 #if defined(DUK_USE_DEBUG)
9143 DUK_INTERNAL void duk_heap_strtable_dump(duk_heap *heap);
9144 #endif
9145 
9146 DUK_INTERNAL_DECL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h);
9147 DUK_INTERNAL_DECL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset);
9148 
9149 #if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
9150 DUK_INTERNAL_DECL void *duk_default_alloc_function(void *udata, duk_size_t size);
9151 DUK_INTERNAL_DECL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize);
9152 DUK_INTERNAL_DECL void duk_default_free_function(void *udata, void *ptr);
9153 #endif
9154 
9155 DUK_INTERNAL_DECL void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size);
9156 DUK_INTERNAL_DECL void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size);
9157 DUK_INTERNAL_DECL void *duk_heap_mem_alloc_checked(duk_hthread *thr, duk_size_t size);
9158 DUK_INTERNAL_DECL void *duk_heap_mem_alloc_checked_zeroed(duk_hthread *thr, duk_size_t size);
9159 DUK_INTERNAL_DECL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize);
9160 DUK_INTERNAL_DECL void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize);
9161 DUK_INTERNAL_DECL void duk_heap_mem_free(duk_heap *heap, void *ptr);
9162 
9163 DUK_INTERNAL_DECL void duk_heap_free_freelists(duk_heap *heap);
9164 
9165 #if defined(DUK_USE_FINALIZER_SUPPORT)
9166 DUK_INTERNAL_DECL void duk_heap_run_finalizer(duk_heap *heap, duk_hobject *obj);
9167 DUK_INTERNAL_DECL void duk_heap_process_finalize_list(duk_heap *heap);
9168 #endif  /* DUK_USE_FINALIZER_SUPPORT */
9169 
9170 DUK_INTERNAL_DECL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags);
9171 
9172 DUK_INTERNAL_DECL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len);
9173 
9174 #endif  /* DUK_HEAP_H_INCLUDED */
9175 /* #include duk_debugger.h */
9176 #if !defined(DUK_DEBUGGER_H_INCLUDED)
9177 #define DUK_DEBUGGER_H_INCLUDED
9178 
9179 /* Debugger protocol version is defined in the public API header. */
9180 
9181 /* Initial bytes for markers. */
9182 #define DUK_DBG_IB_EOM                   0x00
9183 #define DUK_DBG_IB_REQUEST               0x01
9184 #define DUK_DBG_IB_REPLY                 0x02
9185 #define DUK_DBG_IB_ERROR                 0x03
9186 #define DUK_DBG_IB_NOTIFY                0x04
9187 
9188 /* Other initial bytes. */
9189 #define DUK_DBG_IB_INT4                  0x10
9190 #define DUK_DBG_IB_STR4                  0x11
9191 #define DUK_DBG_IB_STR2                  0x12
9192 #define DUK_DBG_IB_BUF4                  0x13
9193 #define DUK_DBG_IB_BUF2                  0x14
9194 #define DUK_DBG_IB_UNUSED                0x15
9195 #define DUK_DBG_IB_UNDEFINED             0x16
9196 #define DUK_DBG_IB_NULL                  0x17
9197 #define DUK_DBG_IB_TRUE                  0x18
9198 #define DUK_DBG_IB_FALSE                 0x19
9199 #define DUK_DBG_IB_NUMBER                0x1a
9200 #define DUK_DBG_IB_OBJECT                0x1b
9201 #define DUK_DBG_IB_POINTER               0x1c
9202 #define DUK_DBG_IB_LIGHTFUNC             0x1d
9203 #define DUK_DBG_IB_HEAPPTR               0x1e
9204 /* The short string/integer initial bytes starting from 0x60 don't have
9205  * defines now.
9206  */
9207 
9208 /* Error codes. */
9209 #define DUK_DBG_ERR_UNKNOWN              0x00
9210 #define DUK_DBG_ERR_UNSUPPORTED          0x01
9211 #define DUK_DBG_ERR_TOOMANY              0x02
9212 #define DUK_DBG_ERR_NOTFOUND             0x03
9213 #define DUK_DBG_ERR_APPLICATION          0x04
9214 
9215 /* Commands and notifys initiated by Duktape. */
9216 #define DUK_DBG_CMD_STATUS               0x01
9217 #define DUK_DBG_CMD_UNUSED_2             0x02  /* Duktape 1.x: print notify */
9218 #define DUK_DBG_CMD_UNUSED_3             0x03  /* Duktape 1.x: alert notify */
9219 #define DUK_DBG_CMD_UNUSED_4             0x04  /* Duktape 1.x: log notify */
9220 #define DUK_DBG_CMD_THROW                0x05
9221 #define DUK_DBG_CMD_DETACHING            0x06
9222 #define DUK_DBG_CMD_APPNOTIFY            0x07
9223 
9224 /* Commands initiated by debug client. */
9225 #define DUK_DBG_CMD_BASICINFO            0x10
9226 #define DUK_DBG_CMD_TRIGGERSTATUS        0x11
9227 #define DUK_DBG_CMD_PAUSE                0x12
9228 #define DUK_DBG_CMD_RESUME               0x13
9229 #define DUK_DBG_CMD_STEPINTO             0x14
9230 #define DUK_DBG_CMD_STEPOVER             0x15
9231 #define DUK_DBG_CMD_STEPOUT              0x16
9232 #define DUK_DBG_CMD_LISTBREAK            0x17
9233 #define DUK_DBG_CMD_ADDBREAK             0x18
9234 #define DUK_DBG_CMD_DELBREAK             0x19
9235 #define DUK_DBG_CMD_GETVAR               0x1a
9236 #define DUK_DBG_CMD_PUTVAR               0x1b
9237 #define DUK_DBG_CMD_GETCALLSTACK         0x1c
9238 #define DUK_DBG_CMD_GETLOCALS            0x1d
9239 #define DUK_DBG_CMD_EVAL                 0x1e
9240 #define DUK_DBG_CMD_DETACH               0x1f
9241 #define DUK_DBG_CMD_DUMPHEAP             0x20
9242 #define DUK_DBG_CMD_GETBYTECODE          0x21
9243 #define DUK_DBG_CMD_APPREQUEST           0x22
9244 #define DUK_DBG_CMD_GETHEAPOBJINFO       0x23
9245 #define DUK_DBG_CMD_GETOBJPROPDESC       0x24
9246 #define DUK_DBG_CMD_GETOBJPROPDESCRANGE  0x25
9247 
9248 /* The low 8 bits map directly to duk_hobject.h DUK_PROPDESC_FLAG_xxx.
9249  * The remaining flags are specific to the debugger.
9250  */
9251 #define DUK_DBG_PROPFLAG_SYMBOL          (1U << 8)
9252 #define DUK_DBG_PROPFLAG_HIDDEN          (1U << 9)
9253 
9254 #if defined(DUK_USE_DEBUGGER_SUPPORT)
9255 DUK_INTERNAL_DECL void duk_debug_do_detach(duk_heap *heap);
9256 
9257 DUK_INTERNAL_DECL duk_bool_t duk_debug_read_peek(duk_hthread *thr);
9258 DUK_INTERNAL_DECL void duk_debug_write_flush(duk_hthread *thr);
9259 
9260 DUK_INTERNAL_DECL void duk_debug_skip_bytes(duk_hthread *thr, duk_size_t length);
9261 DUK_INTERNAL_DECL void duk_debug_skip_byte(duk_hthread *thr);
9262 
9263 DUK_INTERNAL_DECL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_size_t length);
9264 DUK_INTERNAL_DECL duk_uint8_t duk_debug_read_byte(duk_hthread *thr);
9265 DUK_INTERNAL_DECL duk_int32_t duk_debug_read_int(duk_hthread *thr);
9266 DUK_INTERNAL_DECL duk_hstring *duk_debug_read_hstring(duk_hthread *thr);
9267 /* XXX: exposed duk_debug_read_pointer */
9268 /* XXX: exposed duk_debug_read_buffer */
9269 /* XXX: exposed duk_debug_read_hbuffer */
9270 #if 0
9271 DUK_INTERNAL_DECL duk_heaphdr *duk_debug_read_heapptr(duk_hthread *thr);
9272 #endif
9273 #if defined(DUK_USE_DEBUGGER_INSPECT)
9274 DUK_INTERNAL_DECL duk_heaphdr *duk_debug_read_any_ptr(duk_hthread *thr);
9275 #endif
9276 DUK_INTERNAL_DECL duk_tval *duk_debug_read_tval(duk_hthread *thr);
9277 
9278 DUK_INTERNAL_DECL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *data, duk_size_t length);
9279 DUK_INTERNAL_DECL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x);
9280 DUK_INTERNAL_DECL void duk_debug_write_unused(duk_hthread *thr);
9281 DUK_INTERNAL_DECL void duk_debug_write_undefined(duk_hthread *thr);
9282 #if defined(DUK_USE_DEBUGGER_INSPECT)
9283 DUK_INTERNAL_DECL void duk_debug_write_null(duk_hthread *thr);
9284 #endif
9285 DUK_INTERNAL_DECL void duk_debug_write_boolean(duk_hthread *thr, duk_uint_t val);
9286 DUK_INTERNAL_DECL void duk_debug_write_int(duk_hthread *thr, duk_int32_t x);
9287 DUK_INTERNAL_DECL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x);
9288 DUK_INTERNAL_DECL void duk_debug_write_string(duk_hthread *thr, const char *data, duk_size_t length);
9289 DUK_INTERNAL_DECL void duk_debug_write_cstring(duk_hthread *thr, const char *data);
9290 DUK_INTERNAL_DECL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h);
9291 DUK_INTERNAL_DECL void duk_debug_write_buffer(duk_hthread *thr, const char *data, duk_size_t length);
9292 DUK_INTERNAL_DECL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h);
9293 DUK_INTERNAL_DECL void duk_debug_write_pointer(duk_hthread *thr, void *ptr);
9294 #if defined(DUK_USE_DEBUGGER_DUMPHEAP) || defined(DUK_USE_DEBUGGER_INSPECT)
9295 DUK_INTERNAL_DECL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h);
9296 #endif
9297 DUK_INTERNAL_DECL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj);
9298 DUK_INTERNAL_DECL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv);
9299 #if 0  /* unused */
9300 DUK_INTERNAL_DECL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command);
9301 #endif
9302 DUK_INTERNAL_DECL void duk_debug_write_reply(duk_hthread *thr);
9303 DUK_INTERNAL_DECL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uint_t err_code, const char *msg);
9304 DUK_INTERNAL_DECL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t command);
9305 DUK_INTERNAL_DECL void duk_debug_write_eom(duk_hthread *thr);
9306 
9307 DUK_INTERNAL_DECL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr);
9308 DUK_INTERNAL_DECL void duk_debug_send_status(duk_hthread *thr);
9309 #if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
9310 DUK_INTERNAL_DECL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal);
9311 #endif
9312 
9313 DUK_INTERNAL_DECL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev_pc);
9314 DUK_INTERNAL_DECL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t no_block);
9315 
9316 DUK_INTERNAL_DECL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstring *filename, duk_uint32_t line);
9317 DUK_INTERNAL_DECL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_uint_t breakpoint_index);
9318 
9319 DUK_INTERNAL_DECL duk_bool_t duk_debug_is_attached(duk_heap *heap);
9320 DUK_INTERNAL_DECL duk_bool_t duk_debug_is_paused(duk_heap *heap);
9321 DUK_INTERNAL_DECL void duk_debug_set_paused(duk_heap *heap);
9322 DUK_INTERNAL_DECL void duk_debug_clear_paused(duk_heap *heap);
9323 DUK_INTERNAL_DECL void duk_debug_clear_pause_state(duk_heap *heap);
9324 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
9325 
9326 #endif  /* DUK_DEBUGGER_H_INCLUDED */
9327 /* #include duk_debug.h */
9328 /*
9329  *  Debugging macros, DUK_DPRINT() and its variants in particular.
9330  *
9331  *  DUK_DPRINT() allows formatted debug prints, and supports standard
9332  *  and Duktape specific formatters.  See duk_debug_vsnprintf.c for details.
9333  *
9334  *  DUK_D(x), DUK_DD(x), and DUK_DDD(x) are used together with log macros
9335  *  for technical reasons.  They are concretely used to hide 'x' from the
9336  *  compiler when the corresponding log level is disabled.  This allows
9337  *  clean builds on non-C99 compilers, at the cost of more verbose code.
9338  *  Examples:
9339  *
9340  *    DUK_D(DUK_DPRINT("foo"));
9341  *    DUK_DD(DUK_DDPRINT("foo"));
9342  *    DUK_DDD(DUK_DDDPRINT("foo"));
9343  *
9344  *  This approach is preferable to the old "double parentheses" hack because
9345  *  double parentheses make the C99 solution worse: __FILE__ and __LINE__ can
9346  *  no longer be added transparently without going through globals, which
9347  *  works poorly with threading.
9348  */
9349 
9350 #if !defined(DUK_DEBUG_H_INCLUDED)
9351 #define DUK_DEBUG_H_INCLUDED
9352 
9353 #if defined(DUK_USE_DEBUG)
9354 
9355 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)
9356 #define DUK_D(x) x
9357 #else
9358 #define DUK_D(x) do { } while (0) /* omit */
9359 #endif
9360 
9361 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
9362 #define DUK_DD(x) x
9363 #else
9364 #define DUK_DD(x) do { } while (0) /* omit */
9365 #endif
9366 
9367 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
9368 #define DUK_DDD(x) x
9369 #else
9370 #define DUK_DDD(x) do { } while (0) /* omit */
9371 #endif
9372 
9373 /*
9374  *  Exposed debug macros: debugging enabled
9375  */
9376 
9377 #if defined(DUK_USE_VARIADIC_MACROS)
9378 
9379 /* Note: combining __FILE__, __LINE__, and __func__ into fmt would be
9380  * possible compile time, but waste some space with shared function names.
9381  */
9382 #define DUK__DEBUG_LOG(lev,...)  duk_debug_log((duk_int_t) (lev), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, DUK_FUNC_MACRO, __VA_ARGS__);
9383 
9384 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)
9385 #define DUK_DPRINT(...)          DUK__DEBUG_LOG(DUK_LEVEL_DEBUG, __VA_ARGS__)
9386 #else
9387 #define DUK_DPRINT(...)
9388 #endif
9389 
9390 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
9391 #define DUK_DDPRINT(...)         DUK__DEBUG_LOG(DUK_LEVEL_DDEBUG, __VA_ARGS__)
9392 #else
9393 #define DUK_DDPRINT(...)
9394 #endif
9395 
9396 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
9397 #define DUK_DDDPRINT(...)        DUK__DEBUG_LOG(DUK_LEVEL_DDDEBUG, __VA_ARGS__)
9398 #else
9399 #define DUK_DDDPRINT(...)
9400 #endif
9401 
9402 #else  /* DUK_USE_VARIADIC_MACROS */
9403 
9404 #define DUK__DEBUG_STASH(lev)    \
9405 	(void) DUK_SNPRINTF(duk_debug_file_stash, DUK_DEBUG_STASH_SIZE, "%s", (const char *) DUK_FILE_MACRO), \
9406 	(void) (duk_debug_file_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0), \
9407 	(void) (duk_debug_line_stash = (duk_int_t) DUK_LINE_MACRO), \
9408 	(void) DUK_SNPRINTF(duk_debug_func_stash, DUK_DEBUG_STASH_SIZE, "%s", (const char *) DUK_FUNC_MACRO), \
9409 	(void) (duk_debug_func_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0), \
9410 	(void) (duk_debug_level_stash = (lev))
9411 
9412 /* Without variadic macros resort to comma expression trickery to handle debug
9413  * prints.  This generates a lot of harmless warnings.  These hacks are not
9414  * needed normally because DUK_D() and friends will hide the entire debug log
9415  * statement from the compiler.
9416  */
9417 
9418 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)
9419 #define DUK_DPRINT  DUK__DEBUG_STASH(DUK_LEVEL_DEBUG), (void) duk_debug_log  /* args go here in parens */
9420 #else
9421 #define DUK_DPRINT  0 && /* args go here as a comma expression in parens */
9422 #endif
9423 
9424 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
9425 #define DUK_DDPRINT  DUK__DEBUG_STASH(DUK_LEVEL_DDEBUG), (void) duk_debug_log  /* args go here in parens */
9426 #else
9427 #define DUK_DDPRINT  0 && /* args */
9428 #endif
9429 
9430 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
9431 #define DUK_DDDPRINT  DUK__DEBUG_STASH(DUK_LEVEL_DDDEBUG), (void) duk_debug_log  /* args go here in parens */
9432 #else
9433 #define DUK_DDDPRINT  0 && /* args */
9434 #endif
9435 
9436 #endif  /* DUK_USE_VARIADIC_MACROS */
9437 
9438 #else  /* DUK_USE_DEBUG */
9439 
9440 /*
9441  *  Exposed debug macros: debugging disabled
9442  */
9443 
9444 #define DUK_D(x) do { } while (0) /* omit */
9445 #define DUK_DD(x) do { } while (0) /* omit */
9446 #define DUK_DDD(x) do { } while (0) /* omit */
9447 
9448 #if defined(DUK_USE_VARIADIC_MACROS)
9449 
9450 #define DUK_DPRINT(...)
9451 #define DUK_DDPRINT(...)
9452 #define DUK_DDDPRINT(...)
9453 
9454 #else  /* DUK_USE_VARIADIC_MACROS */
9455 
9456 #define DUK_DPRINT    0 && /* args go here as a comma expression in parens */
9457 #define DUK_DDPRINT   0 && /* args */
9458 #define DUK_DDDPRINT  0 && /* args */
9459 
9460 #endif  /* DUK_USE_VARIADIC_MACROS */
9461 
9462 #endif  /* DUK_USE_DEBUG */
9463 
9464 /*
9465  *  Structs
9466  */
9467 
9468 #if defined(DUK_USE_DEBUG)
9469 struct duk_fixedbuffer {
9470 	duk_uint8_t *buffer;
9471 	duk_size_t length;
9472 	duk_size_t offset;
9473 	duk_bool_t truncated;
9474 };
9475 #endif
9476 
9477 /*
9478  *  Prototypes
9479  */
9480 
9481 #if defined(DUK_USE_DEBUG)
9482 DUK_INTERNAL_DECL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap);
9483 #if 0  /*unused*/
9484 DUK_INTERNAL_DECL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...);
9485 #endif
9486 DUK_INTERNAL_DECL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size);
9487 
9488 #if defined(DUK_USE_VARIADIC_MACROS)
9489 DUK_INTERNAL_DECL void duk_debug_log(duk_int_t level, const char *file, duk_int_t line, const char *func, const char *fmt, ...);
9490 #else  /* DUK_USE_VARIADIC_MACROS */
9491 /* parameter passing, not thread safe */
9492 #define DUK_DEBUG_STASH_SIZE  128
9493 #if !defined(DUK_SINGLE_FILE)
9494 DUK_INTERNAL_DECL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
9495 DUK_INTERNAL_DECL duk_int_t duk_debug_line_stash;
9496 DUK_INTERNAL_DECL char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];
9497 DUK_INTERNAL_DECL duk_int_t duk_debug_level_stash;
9498 #endif
9499 DUK_INTERNAL_DECL void duk_debug_log(const char *fmt, ...);
9500 #endif  /* DUK_USE_VARIADIC_MACROS */
9501 
9502 DUK_INTERNAL_DECL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length);
9503 DUK_INTERNAL_DECL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x);
9504 DUK_INTERNAL_DECL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x);
9505 DUK_INTERNAL_DECL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...);
9506 DUK_INTERNAL_DECL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size);
9507 DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb);
9508 
9509 #endif  /* DUK_USE_DEBUG */
9510 
9511 #endif  /* DUK_DEBUG_H_INCLUDED */
9512 /* #include duk_error.h */
9513 /*
9514  *  Error handling macros, assertion macro, error codes.
9515  *
9516  *  There are three types of 'errors':
9517  *
9518  *    1. Ordinary errors relative to a thread, cause a longjmp, catchable.
9519  *    2. Fatal errors relative to a heap, cause fatal handler to be called.
9520  *    3. Fatal errors without context, cause the default (not heap specific)
9521  *       fatal handler to be called.
9522  *
9523  *  Fatal errors without context are used by debug code such as assertions.
9524  *  By providing a fatal error handler for a Duktape heap, user code can
9525  *  avoid fatal errors without context in non-debug builds.
9526  */
9527 
9528 #if !defined(DUK_ERROR_H_INCLUDED)
9529 #define DUK_ERROR_H_INCLUDED
9530 
9531 /*
9532  *  Error codes: defined in duktape.h
9533  *
9534  *  Error codes are used as a shorthand to throw exceptions from inside
9535  *  the implementation.  The appropriate ECMAScript object is constructed
9536  *  based on the code.  ECMAScript code throws objects directly.  The error
9537  *  codes are defined in the public API header because they are also used
9538  *  by calling code.
9539  */
9540 
9541 /*
9542  *  Normal error
9543  *
9544  *  Normal error is thrown with a longjmp() through the current setjmp()
9545  *  catchpoint record in the duk_heap.  The 'curr_thread' of the duk_heap
9546  *  identifies the throwing thread.
9547  *
9548  *  Error formatting is usually unnecessary.  The error macros provide a
9549  *  zero argument version (no formatting) and separate macros for small
9550  *  argument counts.  Variadic macros are not used to avoid portability
9551  *  issues and avoid the need for stash-based workarounds when they're not
9552  *  available.  Vararg calls are avoided for non-formatted error calls
9553  *  because vararg call sites are larger than normal, and there are a lot
9554  *  of call sites with no formatting.
9555  *
9556  *  Note that special formatting provided by debug macros is NOT available.
9557  *
9558  *  The _RAW variants allow the caller to specify file and line.  This makes
9559  *  it easier to write checked calls which want to use the call site of the
9560  *  checked function, not the error macro call inside the checked function.
9561  */
9562 
9563 #if defined(DUK_USE_VERBOSE_ERRORS)
9564 
9565 /* Because there are quite many call sites, pack error code (require at most
9566  * 8-bit) into a single argument.
9567  */
9568 #define DUK_ERROR(thr,err,msg) do { \
9569 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
9570 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9571 		duk_err_handle_error((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (msg)); \
9572 	} while (0)
9573 #define DUK_ERROR_RAW(thr,file,line,err,msg) do { \
9574 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
9575 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9576 		duk_err_handle_error((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (msg)); \
9577 	} while (0)
9578 
9579 #define DUK_ERROR_FMT1(thr,err,fmt,arg1) do { \
9580 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
9581 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9582 		duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1)); \
9583 	} while (0)
9584 #define DUK_ERROR_RAW_FMT1(thr,file,line,err,fmt,arg1) do { \
9585 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
9586 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9587 		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1)); \
9588 	} while (0)
9589 
9590 #define DUK_ERROR_FMT2(thr,err,fmt,arg1,arg2) do { \
9591 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
9592 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9593 		duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2)); \
9594 	} while (0)
9595 #define DUK_ERROR_RAW_FMT2(thr,file,line,err,fmt,arg1,arg2) do { \
9596 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
9597 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9598 		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2)); \
9599 	} while (0)
9600 
9601 #define DUK_ERROR_FMT3(thr,err,fmt,arg1,arg2,arg3) do { \
9602 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
9603 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9604 		duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3)); \
9605 	} while (0)
9606 #define DUK_ERROR_RAW_FMT3(thr,file,line,err,fmt,arg1,arg2,arg3) do { \
9607 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
9608 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9609 		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3)); \
9610 	} while (0)
9611 
9612 #define DUK_ERROR_FMT4(thr,err,fmt,arg1,arg2,arg3,arg4) do { \
9613 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
9614 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9615 		duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3), (arg4)); \
9616 	} while (0)
9617 #define DUK_ERROR_RAW_FMT4(thr,file,line,err,fmt,arg1,arg2,arg3,arg4) do { \
9618 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
9619 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9620 		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3), (arg4)); \
9621 	} while (0)
9622 
9623 #else  /* DUK_USE_VERBOSE_ERRORS */
9624 
9625 #define DUK_ERROR(thr,err,msg)                    duk_err_handle_error((thr), (err))
9626 #define DUK_ERROR_RAW(thr,file,line,err,msg)      duk_err_handle_error((thr), (err))
9627 
9628 #define DUK_ERROR_FMT1(thr,err,fmt,arg1) DUK_ERROR((thr),(err),(fmt))
9629 #define DUK_ERROR_RAW_FMT1(thr,file,line,err,fmt,arg1) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
9630 
9631 #define DUK_ERROR_FMT2(thr,err,fmt,arg1,arg2) DUK_ERROR((thr),(err),(fmt))
9632 #define DUK_ERROR_RAW_FMT2(thr,file,line,err,fmt,arg1,arg2) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
9633 
9634 #define DUK_ERROR_FMT3(thr,err,fmt,arg1,arg2,arg3) DUK_ERROR((thr),(err),(fmt))
9635 #define DUK_ERROR_RAW_FMT3(thr,file,line,err,fmt,arg1,arg2,arg3) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
9636 
9637 #define DUK_ERROR_FMT4(thr,err,fmt,arg1,arg2,arg3,arg4) DUK_ERROR((thr),(err),(fmt))
9638 #define DUK_ERROR_RAW_FMT4(thr,file,line,err,fmt,arg1,arg2,arg3,arg4) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
9639 
9640 #endif  /* DUK_USE_VERBOSE_ERRORS */
9641 
9642 /*
9643  *  Fatal error without context
9644  *
9645  *  The macro is an expression to make it compatible with DUK_ASSERT_EXPR().
9646  */
9647 
9648 #define DUK_FATAL_WITHOUT_CONTEXT(msg) \
9649 	duk_default_fatal_handler(NULL, (msg))
9650 
9651 /*
9652  *  Error throwing helpers
9653  *
9654  *  The goal is to provide verbose and configurable error messages.  Call
9655  *  sites should be clean in source code and compile to a small footprint.
9656  *  Small footprint is also useful for performance because small cold paths
9657  *  reduce code cache pressure.  Adding macros here only makes sense if there
9658  *  are enough call sites to get concrete benefits.
9659  *
9660  *  DUK_ERROR_xxx() macros are generic and can be used anywhere.
9661  *
9662  *  DUK_DCERROR_xxx() macros can only be used in Duktape/C functions where
9663  *  the "return DUK_RET_xxx;" shorthand is available for low memory targets.
9664  *  The DUK_DCERROR_xxx() macros always either throw or perform a
9665  *  'return DUK_RET_xxx' from the calling function.
9666  */
9667 
9668 #if defined(DUK_USE_VERBOSE_ERRORS)
9669 /* Verbose errors with key/value summaries (non-paranoid) or without key/value
9670  * summaries (paranoid, for some security sensitive environments), the paranoid
9671  * vs. non-paranoid distinction affects only a few specific errors.
9672  */
9673 #if defined(DUK_USE_PARANOID_ERRORS)
9674 #define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,idx,expectname,lowmemstr) do { \
9675 		duk_err_require_type_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx), (expectname)); \
9676 	} while (0)
9677 #else  /* DUK_USE_PARANOID_ERRORS */
9678 #define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,idx,expectname,lowmemstr) do { \
9679 		duk_err_require_type_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx), (expectname)); \
9680 	} while (0)
9681 #endif  /* DUK_USE_PARANOID_ERRORS */
9682 
9683 #define DUK_ERROR_INTERNAL(thr) do { \
9684 		duk_err_error_internal((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9685 	} while (0)
9686 #define DUK_DCERROR_INTERNAL(thr) do { \
9687 		DUK_ERROR_INTERNAL((thr)); \
9688 		return 0; \
9689 	} while (0)
9690 #define DUK_ERROR_ALLOC_FAILED(thr) do { \
9691 		duk_err_error_alloc_failed((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9692 	} while (0)
9693 #define DUK_ERROR_UNSUPPORTED(thr) do { \
9694 		DUK_ERROR((thr), DUK_ERR_ERROR, DUK_STR_UNSUPPORTED); \
9695 	} while (0)
9696 #define DUK_DCERROR_UNSUPPORTED(thr) do { \
9697 		DUK_ERROR_UNSUPPORTED((thr)); \
9698 		return 0; \
9699 	} while (0)
9700 #define DUK_ERROR_ERROR(thr,msg) do { \
9701 		duk_err_error((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
9702 	} while (0)
9703 #define DUK_ERROR_RANGE_INDEX(thr,idx) do { \
9704 		duk_err_range_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx)); \
9705 	} while (0)
9706 #define DUK_ERROR_RANGE_PUSH_BEYOND(thr) do { \
9707 		duk_err_range_push_beyond((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9708 	} while (0)
9709 #define DUK_ERROR_RANGE_INVALID_ARGS(thr) do { \
9710 		DUK_ERROR_RANGE((thr), DUK_STR_INVALID_ARGS); \
9711 	} while (0)
9712 #define DUK_DCERROR_RANGE_INVALID_ARGS(thr) do { \
9713 		DUK_ERROR_RANGE_INVALID_ARGS((thr)); \
9714 		return 0; \
9715 	} while (0)
9716 #define DUK_ERROR_RANGE_INVALID_COUNT(thr) do { \
9717 		DUK_ERROR_RANGE((thr), DUK_STR_INVALID_COUNT); \
9718 	} while (0)
9719 #define DUK_DCERROR_RANGE_INVALID_COUNT(thr) do { \
9720 		DUK_ERROR_RANGE_INVALID_COUNT((thr)); \
9721 		return 0; \
9722 	} while (0)
9723 #define DUK_ERROR_RANGE_INVALID_LENGTH(thr) do { \
9724 		DUK_ERROR_RANGE((thr), DUK_STR_INVALID_LENGTH); \
9725 	} while (0)
9726 #define DUK_DCERROR_RANGE_INVALID_LENGTH(thr) do { \
9727 		DUK_ERROR_RANGE_INVALID_LENGTH((thr)); \
9728 		return 0; \
9729 	} while (0)
9730 #define DUK_ERROR_RANGE(thr,msg) do { \
9731 		duk_err_range((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
9732 	} while (0)
9733 #define DUK_ERROR_EVAL(thr,msg) do { \
9734 		DUK_ERROR((thr), DUK_ERR_EVAL_ERROR, (msg)); \
9735 	} while (0)
9736 #define DUK_ERROR_REFERENCE(thr,msg) do { \
9737 		DUK_ERROR((thr), DUK_ERR_REFERENCE_ERROR, (msg)); \
9738 	} while (0)
9739 #define DUK_ERROR_SYNTAX(thr,msg) do { \
9740 		DUK_ERROR((thr), DUK_ERR_SYNTAX_ERROR, (msg)); \
9741 	} while (0)
9742 #define DUK_ERROR_TYPE_INVALID_ARGS(thr) do { \
9743 		duk_err_type_invalid_args((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9744 	} while (0)
9745 #define DUK_DCERROR_TYPE_INVALID_ARGS(thr) do { \
9746 		DUK_ERROR_TYPE_INVALID_ARGS((thr)); \
9747 		return 0; \
9748 	} while (0)
9749 #define DUK_ERROR_TYPE_INVALID_STATE(thr) do { \
9750 		duk_err_type_invalid_state((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9751 	} while (0)
9752 #define DUK_DCERROR_TYPE_INVALID_STATE(thr) do { \
9753 		DUK_ERROR_TYPE_INVALID_STATE((thr)); \
9754 		return 0; \
9755 	} while (0)
9756 #define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
9757 		duk_err_type_invalid_trap_result((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9758 	} while (0)
9759 #define DUK_DCERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
9760 		DUK_ERROR_TYPE((thr), DUK_STR_INVALID_TRAP_RESULT); \
9761 	} while (0)
9762 #define DUK_ERROR_TYPE(thr,msg) do { \
9763 		DUK_ERROR((thr), DUK_ERR_TYPE_ERROR, (msg)); \
9764 	} while (0)
9765 #define DUK_ERROR_URI(thr,msg) do { \
9766 		DUK_ERROR((thr), DUK_ERR_URI_ERROR, (msg)); \
9767 	} while (0)
9768 #else  /* DUK_USE_VERBOSE_ERRORS */
9769 /* Non-verbose errors for low memory targets: no file, line, or message. */
9770 
9771 #define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,idx,expectname,lowmemstr) do { \
9772 		duk_err_type((thr)); \
9773 	} while (0)
9774 
9775 #define DUK_ERROR_INTERNAL(thr) do { \
9776 		duk_err_error((thr)); \
9777 	} while (0)
9778 #define DUK_DCERROR_INTERNAL(thr) do { \
9779 		DUK_UNREF((thr)); \
9780 		return DUK_RET_ERROR; \
9781 	} while (0)
9782 #define DUK_ERROR_ALLOC_FAILED(thr) do { \
9783 		duk_err_error((thr)); \
9784 	} while (0)
9785 #define DUK_ERROR_UNSUPPORTED(thr) do { \
9786 		duk_err_error((thr)); \
9787 	} while (0)
9788 #define DUK_DCERROR_UNSUPPORTED(thr) do { \
9789 		DUK_UNREF((thr)); \
9790 		return DUK_RET_ERROR; \
9791 	} while (0)
9792 #define DUK_ERROR_ERROR(thr,msg) do { \
9793 		duk_err_error((thr)); \
9794 	} while (0)
9795 #define DUK_ERROR_RANGE_INDEX(thr,idx) do { \
9796 		duk_err_range((thr)); \
9797 	} while (0)
9798 #define DUK_ERROR_RANGE_PUSH_BEYOND(thr) do { \
9799 		duk_err_range((thr)); \
9800 	} while (0)
9801 #define DUK_ERROR_RANGE_INVALID_ARGS(thr) do { \
9802 		duk_err_range((thr)); \
9803 	} while (0)
9804 #define DUK_DCERROR_RANGE_INVALID_ARGS(thr) do { \
9805 		DUK_UNREF((thr)); \
9806 		return DUK_RET_RANGE_ERROR; \
9807 	} while (0)
9808 #define DUK_ERROR_RANGE_INVALID_COUNT(thr) do { \
9809 		duk_err_range((thr)); \
9810 	} while (0)
9811 #define DUK_DCERROR_RANGE_INVALID_COUNT(thr) do { \
9812 		DUK_UNREF((thr)); \
9813 		return DUK_RET_RANGE_ERROR; \
9814 	} while (0)
9815 #define DUK_ERROR_RANGE_INVALID_LENGTH(thr) do { \
9816 		duk_err_range((thr)); \
9817 	} while (0)
9818 #define DUK_DCERROR_RANGE_INVALID_LENGTH(thr) do { \
9819 		DUK_UNREF((thr)); \
9820 		return DUK_RET_RANGE_ERROR; \
9821 	} while (0)
9822 #define DUK_ERROR_RANGE(thr,msg) do { \
9823 		duk_err_range((thr)); \
9824 	} while (0)
9825 #define DUK_ERROR_EVAL(thr,msg) do { \
9826 		duk_err_eval((thr)); \
9827 	} while (0)
9828 #define DUK_ERROR_REFERENCE(thr,msg) do { \
9829 		duk_err_reference((thr)); \
9830 	} while (0)
9831 #define DUK_ERROR_SYNTAX(thr,msg) do { \
9832 		duk_err_syntax((thr)); \
9833 	} while (0)
9834 #define DUK_ERROR_TYPE_INVALID_ARGS(thr) do { \
9835 		duk_err_type((thr)); \
9836 	} while (0)
9837 #define DUK_DCERROR_TYPE_INVALID_ARGS(thr) do { \
9838 		DUK_UNREF((thr)); \
9839 		return DUK_RET_TYPE_ERROR; \
9840 	} while (0)
9841 #define DUK_ERROR_TYPE_INVALID_STATE(thr) do { \
9842 		duk_err_type((thr)); \
9843 	} while (0)
9844 #define DUK_DCERROR_TYPE_INVALID_STATE(thr) do { \
9845 		duk_err_type((thr)); \
9846 	} while (0)
9847 #define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
9848 		duk_err_type((thr)); \
9849 	} while (0)
9850 #define DUK_DCERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
9851 		DUK_UNREF((thr)); \
9852 		return DUK_RET_TYPE_ERROR; \
9853 	} while (0)
9854 #define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
9855 		duk_err_type((thr)); \
9856 	} while (0)
9857 #define DUK_ERROR_TYPE(thr,msg) do { \
9858 		duk_err_type((thr)); \
9859 	} while (0)
9860 #define DUK_ERROR_URI(thr,msg) do { \
9861 		duk_err_uri((thr)); \
9862 	} while (0)
9863 #endif  /* DUK_USE_VERBOSE_ERRORS */
9864 
9865 /*
9866  *  Assert macro: failure causes a fatal error.
9867  *
9868  *  NOTE: since the assert macro doesn't take a heap/context argument, there's
9869  *  no way to look up a heap/context specific fatal error handler which may have
9870  *  been given by the application.  Instead, assertion failures always use the
9871  *  internal default fatal error handler; it can be replaced via duk_config.h
9872  *  and then applies to all Duktape heaps.
9873  */
9874 
9875 #if defined(DUK_USE_ASSERTIONS)
9876 
9877 /* The message should be a compile time constant without formatting (less risk);
9878  * we don't care about assertion text size because they're not used in production
9879  * builds.
9880  */
9881 #define DUK_ASSERT(x)  do { \
9882 	if (!(x)) { \
9883 		DUK_FATAL_WITHOUT_CONTEXT("assertion failed: " #x \
9884 			" (" DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"); \
9885 	} \
9886 	} while (0)
9887 
9888 /* Assertion compatible inside a comma expression, evaluates to void. */
9889 #define DUK_ASSERT_EXPR(x) \
9890 	((void) ((x) ? 0 : (DUK_FATAL_WITHOUT_CONTEXT("assertion failed: " #x \
9891 				" (" DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"), 0)))
9892 
9893 #else  /* DUK_USE_ASSERTIONS */
9894 
9895 #define DUK_ASSERT(x)  do { /* assertion omitted */ } while (0)
9896 
9897 #define DUK_ASSERT_EXPR(x)  ((void) 0)
9898 
9899 #endif  /* DUK_USE_ASSERTIONS */
9900 
9901 /* this variant is used when an assert would generate a compile warning by
9902  * being always true (e.g. >= 0 comparison for an unsigned value
9903  */
9904 #define DUK_ASSERT_DISABLE(x)  do { /* assertion disabled */ } while (0)
9905 
9906 /*
9907  *  Assertion helpers
9908  */
9909 
9910 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
9911 #define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h)  do { \
9912 		DUK_ASSERT((h) == NULL || DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) (h)) > 0); \
9913 	} while (0)
9914 #define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv)  do { \
9915 		if ((tv) != NULL && DUK_TVAL_IS_HEAP_ALLOCATED((tv))) { \
9916 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(DUK_TVAL_GET_HEAPHDR((tv))) > 0); \
9917 		} \
9918 	} while (0)
9919 #else
9920 #define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h)  /* no refcount check */
9921 #define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv)    /* no refcount check */
9922 #endif
9923 
9924 #define DUK_ASSERT_TOP(ctx,n)  DUK_ASSERT((duk_idx_t) duk_get_top((ctx)) == (duk_idx_t) (n))
9925 
9926 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_PACKED_TVAL)
9927 #define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval)  do { \
9928 		duk_double_union duk__assert_tmp_du; \
9929 		duk__assert_tmp_du.d = (dval); \
9930 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&duk__assert_tmp_du)); \
9931 	} while (0)
9932 #else
9933 #define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval)  /* nop */
9934 #endif
9935 
9936 #define DUK_ASSERT_VS_SPACE(thr) \
9937 	DUK_ASSERT(thr->valstack_top < thr->valstack_end)
9938 
9939 /*
9940  *  Helper to initialize a memory area (e.g. struct) with garbage when
9941  *  assertions enabled.
9942  */
9943 
9944 #if defined(DUK_USE_ASSERTIONS)
9945 #define DUK_ASSERT_SET_GARBAGE(ptr,size) do { \
9946 		duk_memset_unsafe((void *) (ptr), 0x5a, size); \
9947 	} while (0)
9948 #else
9949 #define DUK_ASSERT_SET_GARBAGE(ptr,size) do {} while (0)
9950 #endif
9951 
9952 /*
9953  *  Helper for valstack space
9954  *
9955  *  Caller of DUK_ASSERT_VALSTACK_SPACE() estimates the number of free stack entries
9956  *  required for its own use, and any child calls which are not (a) Duktape API calls
9957  *  or (b) Duktape calls which involve extending the valstack (e.g. getter call).
9958  */
9959 
9960 #define DUK_VALSTACK_ASSERT_EXTRA  5  /* this is added to checks to allow for Duktape
9961                                        * API calls in addition to function's own use
9962                                        */
9963 #if defined(DUK_USE_ASSERTIONS)
9964 #define DUK_ASSERT_VALSTACK_SPACE(thr,n)   do { \
9965 		DUK_ASSERT((thr) != NULL); \
9966 		DUK_ASSERT((thr)->valstack_end - (thr)->valstack_top >= (n) + DUK_VALSTACK_ASSERT_EXTRA); \
9967 	} while (0)
9968 #else
9969 #define DUK_ASSERT_VALSTACK_SPACE(thr,n)   /* no valstack space check */
9970 #endif
9971 
9972 /*
9973  *  Prototypes
9974  */
9975 
9976 #if defined(DUK_USE_VERBOSE_ERRORS)
9977 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *msg));
9978 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error_fmt(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *fmt, ...));
9979 #else  /* DUK_USE_VERBOSE_ERRORS */
9980 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code));
9981 #endif  /* DUK_USE_VERBOSE_ERRORS */
9982 
9983 #if defined(DUK_USE_VERBOSE_ERRORS)
9984 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code, const char *msg, const char *filename, duk_int_t line));
9985 #else
9986 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code));
9987 #endif
9988 
9989 DUK_NORETURN(DUK_INTERNAL_DECL void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc));
9990 
9991 #define DUK_AUGMENT_FLAG_NOBLAME_FILELINE  (1U << 0)  /* if set, don't blame C file/line for .fileName and .lineNumber */
9992 #define DUK_AUGMENT_FLAG_SKIP_ONE          (1U << 1)  /* if set, skip topmost activation in traceback construction */
9993 
9994 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
9995 DUK_INTERNAL_DECL void duk_err_augment_error_create(duk_hthread *thr, duk_hthread *thr_callstack, const char *filename, duk_int_t line, duk_small_uint_t flags);
9996 #endif
9997 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
9998 DUK_INTERNAL_DECL void duk_err_augment_error_throw(duk_hthread *thr);
9999 #endif
10000 
10001 #if defined(DUK_USE_VERBOSE_ERRORS)
10002 #if defined(DUK_USE_PARANOID_ERRORS)
10003 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx, const char *expect_name));
10004 #else
10005 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx, const char *expect_name));
10006 #endif
10007 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber));
10008 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error_alloc_failed(duk_hthread *thr, const char *filename, duk_int_t linenumber));
10009 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
10010 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx));
10011 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range_push_beyond(duk_hthread *thr, const char *filename, duk_int_t linenumber));
10012 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
10013 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_args(duk_hthread *thr, const char *filename, duk_int_t linenumber));
10014 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_state(duk_hthread *thr, const char *filename, duk_int_t linenumber));
10015 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_trap_result(duk_hthread *thr, const char *filename, duk_int_t linenumber));
10016 #else  /* DUK_VERBOSE_ERRORS */
10017 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error(duk_hthread *thr));
10018 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range(duk_hthread *thr));
10019 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_eval(duk_hthread *thr));
10020 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_reference(duk_hthread *thr));
10021 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_syntax(duk_hthread *thr));
10022 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type(duk_hthread *thr));
10023 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_uri(duk_hthread *thr));
10024 #endif /* DUK_VERBOSE_ERRORS */
10025 
10026 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_longjmp(duk_hthread *thr));
10027 
10028 DUK_NORETURN(DUK_INTERNAL_DECL void duk_default_fatal_handler(void *udata, const char *msg));
10029 
10030 DUK_INTERNAL_DECL void duk_err_setup_ljstate1(duk_hthread *thr, duk_small_uint_t lj_type, duk_tval *tv_val);
10031 #if defined(DUK_USE_DEBUGGER_SUPPORT)
10032 DUK_INTERNAL_DECL void duk_err_check_debugger_integration(duk_hthread *thr);
10033 #endif
10034 
10035 DUK_INTERNAL_DECL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t err_code);
10036 
10037 #endif  /* DUK_ERROR_H_INCLUDED */
10038 /* #include duk_unicode.h */
10039 /*
10040  *  Unicode helpers
10041  */
10042 
10043 #if !defined(DUK_UNICODE_H_INCLUDED)
10044 #define DUK_UNICODE_H_INCLUDED
10045 
10046 /*
10047  *  UTF-8 / XUTF-8 / CESU-8 constants
10048  */
10049 
10050 #define DUK_UNICODE_MAX_XUTF8_LENGTH      7   /* up to 36 bit codepoints */
10051 #define DUK_UNICODE_MAX_XUTF8_BMP_LENGTH  3   /* all codepoints up to U+FFFF */
10052 #define DUK_UNICODE_MAX_CESU8_LENGTH      6   /* all codepoints up to U+10FFFF */
10053 #define DUK_UNICODE_MAX_CESU8_BMP_LENGTH  3   /* all codepoints up to U+FFFF */
10054 
10055 /*
10056  *  Useful Unicode codepoints
10057  *
10058  *  Integer constants must be signed to avoid unexpected coercions
10059  *  in comparisons.
10060  */
10061 
10062 #define DUK_UNICODE_CP_ZWNJ                   0x200cL  /* zero-width non-joiner */
10063 #define DUK_UNICODE_CP_ZWJ                    0x200dL  /* zero-width joiner */
10064 #define DUK_UNICODE_CP_REPLACEMENT_CHARACTER  0xfffdL  /* http://en.wikipedia.org/wiki/Replacement_character#Replacement_character */
10065 
10066 /*
10067  *  ASCII character constants
10068  *
10069  *  C character literals like 'x' have a platform specific value and do
10070  *  not match ASCII (UTF-8) values on e.g. EBCDIC platforms.  So, use
10071  *  these (admittedly awkward) constants instead.  These constants must
10072  *  also have signed values to avoid unexpected coercions in comparisons.
10073  *
10074  *  http://en.wikipedia.org/wiki/ASCII
10075  */
10076 
10077 #define DUK_ASC_NUL              0x00
10078 #define DUK_ASC_SOH              0x01
10079 #define DUK_ASC_STX              0x02
10080 #define DUK_ASC_ETX              0x03
10081 #define DUK_ASC_EOT              0x04
10082 #define DUK_ASC_ENQ              0x05
10083 #define DUK_ASC_ACK              0x06
10084 #define DUK_ASC_BEL              0x07
10085 #define DUK_ASC_BS               0x08
10086 #define DUK_ASC_HT               0x09
10087 #define DUK_ASC_LF               0x0a
10088 #define DUK_ASC_VT               0x0b
10089 #define DUK_ASC_FF               0x0c
10090 #define DUK_ASC_CR               0x0d
10091 #define DUK_ASC_SO               0x0e
10092 #define DUK_ASC_SI               0x0f
10093 #define DUK_ASC_DLE              0x10
10094 #define DUK_ASC_DC1              0x11
10095 #define DUK_ASC_DC2              0x12
10096 #define DUK_ASC_DC3              0x13
10097 #define DUK_ASC_DC4              0x14
10098 #define DUK_ASC_NAK              0x15
10099 #define DUK_ASC_SYN              0x16
10100 #define DUK_ASC_ETB              0x17
10101 #define DUK_ASC_CAN              0x18
10102 #define DUK_ASC_EM               0x19
10103 #define DUK_ASC_SUB              0x1a
10104 #define DUK_ASC_ESC              0x1b
10105 #define DUK_ASC_FS               0x1c
10106 #define DUK_ASC_GS               0x1d
10107 #define DUK_ASC_RS               0x1e
10108 #define DUK_ASC_US               0x1f
10109 #define DUK_ASC_SPACE            0x20
10110 #define DUK_ASC_EXCLAMATION      0x21
10111 #define DUK_ASC_DOUBLEQUOTE      0x22
10112 #define DUK_ASC_HASH             0x23
10113 #define DUK_ASC_DOLLAR           0x24
10114 #define DUK_ASC_PERCENT          0x25
10115 #define DUK_ASC_AMP              0x26
10116 #define DUK_ASC_SINGLEQUOTE      0x27
10117 #define DUK_ASC_LPAREN           0x28
10118 #define DUK_ASC_RPAREN           0x29
10119 #define DUK_ASC_STAR             0x2a
10120 #define DUK_ASC_PLUS             0x2b
10121 #define DUK_ASC_COMMA            0x2c
10122 #define DUK_ASC_MINUS            0x2d
10123 #define DUK_ASC_PERIOD           0x2e
10124 #define DUK_ASC_SLASH            0x2f
10125 #define DUK_ASC_0                0x30
10126 #define DUK_ASC_1                0x31
10127 #define DUK_ASC_2                0x32
10128 #define DUK_ASC_3                0x33
10129 #define DUK_ASC_4                0x34
10130 #define DUK_ASC_5                0x35
10131 #define DUK_ASC_6                0x36
10132 #define DUK_ASC_7                0x37
10133 #define DUK_ASC_8                0x38
10134 #define DUK_ASC_9                0x39
10135 #define DUK_ASC_COLON            0x3a
10136 #define DUK_ASC_SEMICOLON        0x3b
10137 #define DUK_ASC_LANGLE           0x3c
10138 #define DUK_ASC_EQUALS           0x3d
10139 #define DUK_ASC_RANGLE           0x3e
10140 #define DUK_ASC_QUESTION         0x3f
10141 #define DUK_ASC_ATSIGN           0x40
10142 #define DUK_ASC_UC_A             0x41
10143 #define DUK_ASC_UC_B             0x42
10144 #define DUK_ASC_UC_C             0x43
10145 #define DUK_ASC_UC_D             0x44
10146 #define DUK_ASC_UC_E             0x45
10147 #define DUK_ASC_UC_F             0x46
10148 #define DUK_ASC_UC_G             0x47
10149 #define DUK_ASC_UC_H             0x48
10150 #define DUK_ASC_UC_I             0x49
10151 #define DUK_ASC_UC_J             0x4a
10152 #define DUK_ASC_UC_K             0x4b
10153 #define DUK_ASC_UC_L             0x4c
10154 #define DUK_ASC_UC_M             0x4d
10155 #define DUK_ASC_UC_N             0x4e
10156 #define DUK_ASC_UC_O             0x4f
10157 #define DUK_ASC_UC_P             0x50
10158 #define DUK_ASC_UC_Q             0x51
10159 #define DUK_ASC_UC_R             0x52
10160 #define DUK_ASC_UC_S             0x53
10161 #define DUK_ASC_UC_T             0x54
10162 #define DUK_ASC_UC_U             0x55
10163 #define DUK_ASC_UC_V             0x56
10164 #define DUK_ASC_UC_W             0x57
10165 #define DUK_ASC_UC_X             0x58
10166 #define DUK_ASC_UC_Y             0x59
10167 #define DUK_ASC_UC_Z             0x5a
10168 #define DUK_ASC_LBRACKET         0x5b
10169 #define DUK_ASC_BACKSLASH        0x5c
10170 #define DUK_ASC_RBRACKET         0x5d
10171 #define DUK_ASC_CARET            0x5e
10172 #define DUK_ASC_UNDERSCORE       0x5f
10173 #define DUK_ASC_GRAVE            0x60
10174 #define DUK_ASC_LC_A             0x61
10175 #define DUK_ASC_LC_B             0x62
10176 #define DUK_ASC_LC_C             0x63
10177 #define DUK_ASC_LC_D             0x64
10178 #define DUK_ASC_LC_E             0x65
10179 #define DUK_ASC_LC_F             0x66
10180 #define DUK_ASC_LC_G             0x67
10181 #define DUK_ASC_LC_H             0x68
10182 #define DUK_ASC_LC_I             0x69
10183 #define DUK_ASC_LC_J             0x6a
10184 #define DUK_ASC_LC_K             0x6b
10185 #define DUK_ASC_LC_L             0x6c
10186 #define DUK_ASC_LC_M             0x6d
10187 #define DUK_ASC_LC_N             0x6e
10188 #define DUK_ASC_LC_O             0x6f
10189 #define DUK_ASC_LC_P             0x70
10190 #define DUK_ASC_LC_Q             0x71
10191 #define DUK_ASC_LC_R             0x72
10192 #define DUK_ASC_LC_S             0x73
10193 #define DUK_ASC_LC_T             0x74
10194 #define DUK_ASC_LC_U             0x75
10195 #define DUK_ASC_LC_V             0x76
10196 #define DUK_ASC_LC_W             0x77
10197 #define DUK_ASC_LC_X             0x78
10198 #define DUK_ASC_LC_Y             0x79
10199 #define DUK_ASC_LC_Z             0x7a
10200 #define DUK_ASC_LCURLY           0x7b
10201 #define DUK_ASC_PIPE             0x7c
10202 #define DUK_ASC_RCURLY           0x7d
10203 #define DUK_ASC_TILDE            0x7e
10204 #define DUK_ASC_DEL              0x7f
10205 
10206 /*
10207  *  Miscellaneous
10208  */
10209 
10210 /* Uppercase A is 0x41, lowercase a is 0x61; OR 0x20 to convert uppercase
10211  * to lowercase.
10212  */
10213 #define DUK_LOWERCASE_CHAR_ASCII(x)  ((x) | 0x20)
10214 
10215 /*
10216  *  Unicode tables
10217  */
10218 
10219 #if defined(DUK_USE_SOURCE_NONBMP)
10220 /*
10221  *  Automatically generated by extract_chars.py, do not edit!
10222  */
10223 
10224 extern const duk_uint8_t duk_unicode_ids_noa[1116];
10225 #else
10226 /*
10227  *  Automatically generated by extract_chars.py, do not edit!
10228  */
10229 
10230 extern const duk_uint8_t duk_unicode_ids_noabmp[625];
10231 #endif
10232 
10233 #if defined(DUK_USE_SOURCE_NONBMP)
10234 /*
10235  *  Automatically generated by extract_chars.py, do not edit!
10236  */
10237 
10238 extern const duk_uint8_t duk_unicode_ids_m_let_noa[42];
10239 #else
10240 /*
10241  *  Automatically generated by extract_chars.py, do not edit!
10242  */
10243 
10244 extern const duk_uint8_t duk_unicode_ids_m_let_noabmp[24];
10245 #endif
10246 
10247 #if defined(DUK_USE_SOURCE_NONBMP)
10248 /*
10249  *  Automatically generated by extract_chars.py, do not edit!
10250  */
10251 
10252 extern const duk_uint8_t duk_unicode_idp_m_ids_noa[576];
10253 #else
10254 /*
10255  *  Automatically generated by extract_chars.py, do not edit!
10256  */
10257 
10258 extern const duk_uint8_t duk_unicode_idp_m_ids_noabmp[358];
10259 #endif
10260 
10261 /*
10262  *  Automatically generated by extract_caseconv.py, do not edit!
10263  */
10264 
10265 extern const duk_uint8_t duk_unicode_caseconv_uc[1411];
10266 extern const duk_uint8_t duk_unicode_caseconv_lc[706];
10267 
10268 #if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
10269 /*
10270  *  Automatically generated by extract_caseconv.py, do not edit!
10271  */
10272 
10273 extern const duk_uint16_t duk_unicode_re_canon_lookup[65536];
10274 #endif
10275 
10276 #if defined(DUK_USE_REGEXP_CANON_BITMAP)
10277 /*
10278  *  Automatically generated by extract_caseconv.py, do not edit!
10279  */
10280 
10281 #define DUK_CANON_BITMAP_BLKSIZE                                      32
10282 #define DUK_CANON_BITMAP_BLKSHIFT                                     5
10283 #define DUK_CANON_BITMAP_BLKMASK                                      31
10284 extern const duk_uint8_t duk_unicode_re_canon_bitmap[256];
10285 #endif
10286 
10287 /*
10288  *  Extern
10289  */
10290 
10291 /* duk_unicode_support.c */
10292 #if !defined(DUK_SINGLE_FILE)
10293 DUK_INTERNAL_DECL const duk_uint8_t duk_unicode_xutf8_markers[7];
10294 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_digit[2];
10295 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_white[22];
10296 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_wordchar[8];
10297 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_digit[4];
10298 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_white[24];
10299 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_wordchar[10];
10300 DUK_INTERNAL_DECL const duk_int8_t duk_is_idchar_tab[128];
10301 #endif  /* !DUK_SINGLE_FILE */
10302 
10303 /*
10304  *  Prototypes
10305  */
10306 
10307 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_xutf8_length(duk_ucodepoint_t cp);
10308 #if defined(DUK_USE_ASSERTIONS)
10309 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp);
10310 #endif
10311 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_uint8_t *out);
10312 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_uint8_t *out);
10313 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_decode_xutf8(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end, duk_ucodepoint_t *out_cp);
10314 DUK_INTERNAL_DECL duk_ucodepoint_t duk_unicode_decode_xutf8_checked(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end);
10315 DUK_INTERNAL_DECL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen);
10316 DUK_INTERNAL_DECL duk_bool_t duk_unicode_is_utf8_compatible(const duk_uint8_t *buf, duk_size_t len);
10317 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp);
10318 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp);
10319 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp);
10320 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_part(duk_codepoint_t cp);
10321 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp);
10322 DUK_INTERNAL_DECL void duk_unicode_case_convert_string(duk_hthread *thr, duk_bool_t uppercase);
10323 #if defined(DUK_USE_REGEXP_SUPPORT)
10324 DUK_INTERNAL_DECL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr, duk_codepoint_t cp);
10325 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t cp);
10326 #endif
10327 
10328 #endif  /* DUK_UNICODE_H_INCLUDED */
10329 /* #include duk_json.h */
10330 /*
10331  *  Defines for JSON, especially duk_bi_json.c.
10332  */
10333 
10334 #if !defined(DUK_JSON_H_INCLUDED)
10335 #define DUK_JSON_H_INCLUDED
10336 
10337 /* Encoding/decoding flags */
10338 #define DUK_JSON_FLAG_ASCII_ONLY              (1U << 0)  /* escape any non-ASCII characters */
10339 #define DUK_JSON_FLAG_AVOID_KEY_QUOTES        (1U << 1)  /* avoid key quotes when key is an ASCII Identifier */
10340 #define DUK_JSON_FLAG_EXT_CUSTOM              (1U << 2)  /* extended types: custom encoding */
10341 #define DUK_JSON_FLAG_EXT_COMPATIBLE          (1U << 3)  /* extended types: compatible encoding */
10342 
10343 /* How much stack to require on entry to object/array encode */
10344 #define DUK_JSON_ENC_REQSTACK                 32
10345 
10346 /* How much stack to require on entry to object/array decode */
10347 #define DUK_JSON_DEC_REQSTACK                 32
10348 
10349 /* How large a loop detection stack to use */
10350 #define DUK_JSON_ENC_LOOPARRAY                64
10351 
10352 /* Encoding state.  Heap object references are all borrowed. */
10353 typedef struct {
10354 	duk_hthread *thr;
10355 	duk_bufwriter_ctx bw;        /* output bufwriter */
10356 	duk_hobject *h_replacer;     /* replacer function */
10357 	duk_hstring *h_gap;          /* gap (if empty string, NULL) */
10358 	duk_idx_t idx_proplist;      /* explicit PropertyList */
10359 	duk_idx_t idx_loop;          /* valstack index of loop detection object */
10360 	duk_small_uint_t flags;
10361 	duk_small_uint_t flag_ascii_only;
10362 	duk_small_uint_t flag_avoid_key_quotes;
10363 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
10364 	duk_small_uint_t flag_ext_custom;
10365 	duk_small_uint_t flag_ext_compatible;
10366 	duk_small_uint_t flag_ext_custom_or_compatible;
10367 #endif
10368 	duk_uint_t recursion_depth;
10369 	duk_uint_t recursion_limit;
10370 	duk_uint_t mask_for_undefined;      /* type bit mask: types which certainly produce 'undefined' */
10371 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
10372 	duk_small_uint_t stridx_custom_undefined;
10373 	duk_small_uint_t stridx_custom_nan;
10374 	duk_small_uint_t stridx_custom_neginf;
10375 	duk_small_uint_t stridx_custom_posinf;
10376 	duk_small_uint_t stridx_custom_function;
10377 #endif
10378 	duk_hobject *visiting[DUK_JSON_ENC_LOOPARRAY];  /* indexed by recursion_depth */
10379 } duk_json_enc_ctx;
10380 
10381 typedef struct {
10382 	duk_hthread *thr;
10383 	const duk_uint8_t *p;
10384 	const duk_uint8_t *p_start;
10385 	const duk_uint8_t *p_end;
10386 	duk_idx_t idx_reviver;
10387 	duk_small_uint_t flags;
10388 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
10389 	duk_small_uint_t flag_ext_custom;
10390 	duk_small_uint_t flag_ext_compatible;
10391 	duk_small_uint_t flag_ext_custom_or_compatible;
10392 #endif
10393 	duk_int_t recursion_depth;
10394 	duk_int_t recursion_limit;
10395 } duk_json_dec_ctx;
10396 
10397 #endif  /* DUK_JSON_H_INCLUDED */
10398 /* #include duk_js.h */
10399 /*
10400  *  ECMAScript execution, support primitives.
10401  */
10402 
10403 #if !defined(DUK_JS_H_INCLUDED)
10404 #define DUK_JS_H_INCLUDED
10405 
10406 /* Flags for call handling.  Lowest flags must match bytecode DUK_BC_CALL_FLAG_xxx 1:1. */
10407 #define DUK_CALL_FLAG_TAILCALL                 (1U << 0)  /* setup for a tail call */
10408 #define DUK_CALL_FLAG_CONSTRUCT                (1U << 1)  /* constructor call (i.e. called as 'new Foo()') */
10409 #define DUK_CALL_FLAG_CALLED_AS_EVAL           (1U << 2)  /* call was made using the identifier 'eval' */
10410 #define DUK_CALL_FLAG_ALLOW_ECMATOECMA         (1U << 3)  /* ecma-to-ecma call with executor reuse is possible */
10411 #define DUK_CALL_FLAG_DIRECT_EVAL              (1U << 4)  /* call is a direct eval call */
10412 #define DUK_CALL_FLAG_CONSTRUCT_PROXY          (1U << 5)  /* handled via 'construct' proxy trap, check return value invariant(s) */
10413 #define DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED (1U << 6)  /* prototype of 'default instance' updated, temporary flag in call handling */
10414 
10415 /* Flags for duk_js_equals_helper(). */
10416 #define DUK_EQUALS_FLAG_SAMEVALUE            (1U << 0)  /* use SameValue instead of non-strict equality */
10417 #define DUK_EQUALS_FLAG_STRICT               (1U << 1)  /* use strict equality instead of non-strict equality */
10418 
10419 /* Flags for duk_js_compare_helper(). */
10420 #define DUK_COMPARE_FLAG_NEGATE              (1U << 0)  /* negate result */
10421 #define DUK_COMPARE_FLAG_EVAL_LEFT_FIRST     (1U << 1)  /* eval left argument first */
10422 
10423 /* conversions, coercions, comparison, etc */
10424 DUK_INTERNAL_DECL duk_bool_t duk_js_toboolean(duk_tval *tv);
10425 DUK_INTERNAL_DECL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv);
10426 DUK_INTERNAL_DECL duk_double_t duk_js_tointeger_number(duk_double_t x);
10427 DUK_INTERNAL_DECL duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv);
10428 DUK_INTERNAL_DECL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv);
10429 DUK_INTERNAL_DECL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv);
10430 DUK_INTERNAL_DECL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv);
10431 DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_string(const duk_uint8_t *str, duk_uint32_t blen);
10432 #if !defined(DUK_USE_HSTRING_ARRIDX)
10433 DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_hstring_fast_known(duk_hstring *h);
10434 DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_hstring_fast(duk_hstring *h);
10435 #endif
10436 DUK_INTERNAL_DECL duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_t flags);
10437 DUK_INTERNAL_DECL duk_small_int_t duk_js_data_compare(const duk_uint8_t *buf1, const duk_uint8_t *buf2, duk_size_t len1, duk_size_t len2);
10438 DUK_INTERNAL_DECL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2);
10439 #if 0  /* unused */
10440 DUK_INTERNAL_DECL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2);
10441 #endif
10442 DUK_INTERNAL_DECL duk_bool_t duk_js_compare_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_t flags);
10443 DUK_INTERNAL_DECL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
10444 #if defined(DUK_USE_SYMBOL_BUILTIN)
10445 DUK_INTERNAL_DECL duk_bool_t duk_js_instanceof_ordinary(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
10446 #endif
10447 DUK_INTERNAL_DECL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
10448 DUK_INTERNAL_DECL duk_small_uint_t duk_js_typeof_stridx(duk_tval *tv_x);
10449 DUK_INTERNAL_DECL duk_bool_t duk_js_isarray_hobject(duk_hobject *h);
10450 DUK_INTERNAL_DECL duk_bool_t duk_js_isarray(duk_tval *tv);
10451 
10452 /* arithmetic */
10453 DUK_INTERNAL_DECL double duk_js_arith_pow(double x, double y);
10454 DUK_INTERNAL_DECL double duk_js_arith_mod(double x, double y);
10455 
10456 #define duk_js_equals(thr,tv_x,tv_y) \
10457 	duk_js_equals_helper((thr), (tv_x), (tv_y), 0)
10458 #define duk_js_strict_equals(tv_x,tv_y) \
10459 	duk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_STRICT)
10460 #define duk_js_samevalue(tv_x,tv_y) \
10461 	duk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_SAMEVALUE)
10462 
10463 /* E5 Sections 11.8.1, 11.8.5; x < y */
10464 #define duk_js_lessthan(thr,tv_x,tv_y) \
10465 	duk_js_compare_helper((thr), (tv_x), (tv_Y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST)
10466 
10467 /* E5 Sections 11.8.2, 11.8.5; x > y  -->  y < x */
10468 #define duk_js_greaterthan(thr,tv_x,tv_y) \
10469 	duk_js_compare_helper((thr), (tv_y), (tv_x), 0)
10470 
10471 /* E5 Sections 11.8.3, 11.8.5; x <= y  -->  not (x > y)  -->  not (y < x) */
10472 #define duk_js_lessthanorequal(thr,tv_x,tv_y) \
10473 	duk_js_compare_helper((thr), (tv_y), (tv_x), DUK_COMPARE_FLAG_NEGATE)
10474 
10475 /* E5 Sections 11.8.4, 11.8.5; x >= y  -->  not (x < y) */
10476 #define duk_js_greaterthanorequal(thr,tv_x,tv_y) \
10477 	duk_js_compare_helper((thr), (tv_x), (tv_y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST | DUK_COMPARE_FLAG_NEGATE)
10478 
10479 /* identifiers and environment handling */
10480 #if 0  /*unused*/
10481 DUK_INTERNAL duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);
10482 #endif
10483 DUK_INTERNAL_DECL duk_bool_t duk_js_getvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_bool_t throw_flag);
10484 DUK_INTERNAL_DECL duk_bool_t duk_js_getvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_bool_t throw_flag);
10485 DUK_INTERNAL_DECL void duk_js_putvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_tval *val, duk_bool_t strict);
10486 DUK_INTERNAL_DECL void duk_js_putvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_tval *val, duk_bool_t strict);
10487 #if 0  /*unused*/
10488 DUK_INTERNAL_DECL duk_bool_t duk_js_delvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);
10489 #endif
10490 DUK_INTERNAL_DECL duk_bool_t duk_js_delvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name);
10491 DUK_INTERNAL_DECL duk_bool_t duk_js_declvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_tval *val, duk_small_uint_t prop_flags, duk_bool_t is_func_decl);
10492 DUK_INTERNAL_DECL void duk_js_init_activation_environment_records_delayed(duk_hthread *thr, duk_activation *act);
10493 DUK_INTERNAL_DECL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env);
10494 DUK_INTERNAL_DECL duk_hobject *duk_create_activation_environment_record(duk_hthread *thr, duk_hobject *func, duk_size_t bottom_byteoff);
10495 DUK_INTERNAL_DECL void duk_js_push_closure(duk_hthread *thr,
10496                                            duk_hcompfunc *fun_temp,
10497                                            duk_hobject *outer_var_env,
10498                                            duk_hobject *outer_lex_env,
10499                                            duk_bool_t add_auto_proto);
10500 
10501 /* call handling */
10502 DUK_INTERNAL_DECL void duk_native_stack_check(duk_hthread *thr);
10503 DUK_INTERNAL_DECL duk_int_t duk_handle_call_unprotected(duk_hthread *thr, duk_idx_t idx_func, duk_small_uint_t call_flags);
10504 DUK_INTERNAL_DECL duk_int_t duk_handle_call_unprotected_nargs(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags);
10505 DUK_INTERNAL_DECL duk_int_t duk_handle_safe_call(duk_hthread *thr, duk_safe_call_function func, void *udata, duk_idx_t num_stack_args, duk_idx_t num_stack_res);
10506 DUK_INTERNAL_DECL void duk_call_construct_postprocess(duk_hthread *thr, duk_small_uint_t proxy_invariant);
10507 #if defined(DUK_USE_VERBOSE_ERRORS)
10508 DUK_INTERNAL_DECL void duk_call_setup_propcall_error(duk_hthread *thr, duk_tval *tv_base, duk_tval *tv_key);
10509 #endif
10510 
10511 /* bytecode execution */
10512 DUK_INTERNAL_DECL void duk_js_execute_bytecode(duk_hthread *exec_thr);
10513 
10514 #endif  /* DUK_JS_H_INCLUDED */
10515 /* #include duk_numconv.h */
10516 /*
10517  *  Number-to-string conversion.  The semantics of these is very tightly
10518  *  bound with the ECMAScript semantics required for call sites.
10519  */
10520 
10521 #if !defined(DUK_NUMCONV_H_INCLUDED)
10522 #define DUK_NUMCONV_H_INCLUDED
10523 
10524 /* Output a specified number of digits instead of using the shortest
10525  * form.  Used for toPrecision() and toFixed().
10526  */
10527 #define DUK_N2S_FLAG_FIXED_FORMAT         (1U << 0)
10528 
10529 /* Force exponential format.  Used for toExponential(). */
10530 #define DUK_N2S_FLAG_FORCE_EXP            (1U << 1)
10531 
10532 /* If number would need zero padding (for whole number part), use
10533  * exponential format instead.  E.g. if input number is 12300, 3
10534  * digits are generated ("123"), output "1.23e+4" instead of "12300".
10535  * Used for toPrecision().
10536  */
10537 #define DUK_N2S_FLAG_NO_ZERO_PAD          (1U << 2)
10538 
10539 /* Digit count indicates number of fractions (i.e. an absolute
10540  * digit index instead of a relative one).  Used together with
10541  * DUK_N2S_FLAG_FIXED_FORMAT for toFixed().
10542  */
10543 #define DUK_N2S_FLAG_FRACTION_DIGITS      (1U << 3)
10544 
10545 /*
10546  *  String-to-number conversion
10547  */
10548 
10549 /* Maximum exponent value when parsing numbers.  This is not strictly
10550  * compliant as there should be no upper limit, but as we parse the
10551  * exponent without a bigint, impose some limit.  The limit should be
10552  * small enough that multiplying it (or limit-1 to be precise) won't
10553  * overflow signed 32-bit integer range.  Exponent is only parsed with
10554  * radix 10, but with maximum radix (36) a safe limit is:
10555  * (10000000*36).toString(16) -> '15752a00'
10556  */
10557 #define DUK_S2N_MAX_EXPONENT              10000000L
10558 
10559 /* Trim white space (= allow leading and trailing whitespace) */
10560 #define DUK_S2N_FLAG_TRIM_WHITE           (1U << 0)
10561 
10562 /* Allow exponent */
10563 #define DUK_S2N_FLAG_ALLOW_EXP            (1U << 1)
10564 
10565 /* Allow trailing garbage (e.g. treat "123foo" as "123) */
10566 #define DUK_S2N_FLAG_ALLOW_GARBAGE        (1U << 2)
10567 
10568 /* Allow leading plus sign */
10569 #define DUK_S2N_FLAG_ALLOW_PLUS           (1U << 3)
10570 
10571 /* Allow leading minus sign */
10572 #define DUK_S2N_FLAG_ALLOW_MINUS          (1U << 4)
10573 
10574 /* Allow 'Infinity' */
10575 #define DUK_S2N_FLAG_ALLOW_INF            (1U << 5)
10576 
10577 /* Allow fraction part */
10578 #define DUK_S2N_FLAG_ALLOW_FRAC           (1U << 6)
10579 
10580 /* Allow naked fraction (e.g. ".123") */
10581 #define DUK_S2N_FLAG_ALLOW_NAKED_FRAC     (1U << 7)
10582 
10583 /* Allow empty fraction (e.g. "123.") */
10584 #define DUK_S2N_FLAG_ALLOW_EMPTY_FRAC     (1U << 8)
10585 
10586 /* Allow empty string to be interpreted as 0 */
10587 #define DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO  (1U << 9)
10588 
10589 /* Allow leading zeroes (e.g. "0123" -> "123") */
10590 #define DUK_S2N_FLAG_ALLOW_LEADING_ZERO   (1U << 10)
10591 
10592 /* Allow automatic detection of hex base ("0x" or "0X" prefix),
10593  * overrides radix argument and forces integer mode.
10594  */
10595 #define DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT   (1U << 11)
10596 
10597 /* Allow automatic detection of legacy octal base ("0n"),
10598  * overrides radix argument and forces integer mode.
10599  */
10600 #define DUK_S2N_FLAG_ALLOW_AUTO_LEGACY_OCT_INT   (1U << 12)
10601 
10602 /* Allow automatic detection of ES2015 octal base ("0o123"),
10603  * overrides radix argument and forces integer mode.
10604  */
10605 #define DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT   (1U << 13)
10606 
10607 /* Allow automatic detection of ES2015 binary base ("0b10001"),
10608  * overrides radix argument and forces integer mode.
10609  */
10610 #define DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT   (1U << 14)
10611 
10612 /*
10613  *  Prototypes
10614  */
10615 
10616 DUK_INTERNAL_DECL void duk_numconv_stringify(duk_hthread *thr, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags);
10617 DUK_INTERNAL_DECL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk_small_uint_t flags);
10618 
10619 #endif  /* DUK_NUMCONV_H_INCLUDED */
10620 /* #include duk_bi_protos.h */
10621 /*
10622  *  Prototypes for built-in functions not automatically covered by the
10623  *  header declarations emitted by genbuiltins.py.
10624  */
10625 
10626 #if !defined(DUK_BUILTIN_PROTOS_H_INCLUDED)
10627 #define DUK_BUILTIN_PROTOS_H_INCLUDED
10628 
10629 /* Buffer size needed for ISO 8601 formatting.
10630  * Accurate value is 32 + 1 for NUL termination:
10631  *   >>> len('+123456-01-23T12:34:56.123+12:34')
10632  *   32
10633  * Include additional space to be safe.
10634  */
10635 #define  DUK_BI_DATE_ISO8601_BUFSIZE  40
10636 
10637 /* Helpers exposed for internal use */
10638 DUK_INTERNAL_DECL void duk_bi_date_timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_double_t *dparts, duk_small_uint_t flags);
10639 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags);
10640 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_is_leap_year(duk_int_t year);
10641 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_valid_range(duk_double_t x);
10642 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_year_in_valid_range(duk_double_t year);
10643 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_leeway_range(duk_double_t x);
10644 /* Built-in providers */
10645 #if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
10646 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_gettimeofday(void);
10647 #endif
10648 #if defined(DUK_USE_DATE_NOW_TIME)
10649 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_time(void);
10650 #endif
10651 #if defined(DUK_USE_DATE_NOW_WINDOWS)
10652 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_windows(void);
10653 #endif
10654 #if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS)
10655 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_windows_subms(void);
10656 #endif
10657 #if defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME_S) || defined(DUK_USE_DATE_TZO_GMTIME)
10658 DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d);
10659 #endif
10660 #if defined(DUK_USE_DATE_TZO_WINDOWS)
10661 DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d);
10662 #endif
10663 #if defined(DUK_USE_DATE_TZO_WINDOWS_NO_DST)
10664 DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows_no_dst(duk_double_t d);
10665 #endif
10666 #if defined(DUK_USE_DATE_PRS_STRPTIME)
10667 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_strptime(duk_hthread *thr, const char *str);
10668 #endif
10669 #if defined(DUK_USE_DATE_PRS_GETDATE)
10670 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_getdate(duk_hthread *thr, const char *str);
10671 #endif
10672 #if defined(DUK_USE_DATE_FMT_STRFTIME)
10673 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_format_parts_strftime(duk_hthread *thr, duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags);
10674 #endif
10675 
10676 #if defined(DUK_USE_GET_MONOTONIC_TIME_CLOCK_GETTIME)
10677 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_monotonic_time_clock_gettime(void);
10678 #endif
10679 #if defined(DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC)
10680 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_monotonic_time_windows_qpc(void);
10681 #endif
10682 
10683 DUK_INTERNAL_DECL
10684 void duk_bi_json_parse_helper(duk_hthread *thr,
10685                               duk_idx_t idx_value,
10686                               duk_idx_t idx_reviver,
10687                               duk_small_uint_t flags);
10688 DUK_INTERNAL_DECL
10689 void duk_bi_json_stringify_helper(duk_hthread *thr,
10690                                   duk_idx_t idx_value,
10691                                   duk_idx_t idx_replacer,
10692                                   duk_idx_t idx_space,
10693                                   duk_small_uint_t flags);
10694 
10695 DUK_INTERNAL_DECL duk_ret_t duk_textdecoder_decode_utf8_nodejs(duk_hthread *thr);
10696 
10697 #if defined(DUK_USE_ES6_PROXY)
10698 DUK_INTERNAL_DECL void duk_proxy_ownkeys_postprocess(duk_hthread *thr, duk_hobject *h_proxy_target, duk_uint_t flags);
10699 #endif
10700 
10701 #endif  /* DUK_BUILTIN_PROTOS_H_INCLUDED */
10702 /* #include duk_selftest.h */
10703 /*
10704  *  Selftest code
10705  */
10706 
10707 #if !defined(DUK_SELFTEST_H_INCLUDED)
10708 #define DUK_SELFTEST_H_INCLUDED
10709 
10710 #if defined(DUK_USE_SELF_TESTS)
10711 DUK_INTERNAL_DECL duk_uint_t duk_selftest_run_tests(duk_alloc_function alloc_func,
10712                                                     duk_realloc_function realloc_func,
10713                                                     duk_free_function free_func,
10714                                                     void *udata);
10715 #endif
10716 
10717 #endif  /* DUK_SELFTEST_H_INCLUDED */
10718 
10719 #endif  /* DUK_INTERNAL_H_INCLUDED */
10720 
10721 #if defined(DUK_USE_COMPUTED_NAN)
10722 DUK_INTERNAL double duk_computed_nan;
10723 #endif
10724 
10725 #if defined(DUK_USE_COMPUTED_INFINITY)
10726 DUK_INTERNAL double duk_computed_infinity;
10727 #endif
10728 
10729 #if defined(DUK_USE_REPL_FPCLASSIFY)
duk_repl_fpclassify(double x)10730 DUK_INTERNAL int duk_repl_fpclassify(double x) {
10731 	duk_double_union u;
10732 	duk_uint_fast16_t expt;
10733 	duk_small_int_t mzero;
10734 
10735 	u.d = x;
10736 	expt = (duk_uint_fast16_t) (u.us[DUK_DBL_IDX_US0] & 0x7ff0UL);
10737 	if (expt > 0x0000UL && expt < 0x7ff0UL) {
10738 		/* expt values [0x001,0x7fe] = normal */
10739 		return DUK_FP_NORMAL;
10740 	}
10741 
10742 	mzero = (u.ui[DUK_DBL_IDX_UI1] == 0 && (u.ui[DUK_DBL_IDX_UI0] & 0x000fffffUL) == 0);
10743 	if (expt == 0x0000UL) {
10744 		/* expt 0x000 is zero/subnormal */
10745 		if (mzero) {
10746 			return DUK_FP_ZERO;
10747 		} else {
10748 			return DUK_FP_SUBNORMAL;
10749 		}
10750 	} else {
10751 		/* expt 0xfff is infinite/nan */
10752 		if (mzero) {
10753 			return DUK_FP_INFINITE;
10754 		} else {
10755 			return DUK_FP_NAN;
10756 		}
10757 	}
10758 }
10759 #endif
10760 
10761 #if defined(DUK_USE_REPL_SIGNBIT)
duk_repl_signbit(double x)10762 DUK_INTERNAL int duk_repl_signbit(double x) {
10763 	duk_double_union u;
10764 	u.d = x;
10765 	return (int) (u.uc[DUK_DBL_IDX_UC0] & 0x80UL);
10766 }
10767 #endif
10768 
10769 #if defined(DUK_USE_REPL_ISFINITE)
duk_repl_isfinite(double x)10770 DUK_INTERNAL int duk_repl_isfinite(double x) {
10771 	int c = DUK_FPCLASSIFY(x);
10772 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
10773 		return 0;
10774 	} else {
10775 		return 1;
10776 	}
10777 }
10778 #endif
10779 
10780 #if defined(DUK_USE_REPL_ISNAN)
duk_repl_isnan(double x)10781 DUK_INTERNAL int duk_repl_isnan(double x) {
10782 	int c = DUK_FPCLASSIFY(x);
10783 	return (c == DUK_FP_NAN);
10784 }
10785 #endif
10786 
10787 #if defined(DUK_USE_REPL_ISINF)
duk_repl_isinf(double x)10788 DUK_INTERNAL int duk_repl_isinf(double x) {
10789 	int c = DUK_FPCLASSIFY(x);
10790 	return (c == DUK_FP_INFINITE);
10791 }
10792 #endif
10793 /*
10794  *  Debugging macro calls.
10795  */
10796 
10797 /* #include duk_internal.h -> already included */
10798 
10799 #if defined(DUK_USE_DEBUG)
10800 
10801 /*
10802  *  Debugging enabled
10803  */
10804 
10805 #include <stdio.h>
10806 #include <stdlib.h>
10807 #include <stdarg.h>
10808 
10809 #if !defined(DUK_USE_DEBUG_WRITE)
10810 #error debugging enabled (DUK_USE_DEBUG) but DUK_USE_DEBUG_WRITE not defined
10811 #endif
10812 
10813 #define DUK__DEBUG_BUFSIZE  DUK_USE_DEBUG_BUFSIZE
10814 
10815 #if defined(DUK_USE_VARIADIC_MACROS)
10816 
duk_debug_log(duk_int_t level,const char * file,duk_int_t line,const char * func,const char * fmt,...)10817 DUK_INTERNAL void duk_debug_log(duk_int_t level, const char *file, duk_int_t line, const char *func, const char *fmt, ...) {
10818 	va_list ap;
10819 	long arg_level;
10820 	const char *arg_file;
10821 	long arg_line;
10822 	const char *arg_func;
10823 	const char *arg_msg;
10824 	char buf[DUK__DEBUG_BUFSIZE];
10825 
10826 	va_start(ap, fmt);
10827 
10828 	duk_memzero((void *) buf, (size_t) DUK__DEBUG_BUFSIZE);
10829 	duk_debug_vsnprintf(buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
10830 
10831 	arg_level = (long) level;
10832 	arg_file = (const char *) file;
10833 	arg_line = (long) line;
10834 	arg_func = (const char *) func;
10835 	arg_msg = (const char *) buf;
10836 	DUK_USE_DEBUG_WRITE(arg_level, arg_file, arg_line, arg_func, arg_msg);
10837 
10838 	va_end(ap);
10839 }
10840 
10841 #else  /* DUK_USE_VARIADIC_MACROS */
10842 
10843 DUK_INTERNAL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
10844 DUK_INTERNAL duk_int_t duk_debug_line_stash;
10845 DUK_INTERNAL char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];
10846 DUK_INTERNAL duk_int_t duk_debug_level_stash;
10847 
duk_debug_log(const char * fmt,...)10848 DUK_INTERNAL void duk_debug_log(const char *fmt, ...) {
10849 	va_list ap;
10850 	long arg_level;
10851 	const char *arg_file;
10852 	long arg_line;
10853 	const char *arg_func;
10854 	const char *arg_msg;
10855 	char buf[DUK__DEBUG_BUFSIZE];
10856 
10857 	va_start(ap, fmt);
10858 
10859 	duk_memzero((void *) buf, (size_t) DUK__DEBUG_BUFSIZE);
10860 	duk_debug_vsnprintf(buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
10861 
10862 	arg_level = (long) duk_debug_level_stash;
10863 	arg_file = (const char *) duk_debug_file_stash;
10864 	arg_line = (long) duk_debug_line_stash;
10865 	arg_func = (const char *) duk_debug_func_stash;
10866 	arg_msg = (const char *) buf;
10867 	DUK_USE_DEBUG_WRITE(arg_level, arg_file, arg_line, arg_func, arg_msg);
10868 
10869 	va_end(ap);
10870 }
10871 
10872 #endif  /* DUK_USE_VARIADIC_MACROS */
10873 
10874 #else  /* DUK_USE_DEBUG */
10875 
10876 /*
10877  *  Debugging disabled
10878  */
10879 
10880 #endif  /* DUK_USE_DEBUG */
10881 
10882 /* automatic undefs */
10883 #undef DUK__DEBUG_BUFSIZE
10884 /*
10885  *  Automatically generated by genbuiltins.py, do not edit!
10886  */
10887 
10888 /* #include duk_internal.h -> already included */
10889 
10890 #if defined(DUK_USE_ASSERTIONS)
10891 #define DUK__REFCINIT(refc) 0 /*h_assert_refcount*/, (refc) /*actual*/
10892 #else
10893 #define DUK__REFCINIT(refc) (refc) /*actual*/
10894 #endif
10895 
10896 #if defined(DUK_USE_ROM_STRINGS)
10897 #error ROM support not enabled, rerun configure.py with --rom-support
10898 #else  /* DUK_USE_ROM_STRINGS */
10899 DUK_INTERNAL const duk_uint8_t duk_strings_data[972] = {
10900 79,40,209,144,168,105,6,78,54,139,89,185,44,48,46,90,120,8,154,140,35,103,
10901 35,113,193,73,5,52,112,180,104,166,135,52,188,4,98,12,27,146,156,80,211,31,
10902 129,115,150,64,52,220,109,24,18,68,156,24,38,67,114,36,55,9,119,151,132,
10903 140,93,18,113,128,153,201,212,201,205,2,248,8,196,24,224,104,82,146,40,224,
10904 193,48,114,168,37,147,196,54,123,28,4,98,12,43,148,67,103,177,192,70,32,
10905 196,121,68,54,123,28,18,192,199,144,124,4,98,12,43,136,108,244,117,184,8,
10906 196,24,95,40,134,207,71,91,128,140,65,133,113,13,158,158,151,1,24,131,11,
10907 229,16,217,233,233,112,17,136,48,206,21,110,4,244,244,184,8,196,24,103,10,
10908 183,2,122,218,156,4,98,12,24,203,112,64,179,113,193,79,8,218,155,131,32,
10909 184,70,212,220,13,10,82,68,252,123,144,217,146,38,228,207,18,0,100,37,64,
10910 178,212,11,161,17,104,162,96,10,200,193,57,165,65,169,16,5,100,81,27,70,18,
10911 32,10,200,68,185,13,116,221,197,184,64,89,57,41,197,13,49,234,5,208,156,
10912 113,87,55,118,147,20,187,56,161,166,92,221,212,73,210,236,226,134,153,115,
10913 119,76,201,203,179,138,26,99,73,212,136,136,164,25,174,137,56,32,72,137,
10914 101,23,52,45,13,34,86,9,79,136,104,201,114,149,96,52,138,134,140,151,75,
10915 226,233,186,120,121,22,39,54,83,141,5,55,68,236,36,164,3,16,225,115,150,64,
10916 52,205,163,2,72,154,83,138,26,99,75,12,11,150,103,5,36,20,211,70,140,133,
10917 67,72,49,241,160,227,81,196,52,168,106,39,132,252,183,136,105,80,212,79,2,
10918 249,110,128,126,88,95,133,109,237,237,237,151,235,127,46,249,119,203,190,
10919 186,206,33,181,2,208,61,190,12,19,34,65,19,81,132,108,228,97,1,107,33,12,
10920 32,45,100,137,64,247,175,9,19,155,41,198,130,155,134,69,146,100,227,226,
10921 231,146,51,192,204,73,140,224,145,221,102,241,68,196,169,248,30,75,12,11,
10922 151,242,233,187,143,138,24,137,162,164,255,253,63,3,201,97,129,114,254,92,
10923 112,75,136,108,166,6,136,159,255,167,224,121,44,48,46,95,203,166,238,74,
10924 113,67,77,201,128,223,255,223,224,121,44,48,46,95,203,145,46,9,205,16,39,
10925 201,62,36,0,192,21,147,255,238,145,39,199,197,211,116,240,242,113,197,78,
10926 214,211,226,233,187,107,105,19,119,37,56,161,166,52,221,212,201,205,36,240,
10927 242,16,96,152,12,26,20,164,137,150,70,154,103,28,137,50,202,96,18,132,241,
10928 41,104,105,56,218,48,36,138,183,57,56,128,68,24,38,2,52,12,34,10,133,147,
10929 141,3,8,119,185,13,153,34,125,206,76,17,49,38,93,206,52,151,154,119,56,28,
10930 76,130,112,200,141,206,21,209,96,23,35,238,114,160,139,0,243,238,114,78,
10931 164,68,68,110,113,226,210,90,26,66,110,113,128,121,247,57,80,68,141,170,
10932 183,56,84,52,11,70,73,19,110,114,160,93,8,113,57,143,66,200,84,53,244,154,
10933 73,24,240,81,32,38,68,18,49,228,207,23,88,100,109,70,114,92,193,4,137,173,
10934 168,36,220,73,19,247,247,182,168,209,144,187,223,58,156,104,79,190,183,127,
10935 123,105,160,110,247,206,167,26,19,239,173,223,222,218,67,75,189,243,169,
10936 198,132,251,235,183,247,182,154,134,151,123,231,83,141,9,247,215,111,239,
10937 109,22,141,22,247,206,167,26,19,239,172,223,218,45,26,47,157,78,52,39,223,
10938 74,24,144,10,32,129,34,20,64,152,142,129,57,179,67,104,68,12,129,161,140,
10939 72,156,100,40,40,185,152,100,89,38,65,13,196,34,228,67,149,13,2,215,129,
10940 149,209,65,104,209,77,14,104,144,81,33,170,67,101,48,52,68,113,70,210,88,
10941 209,36,233,22,154,86,68,196,114,76,232,145,102,120,186,195,156,112,105,225,
10942 228,113,71,80,68,162,115,101,50,85,200,25,108,116,44,132,178,38,114,137,96,
10943 148,136,70,209,134,37,222,232,204,228,188,200,209,200,200,99,221,25,150,84,
10944 121,34,70,209,107,36,227,66,20,160,92,136,164,49,235,35,8,217,201,40,108,
10945 201,18,128,68,26,201,51,188,2,80,12,67,190,40,168,38,68,190,46,153,5,50,12,
10946 207,160,86,129,26,83,4,208,34,225,4,88,192,
10947 };
10948 #endif  /* DUK_USE_ROM_STRINGS */
10949 
10950 #if defined(DUK_USE_ROM_OBJECTS)
10951 #error ROM support not enabled, rerun configure.py with --rom-support
10952 #else  /* DUK_USE_ROM_OBJECTS */
10953 /* native functions: 185 */
10954 DUK_INTERNAL const duk_c_function duk_bi_native_functions[185] = {
10955 	NULL,
10956 	duk_bi_array_constructor,
10957 	duk_bi_array_constructor_is_array,
10958 	duk_bi_array_prototype_concat,
10959 	duk_bi_array_prototype_indexof_shared,
10960 	duk_bi_array_prototype_iter_shared,
10961 	duk_bi_array_prototype_join_shared,
10962 	duk_bi_array_prototype_pop,
10963 	duk_bi_array_prototype_push,
10964 	duk_bi_array_prototype_reduce_shared,
10965 	duk_bi_array_prototype_reverse,
10966 	duk_bi_array_prototype_shift,
10967 	duk_bi_array_prototype_slice,
10968 	duk_bi_array_prototype_sort,
10969 	duk_bi_array_prototype_splice,
10970 	duk_bi_array_prototype_to_string,
10971 	duk_bi_array_prototype_unshift,
10972 	duk_bi_arraybuffer_constructor,
10973 	duk_bi_arraybuffer_isview,
10974 	duk_bi_boolean_constructor,
10975 	duk_bi_boolean_prototype_tostring_shared,
10976 	duk_bi_buffer_compare_shared,
10977 	duk_bi_buffer_readfield,
10978 	duk_bi_buffer_slice_shared,
10979 	duk_bi_buffer_writefield,
10980 	duk_bi_cbor_decode,
10981 	duk_bi_cbor_encode,
10982 	duk_bi_dataview_constructor,
10983 	duk_bi_date_constructor,
10984 	duk_bi_date_constructor_now,
10985 	duk_bi_date_constructor_parse,
10986 	duk_bi_date_constructor_utc,
10987 	duk_bi_date_prototype_get_shared,
10988 	duk_bi_date_prototype_get_timezone_offset,
10989 	duk_bi_date_prototype_set_shared,
10990 	duk_bi_date_prototype_set_time,
10991 	duk_bi_date_prototype_to_json,
10992 	duk_bi_date_prototype_toprimitive,
10993 	duk_bi_date_prototype_tostring_shared,
10994 	duk_bi_date_prototype_value_of,
10995 	duk_bi_duktape_object_act,
10996 	duk_bi_duktape_object_compact,
10997 	duk_bi_duktape_object_dec,
10998 	duk_bi_duktape_object_enc,
10999 	duk_bi_duktape_object_fin,
11000 	duk_bi_duktape_object_gc,
11001 	duk_bi_duktape_object_info,
11002 	duk_bi_error_constructor_shared,
11003 	duk_bi_error_prototype_filename_getter,
11004 	duk_bi_error_prototype_filename_setter,
11005 	duk_bi_error_prototype_linenumber_getter,
11006 	duk_bi_error_prototype_linenumber_setter,
11007 	duk_bi_error_prototype_stack_getter,
11008 	duk_bi_error_prototype_stack_setter,
11009 	duk_bi_error_prototype_to_string,
11010 	duk_bi_function_constructor,
11011 	duk_bi_function_prototype,
11012 	duk_bi_function_prototype_apply,
11013 	duk_bi_function_prototype_bind,
11014 	duk_bi_function_prototype_call,
11015 	duk_bi_function_prototype_hasinstance,
11016 	duk_bi_function_prototype_to_string,
11017 	duk_bi_global_object_decode_uri,
11018 	duk_bi_global_object_decode_uri_component,
11019 	duk_bi_global_object_encode_uri,
11020 	duk_bi_global_object_encode_uri_component,
11021 	duk_bi_global_object_escape,
11022 	duk_bi_global_object_eval,
11023 	duk_bi_global_object_is_finite,
11024 	duk_bi_global_object_is_nan,
11025 	duk_bi_global_object_parse_float,
11026 	duk_bi_global_object_parse_int,
11027 	duk_bi_global_object_unescape,
11028 	duk_bi_json_object_parse,
11029 	duk_bi_json_object_stringify,
11030 	duk_bi_math_object_clz32,
11031 	duk_bi_math_object_hypot,
11032 	duk_bi_math_object_imul,
11033 	duk_bi_math_object_max,
11034 	duk_bi_math_object_min,
11035 	duk_bi_math_object_onearg_shared,
11036 	duk_bi_math_object_random,
11037 	duk_bi_math_object_sign,
11038 	duk_bi_math_object_twoarg_shared,
11039 	duk_bi_native_function_length,
11040 	duk_bi_native_function_name,
11041 	duk_bi_nodejs_buffer_byte_length,
11042 	duk_bi_nodejs_buffer_concat,
11043 	duk_bi_nodejs_buffer_constructor,
11044 	duk_bi_nodejs_buffer_copy,
11045 	duk_bi_nodejs_buffer_fill,
11046 	duk_bi_nodejs_buffer_is_buffer,
11047 	duk_bi_nodejs_buffer_is_encoding,
11048 	duk_bi_nodejs_buffer_tojson,
11049 	duk_bi_nodejs_buffer_tostring,
11050 	duk_bi_nodejs_buffer_write,
11051 	duk_bi_number_check_shared,
11052 	duk_bi_number_constructor,
11053 	duk_bi_number_prototype_to_exponential,
11054 	duk_bi_number_prototype_to_fixed,
11055 	duk_bi_number_prototype_to_locale_string,
11056 	duk_bi_number_prototype_to_precision,
11057 	duk_bi_number_prototype_to_string,
11058 	duk_bi_number_prototype_value_of,
11059 	duk_bi_object_constructor,
11060 	duk_bi_object_constructor_assign,
11061 	duk_bi_object_constructor_create,
11062 	duk_bi_object_constructor_define_properties,
11063 	duk_bi_object_constructor_define_property,
11064 	duk_bi_object_constructor_get_own_property_descriptor,
11065 	duk_bi_object_constructor_is,
11066 	duk_bi_object_constructor_is_extensible,
11067 	duk_bi_object_constructor_is_sealed_frozen_shared,
11068 	duk_bi_object_constructor_keys_shared,
11069 	duk_bi_object_constructor_prevent_extensions,
11070 	duk_bi_object_constructor_seal_freeze_shared,
11071 	duk_bi_object_getprototype_shared,
11072 	duk_bi_object_prototype_defineaccessor,
11073 	duk_bi_object_prototype_has_own_property,
11074 	duk_bi_object_prototype_is_prototype_of,
11075 	duk_bi_object_prototype_lookupaccessor,
11076 	duk_bi_object_prototype_property_is_enumerable,
11077 	duk_bi_object_prototype_to_locale_string,
11078 	duk_bi_object_prototype_to_string,
11079 	duk_bi_object_prototype_value_of,
11080 	duk_bi_object_setprototype_shared,
11081 	duk_bi_performance_now,
11082 	duk_bi_pointer_constructor,
11083 	duk_bi_pointer_prototype_tostring_shared,
11084 	duk_bi_proxy_constructor,
11085 	duk_bi_reflect_apply,
11086 	duk_bi_reflect_construct,
11087 	duk_bi_reflect_object_delete_property,
11088 	duk_bi_reflect_object_get,
11089 	duk_bi_reflect_object_has,
11090 	duk_bi_reflect_object_set,
11091 	duk_bi_regexp_constructor,
11092 	duk_bi_regexp_prototype_exec,
11093 	duk_bi_regexp_prototype_flags,
11094 	duk_bi_regexp_prototype_shared_getter,
11095 	duk_bi_regexp_prototype_test,
11096 	duk_bi_regexp_prototype_tostring,
11097 	duk_bi_string_constructor,
11098 	duk_bi_string_constructor_from_char_code,
11099 	duk_bi_string_constructor_from_code_point,
11100 	duk_bi_string_prototype_caseconv_shared,
11101 	duk_bi_string_prototype_char_at,
11102 	duk_bi_string_prototype_char_code_at,
11103 	duk_bi_string_prototype_concat,
11104 	duk_bi_string_prototype_includes,
11105 	duk_bi_string_prototype_indexof_shared,
11106 	duk_bi_string_prototype_locale_compare,
11107 	duk_bi_string_prototype_match,
11108 	duk_bi_string_prototype_repeat,
11109 	duk_bi_string_prototype_replace,
11110 	duk_bi_string_prototype_search,
11111 	duk_bi_string_prototype_slice,
11112 	duk_bi_string_prototype_split,
11113 	duk_bi_string_prototype_startswith_endswith,
11114 	duk_bi_string_prototype_substr,
11115 	duk_bi_string_prototype_substring,
11116 	duk_bi_string_prototype_to_string,
11117 	duk_bi_string_prototype_trim,
11118 	duk_bi_symbol_constructor_shared,
11119 	duk_bi_symbol_key_for,
11120 	duk_bi_symbol_toprimitive,
11121 	duk_bi_symbol_tostring_shared,
11122 	duk_bi_textdecoder_constructor,
11123 	duk_bi_textdecoder_prototype_decode,
11124 	duk_bi_textdecoder_prototype_shared_getter,
11125 	duk_bi_textencoder_constructor,
11126 	duk_bi_textencoder_prototype_encode,
11127 	duk_bi_textencoder_prototype_encoding_getter,
11128 	duk_bi_thread_constructor,
11129 	duk_bi_thread_current,
11130 	duk_bi_thread_resume,
11131 	duk_bi_thread_yield,
11132 	duk_bi_type_error_thrower,
11133 	duk_bi_typedarray_buffer_getter,
11134 	duk_bi_typedarray_bytelength_getter,
11135 	duk_bi_typedarray_byteoffset_getter,
11136 	duk_bi_typedarray_constructor,
11137 	duk_bi_typedarray_set,
11138 	duk_bi_uint8array_allocplain,
11139 	duk_bi_uint8array_plainof,
11140 };
11141 #if defined(DUK_USE_DOUBLE_LE)
11142 DUK_INTERNAL const duk_uint8_t duk_builtins_data[4281] = {
11143 144,148,105,226,32,68,52,228,254,12,104,202,37,132,52,167,194,138,105,245,
11144 124,57,28,211,57,18,64,52,239,126,44,138,111,175,241,164,19,87,145,30,33,
11145 167,22,145,159,8,211,139,9,225,42,5,240,145,139,163,163,8,211,139,10,228,
11146 64,211,19,132,140,93,29,56,70,156,88,119,34,66,146,36,104,137,194,70,46,
11147 142,172,35,78,44,47,146,195,102,11,240,145,139,163,175,8,211,139,9,228,240,
11148 242,112,145,139,163,179,8,211,139,8,237,34,130,118,49,116,118,225,26,48,0,
11149 1,98,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
11150 33,8,66,26,180,105,97,167,68,150,34,33,154,112,0,1,91,247,35,79,111,237,
11151 198,174,232,47,31,23,95,17,13,31,249,96,211,49,50,53,214,77,141,24,0,0,181,
11152 10,228,240,242,15,128,140,65,128,134,188,0,0,90,167,97,181,224,0,2,213,62,
11153 53,224,0,2,213,66,237,120,0,0,181,81,204,107,192,0,5,170,150,67,94,0,0,45,
11154 84,245,90,240,0,1,106,169,162,215,128,0,11,85,93,150,188,0,0,90,171,111,53,
11155 109,22,162,26,48,0,1,84,23,201,146,243,225,26,39,12,145,136,104,192,0,5,61,
11156 11,228,201,121,240,100,19,134,72,196,33,195,14,40,203,112,64,190,76,232,
11157 145,153,136,0,0,0,0,0,0,31,15,249,152,0,0,0,0,0,0,30,15,249,120,144,13,96,
11158 155,194,56,80,206,36,67,141,20,228,70,57,81,206,100,131,156,39,132,168,23,
11159 194,70,46,137,208,21,200,129,166,39,9,24,186,39,72,119,34,66,146,36,104,
11160 137,194,70,46,137,212,23,201,97,179,5,248,72,197,209,58,194,121,60,60,156,
11161 36,98,232,157,129,29,164,80,78,198,46,137,218,146,121,25,71,146,9,209,5,
11162 209,61,48,126,14,138,152,30,67,186,23,143,139,175,131,202,135,228,72,85,
11163 144,83,60,179,30,94,209,233,102,30,98,105,230,103,30,114,121,231,104,30,
11164 122,137,231,233,30,130,153,232,106,30,138,169,232,235,30,144,67,193,25,19,
11165 136,108,207,30,41,224,140,137,194,173,192,153,228,5,242,100,188,248,70,137,
11166 195,36,79,78,47,147,37,231,193,144,78,25,34,122,145,111,36,74,232,176,13,
11167 17,61,234,226,93,207,148,160,84,75,141,7,27,161,32,33,18,225,80,212,76,154,
11168 2,2,70,65,56,100,237,34,140,209,2,67,32,156,50,118,145,64,186,230,61,205,
11169 35,103,155,32,36,141,19,134,78,210,40,206,16,36,70,137,195,39,105,20,11,
11170 174,99,220,210,54,121,210,1,137,33,1,228,207,16,17,70,146,66,3,201,164,32,
11171 0,65,112,152,56,196,159,31,23,77,211,195,201,199,23,160,72,214,246,81,6,12,
11172 73,241,214,111,31,23,60,145,158,56,50,72,81,67,230,232,242,80,19,49,39,199,
11173 89,188,124,92,242,70,120,227,64,194,75,154,72,12,9,73,6,111,21,120,12,40,
11174 144,19,39,25,0,225,144,168,105,56,248,185,228,140,241,200,96,64,100,42,26,
11175 78,62,46,121,35,52,18,92,116,1,36,64,47,158,64,49,98,66,100,156,242,65,23,
11176 196,149,35,103,194,94,100,108,144,230,203,156,64,66,37,201,16,11,32,249,
11177 132,4,34,92,44,93,146,55,152,72,24,137,112,151,153,27,36,5,100,229,144,8,
11178 162,98,92,210,5,76,73,241,214,111,31,23,60,145,158,57,44,48,46,92,185,164,
11179 160,72,151,41,0,50,107,179,244,59,36,93,127,92,6,19,172,3,11,216,0,56,224,
11180 151,29,102,241,241,115,201,25,227,164,64,106,37,199,197,211,116,240,242,
11181 113,197,233,144,40,248,185,228,140,241,196,75,132,109,24,72,128,43,39,84,
11182 129,13,173,161,144,168,105,56,98,78,100,142,214,215,69,1,13,173,161,144,
11183 168,105,57,34,78,100,142,214,215,69,16,67,107,105,110,114,168,254,24,147,
11184 153,35,181,181,212,32,67,107,105,110,114,168,254,72,147,153,35,181,181,212,
11185 36,65,130,3,144,8,26,252,200,13,30,85,16,16,64,90,242,231,192,64,161,163,
11186 203,31,26,172,193,17,4,23,105,159,96,27,172,251,16,32,196,4,14,137,112,17,
11187 136,48,164,28,134,80,215,202,1,132,130,8,12,39,52,64,155,31,24,56,36,1,189,
11188 207,132,0,35,233,35,195,62,3,196,149,36,100,72,160,2,200,232,44,227,0,11,
11189 37,160,68,142,128,36,157,25,200,32,26,79,90,4,73,43,192,122,54,71,65,103,
11190 44,248,14,134,140,151,227,138,231,208,45,96,148,248,134,140,151,227,138,
11191 231,240,1,255,254,10,74,146,56,128,104,4,147,152,72,6,144,28,174,143,8,1,
11192 30,1,165,3,96,31,0,211,3,21,11,153,35,0,211,131,68,131,160,137,16,250,5,
11193 196,131,160,137,200,160,199,156,67,248,0,255,255,65,140,10,48,177,115,56,
11194 35,130,60,19,134,79,89,240,52,177,115,56,39,12,156,123,144,217,251,15,135,
11195 34,167,30,20,170,154,255,232,12,47,244,0,97,28,17,224,39,238,32,40,71,4,
11196 120,39,12,156,4,253,228,5,137,195,39,30,228,54,124,4,253,228,128,194,115,
11197 68,9,252,15,128,232,104,201,126,56,191,35,64,90,193,41,241,13,25,47,199,23,
11198 228,105,3,86,225,1,100,224,156,199,130,36,249,144,10,192,76,71,250,16,15,
11199 18,61,96,17,62,200,3,72,128,136,143,247,32,22,75,64,137,248,64,22,79,90,39,
11200 249,64,38,84,12,167,20,52,223,196,2,230,238,45,214,36,120,32,72,158,208,4,
11201 102,238,45,194,2,201,197,186,196,143,4,9,19,218,0,92,221,202,61,228,143,4,
11202 9,19,218,8,35,55,113,110,16,22,78,81,239,36,120,32,72,158,208,64,73,197,12,
11203 255,0,13,18,60,128,159,212,128,169,76,17,156,185,100,76,255,163,64,65,26,
11204 57,114,200,153,255,70,144,33,13,18,232,50,75,226,104,6,149,3,41,199,246,
11205 130,12,128,28,142,156,120,203,175,158,8,194,207,1,6,81,20,79,88,11,237,84,
11206 11,161,32,127,255,255,255,255,255,247,191,137,235,16,221,170,129,116,36,0,
11207 16,0,0,0,0,0,0,12,196,0,0,0,0,0,0,15,135,242,61,123,164,137,162,164,218,67,
11208 74,134,162,120,128,0,0,0,0,0,1,224,254,71,173,33,129,52,84,155,72,105,80,
11209 212,79,16,0,0,0,0,0,0,60,63,195,244,143,146,22,230,192,0,0,0,0,0,0,176,60,
11210 33,214,2,251,82,1,73,180,134,204,134,36,96,127,255,255,255,255,255,159,161,
11211 144,235,16,221,169,0,164,218,67,102,67,18,48,63,255,255,255,255,255,207,
11212 240,196,60,17,145,56,134,204,241,226,158,8,200,156,42,220,9,158,65,196,34,
11213 92,42,26,137,147,120,64,74,37,196,54,100,49,35,188,36,5,68,184,208,113,187,
11214 194,80,212,75,146,1,73,196,54,100,49,35,188,38,57,37,56,240,0,0,0,0,0,0,0,
11215 0,32,235,248,68,48,156,2,24,94,24,0,243,119,10,139,144,123,242,3,102,238,
11216 18,239,115,72,217,160,11,223,16,23,55,113,241,32,145,36,57,188,18,16,102,3,
11217 5,120,35,34,89,32,15,180,152,173,127,0,218,235,88,0,228,180,227,200,0,0,0,
11218 0,0,0,248,127,197,107,240,64,6,77,220,24,38,78,74,113,67,77,130,4,12,155,
11219 185,52,48,156,148,226,134,155,4,10,194,96,129,132,166,238,45,194,2,201,193,
11220 130,100,228,167,20,52,216,32,113,41,187,139,112,128,178,114,104,97,57,41,
11221 197,13,54,8,32,48,216,32,130,195,224,130,19,97,124,134,23,6,0,57,137,62,77,
11222 12,38,12,0,179,18,124,45,22,190,96,128,141,176,134,28,98,79,180,152,139,
11223 218,45,124,193,1,27,97,16,32,196,159,24,230,204,246,194,40,89,137,62,210,
11224 98,103,92,217,158,216,70,7,49,39,193,130,100,182,17,194,140,73,246,147,16,
11225 250,9,146,216,72,6,49,39,193,131,22,194,72,73,137,62,210,98,31,65,139,97,
11226 40,32,196,159,14,234,70,86,194,88,89,137,62,210,98,63,93,72,202,216,76,10,
11227 49,39,198,33,180,153,37,108,38,134,152,147,237,38,38,117,13,164,201,43,97,
11228 56,40,196,159,36,65,57,163,149,176,158,26,98,79,180,152,165,210,9,205,28,
11229 173,133,0,243,18,124,98,22,180,72,130,115,71,43,97,68,72,196,159,105,49,51,
11230 168,90,209,34,9,205,28,173,133,33,19,18,124,154,24,76,185,164,227,138,89,
11231 18,119,0,7,145,39,201,161,132,188,64,124,137,62,49,11,90,36,65,57,163,149,
11232 210,166,37,34,79,180,152,153,212,45,104,145,4,230,142,87,74,160,84,137,62,
11233 72,130,115,71,43,171,234,134,200,147,237,38,41,116,130,115,71,43,171,235,5,
11234 72,147,227,16,218,76,146,186,254,184,108,137,62,210,98,103,80,218,76,146,
11235 186,254,192,68,137,62,29,212,140,174,207,178,23,34,79,180,152,143,215,82,
11236 50,187,62,208,60,137,62,12,19,37,210,182,21,34,79,180,152,135,208,76,151,
11237 74,224,68,137,62,49,205,153,238,175,186,23,34,79,180,152,153,215,54,103,
11238 186,190,240,92,137,62,22,139,95,48,64,70,235,251,225,210,36,251,73,136,189,
11239 162,215,204,16,17,186,255,2,14,98,79,152,32,35,108,48,64,242,36,249,130,2,
11240 55,75,6,212,224,72,200,51,128,114,108,28,100,128,0,0,0,0,0,0,0,12,110,127,
11241 48,98,115,249,201,117,243,249,195,21,159,206,38,47,63,156,86,8,75,144,94,
11242 82,1,38,73,79,208,67,95,233,1,6,128,14,79,129,186,40,249,18,149,182,207,
11243 144,200,155,188,248,204,105,184,207,142,199,137,175,201,0,159,72,10,5,21,
11244 221,10,120,74,129,124,36,98,232,228,74,81,62,160,20,10,107,186,21,114,32,
11245 105,137,194,70,46,142,68,165,19,235,1,64,170,187,161,119,34,66,146,36,104,
11246 137,194,70,46,142,68,165,19,236,1,64,174,187,161,95,37,134,204,23,225,35,
11247 23,71,34,82,137,246,128,160,89,93,208,167,147,195,201,194,70,46,142,68,165,
11248 19,238,1,64,182,187,161,71,105,20,19,177,139,163,145,41,68,16,7,6,15,82,70,
11249 72,115,96,0,0,0,0,0,15,106,32,91,60,165,195,201,194,8,134,149,216,162,0,
11250 192,41,225,8,2,48,177,36,1,149,13,196,15,0,200,209,97,199,128,99,32,176,
11251 195,192,113,57,143,0,167,133,32,230,80,28,202,139,175,238,2,48,189,192,20,
11252 1,119,80,87,193,186,129,89,56,72,197,209,200,193,185,35,23,71,109,13,219,
11253 36,98,232,237,156,13,26,208,211,14,102,19,87,137,91,95,128,0,10,96,24,92,0,
11254 0,83,2,53,56,0,0,165,3,28,204,160,160,226,100,226,200,211,76,241,240,0,1,
11255 102,8,22,75,64,137,73,20,230,105,133,7,19,39,22,70,154,103,143,128,0,11,48,
11256 20,28,76,156,113,75,34,78,62,0,0,45,3,103,31,0,0,22,65,44,57,137,62,33,179,
11257 216,162,152,192,131,18,124,162,27,61,138,41,108,32,196,159,16,217,232,235,
11258 81,76,104,73,137,62,81,13,158,142,181,20,184,16,98,79,136,108,244,244,168,
11259 166,56,36,196,159,40,134,207,79,74,138,93,10,49,39,194,173,192,158,158,149,
11260 20,188,20,98,79,133,91,129,61,109,74,41,124,30,68,159,16,217,236,83,108,96,
11261 68,137,62,81,13,158,197,54,182,17,34,79,136,108,244,117,169,182,52,38,68,
11262 159,40,134,207,71,90,155,92,8,145,39,196,54,122,122,84,219,28,19,34,79,148,
11263 67,103,167,165,77,174,133,72,147,225,86,224,79,79,74,155,94,10,145,39,194,
11264 173,192,158,182,165,54,190,206,25,212,35,208,226,100,150,211,201,29,162,44,
11265 140,35,103,0,0,0,0,0,0,3,192,252,206,25,228,35,208,226,100,150,211,201,29,
11266 162,44,140,35,103,0,0,0,0,0,0,3,192,252,206,25,244,35,208,226,100,150,211,
11267 201,29,162,44,140,35,103,0,0,0,0,0,0,3,192,252,206,26,4,35,208,226,100,150,
11268 211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,1,0,206,26,20,35,208,226,100,
11269 150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,1,0,206,26,36,35,208,226,
11270 100,150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,65,0,206,26,52,35,208,
11271 226,100,150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,65,0,206,26,68,35,
11272 208,226,100,150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,65,0,206,26,84,
11273 35,208,226,100,150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,129,0,195,
11274 154,99,16,38,36,0,251,68,117,179,216,162,128,68,72,1,241,13,158,197,20,150,
11275 25,18,0,125,162,58,217,232,235,117,100,162,136,25,18,0,125,162,58,217,232,
11276 235,116,36,162,145,2,226,64,15,136,108,244,117,186,178,81,73,129,113,32,7,
11277 196,54,122,58,221,9,40,165,64,200,144,3,237,17,214,207,79,75,171,37,20,80,
11278 200,144,3,237,17,214,207,79,75,161,37,20,138,23,18,0,124,67,103,167,165,
11279 213,146,138,77,11,137,0,62,33,179,211,210,232,73,69,42,133,196,128,31,10,
11280 183,2,125,89,40,163,5,196,128,31,10,183,2,125,9,40,164,96,200,144,3,224,
11281 221,64,172,157,89,40,163,134,68,128,31,6,234,5,100,232,73,69,35,133,68,128,
11282 31,104,142,182,125,89,40,180,0,168,144,3,237,17,214,207,161,37,22,144,19,
11283 18,0,124,67,103,213,146,139,80,9,137,0,62,33,179,232,73,69,172,5,90,40,153,
11284 59,68,117,179,216,166,192,77,162,137,147,136,108,246,41,180,176,219,69,19,
11285 39,104,142,182,122,58,221,89,41,178,6,218,40,153,59,68,117,179,209,214,232,
11286 73,77,162,6,90,40,153,56,134,207,71,91,171,37,54,152,25,104,162,100,226,27,
11287 61,29,110,132,148,218,160,109,162,137,147,180,71,91,61,61,46,172,148,217,
11288 67,109,20,76,157,162,58,217,233,233,116,36,166,209,67,45,20,76,156,67,103,
11289 167,165,213,146,155,77,12,180,81,50,113,13,158,158,151,66,74,109,84,50,209,
11290 68,201,194,173,192,159,86,74,108,193,150,138,38,78,21,110,4,250,18,83,104,
11291 193,182,138,38,78,13,212,10,201,213,146,155,56,109,162,137,147,131,117,2,
11292 178,116,36,166,209,194,237,20,76,157,162,58,217,245,100,167,16,2,237,20,76,
11293 157,162,58,217,244,36,167,18,2,173,20,76,156,67,103,213,146,156,80,10,180,
11294 81,50,113,13,159,66,74,113,97,175,221,48,216,110,64,4,42,22,189,179,0,196,
11295 133,0,185,80,32,28,78,99,193,18,80,36,4,19,159,141,172,0,178,90,4,74,73,0,
11296 22,209,68,201,187,129,4,2,8,3,132,64,60,36,6,149,113,72,176,171,240,84,0,
11297 157,91,116,116,32,11,42,218,221,216,181,129,32,3,234,219,165,3,188,231,235,
11298 249,8,187,152,252,47,86,227,105,18,7,244,17,91,42,56,175,185,248,110,173,
11299 198,209,208,36,0,238,82,97,87,188,189,179,240,93,122,32,12,22,162,42,125,
11300 144,132,160,7,236,161,25,232,237,105,64,205,59,127,102,158,160,230,63,11,
11301 217,66,51,210,129,154,118,254,205,61,65,236,127,171,197,34,168,48,6,90,194,
11302 1,0,39,75,88,72,8,9,33,186,194,80,64,76,13,214,19,2,130,96,110,150,189,0,
11303 65,6,51,214,20,128,65,17,11,214,19,130,137,121,211,210,211,144,6,39,75,88,
11304 80,0,201,119,235,10,8,41,86,231,71,88,80,129,79,135,186,122,133,224,34,25,
11305 69,234,80,3,91,141,172,40,96,139,113,180,181,133,36,21,110,54,142,134,176,
11306 165,1,176,23,213,47,0,216,134,234,215,128,111,117,181,232,128,209,3,70,230,
11307 107,64,5,139,168,209,235,10,32,36,144,102,235,136,3,146,27,172,40,160,146,
11308 132,103,172,40,192,115,3,117,133,28,22,113,163,69,172,41,103,1,66,188,17,
11309 145,52,168,4,202,113,67,76,130,227,76,194,13,240,108,0,0,83,224,0,2,193,0,
11310 104,146,84,97,48,0,1,94,192,56,169,24,145,179,192,0,5,112,8,56,16,32,128,
11311 56,18,52,125,230,86,147,190,140,28,50,21,13,39,31,23,60,145,158,57,12,141,
11312 47,129,6,155,194,188,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,
11313 15,155,163,201,68,14,49,39,199,197,211,116,240,242,113,197,232,18,180,254,
11314 36,3,17,46,18,243,35,100,128,172,156,178,70,163,154,76,34,248,146,164,108,
11315 248,75,204,141,146,28,217,115,137,27,95,27,241,173,236,162,160,224,200,2,
11316 206,9,113,13,148,192,209,18,22,164,146,37,193,57,162,4,249,39,196,128,24,2,
11317 178,66,213,136,68,201,16,77,209,131,31,192,242,88,96,92,191,151,34,100,136,
11318 38,232,255,252,92,221,199,197,12,68,209,82,66,212,11,155,185,41,197,13,55,
11319 38,3,66,213,47,135,254,72,12,162,99,133,116,112,0,1,72,66,14,16,16,50,37,
11320 202,160,150,154,66,14,20,8,57,192,28,24,80,113,50,113,100,105,166,120,248,
11321 0,0,179,1,65,196,201,199,20,178,36,227,224,0,2,208,54,113,240,0,1,100,11,
11322 181,192,0,5,178,1,18,160,65,24,131,20,145,25,188,48,132,122,28,76,146,218,
11323 121,35,180,69,145,132,108,224,0,0,0,0,0,0,120,31,153,188,56,132,122,28,76,
11324 146,218,121,35,180,69,145,132,108,224,0,0,0,0,0,0,120,31,168,160,45,110,23,
11325 30,176,33,184,0,0,183,32,29,235,2,27,199,23,0,0,23,4,51,120,129,8,244,56,
11326 153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,240,63,51,120,145,8,244,
11327 56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,0,64,51,120,161,8,
11328 244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,0,64,51,120,177,
11329 8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,51,120,
11330 193,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,51,
11331 120,209,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,
11332 51,120,225,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,32,
11333 64,32,227,194,0,97,57,162,4,246,104,5,34,92,35,68,225,161,166,220,16,16,
11334 137,112,52,41,73,29,185,1,65,196,201,197,145,166,153,246,72,3,137,204,120,
11335 34,74,8,199,1,67,17,162,112,201,84,128,97,144,78,25,42,16,131,169,1,205,66,
11336 8,35,68,225,161,166,239,128,0,10,192,64,196,104,156,50,96,0,2,172,73,240,
11337 117,96,57,170,97,4,104,156,52,52,221,240,0,1,82,1,74,9,129,125,240,0,1,82,
11338 32,148,25,174,137,58,23,51,190,0,0,42,69,64,195,32,156,50,96,0,2,160,81,
11339 238,2,3,107,173,218,3,192,
11340 };
11341 #elif defined(DUK_USE_DOUBLE_BE)
11342 DUK_INTERNAL const duk_uint8_t duk_builtins_data[4281] = {
11343 144,148,105,226,32,68,52,228,254,12,104,202,37,132,52,167,194,138,105,245,
11344 124,57,28,211,57,18,64,52,239,126,44,138,111,175,241,164,19,87,145,30,33,
11345 167,22,145,159,8,211,139,9,225,42,5,240,145,139,163,163,8,211,139,10,228,
11346 64,211,19,132,140,93,29,56,70,156,88,119,34,66,146,36,104,137,194,70,46,
11347 142,172,35,78,44,47,146,195,102,11,240,145,139,163,175,8,211,139,9,228,240,
11348 242,112,145,139,163,179,8,211,139,8,237,34,130,118,49,116,118,225,26,48,0,
11349 1,98,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
11350 33,8,66,26,180,105,97,167,68,150,34,33,154,112,0,1,91,247,35,79,111,237,
11351 198,174,232,47,31,23,95,17,13,31,249,96,211,49,50,53,214,77,141,24,0,0,181,
11352 10,228,240,242,15,128,140,65,128,134,188,0,0,90,167,97,181,224,0,2,213,62,
11353 53,224,0,2,213,66,237,120,0,0,181,81,204,107,192,0,5,170,150,67,94,0,0,45,
11354 84,245,90,240,0,1,106,169,162,215,128,0,11,85,93,150,188,0,0,90,171,111,53,
11355 109,22,162,26,48,0,1,84,23,201,146,243,225,26,39,12,145,136,104,192,0,5,61,
11356 11,228,201,121,240,100,19,134,72,196,33,195,14,40,203,112,64,190,76,232,
11357 145,153,136,15,255,0,0,0,0,0,0,25,152,15,254,0,0,0,0,0,0,25,120,144,13,96,
11358 155,194,56,80,206,36,67,141,20,228,70,57,81,206,100,131,156,39,132,168,23,
11359 194,70,46,137,208,21,200,129,166,39,9,24,186,39,72,119,34,66,146,36,104,
11360 137,194,70,46,137,212,23,201,97,179,5,248,72,197,209,58,194,121,60,60,156,
11361 36,98,232,157,129,29,164,80,78,198,46,137,218,146,121,25,71,146,9,209,5,
11362 209,61,48,126,14,138,152,30,67,186,23,143,139,175,131,202,135,228,72,85,
11363 144,83,60,179,30,94,209,233,102,30,98,105,230,103,30,114,121,231,104,30,
11364 122,137,231,233,30,130,153,232,106,30,138,169,232,235,30,144,67,193,25,19,
11365 136,108,207,30,41,224,140,137,194,173,192,153,228,5,242,100,188,248,70,137,
11366 195,36,79,78,47,147,37,231,193,144,78,25,34,122,145,111,36,74,232,176,13,
11367 17,61,234,226,93,207,148,160,84,75,141,7,27,161,32,33,18,225,80,212,76,154,
11368 2,2,70,65,56,100,237,34,140,209,2,67,32,156,50,118,145,64,186,230,61,205,
11369 35,103,155,32,36,141,19,134,78,210,40,206,16,36,70,137,195,39,105,20,11,
11370 174,99,220,210,54,121,210,1,137,33,1,228,207,16,17,70,146,66,3,201,164,32,
11371 0,65,112,152,56,196,159,31,23,77,211,195,201,199,23,160,72,214,246,81,6,12,
11372 73,241,214,111,31,23,60,145,158,56,50,72,81,67,230,232,242,80,19,49,39,199,
11373 89,188,124,92,242,70,120,227,64,194,75,154,72,12,9,73,6,111,21,120,12,40,
11374 144,19,39,25,0,225,144,168,105,56,248,185,228,140,241,200,96,64,100,42,26,
11375 78,62,46,121,35,52,18,92,116,1,36,64,47,158,64,49,98,66,100,156,242,65,23,
11376 196,149,35,103,194,94,100,108,144,230,203,156,64,66,37,201,16,11,32,249,
11377 132,4,34,92,44,93,146,55,152,72,24,137,112,151,153,27,36,5,100,229,144,8,
11378 162,98,92,210,5,76,73,241,214,111,31,23,60,145,158,57,44,48,46,92,185,164,
11379 160,72,151,41,0,50,107,179,244,59,36,93,127,92,6,19,172,3,11,216,0,56,224,
11380 151,29,102,241,241,115,201,25,227,164,64,106,37,199,197,211,116,240,242,
11381 113,197,233,144,40,248,185,228,140,241,196,75,132,109,24,72,128,43,39,84,
11382 129,13,173,161,144,168,105,56,98,78,100,142,214,215,69,1,13,173,161,144,
11383 168,105,57,34,78,100,142,214,215,69,16,67,107,105,110,114,168,254,24,147,
11384 153,35,181,181,212,32,67,107,105,110,114,168,254,72,147,153,35,181,181,212,
11385 36,65,130,3,144,8,26,252,200,13,30,85,16,16,64,90,242,231,192,64,161,163,
11386 203,31,26,172,193,17,4,23,105,159,96,27,172,251,16,32,196,4,14,137,112,17,
11387 136,48,164,28,134,80,215,202,1,132,130,8,12,39,52,64,155,31,24,56,36,1,189,
11388 207,132,0,35,233,35,195,62,3,196,149,36,100,72,160,2,200,232,44,227,0,11,
11389 37,160,68,142,128,36,157,25,200,32,26,79,90,4,73,43,192,122,54,71,65,103,
11390 44,248,14,134,140,151,227,138,231,208,45,96,148,248,134,140,151,227,138,
11391 231,240,1,255,254,10,74,146,56,128,104,4,147,152,72,6,144,28,174,143,8,1,
11392 30,1,165,3,96,31,0,211,3,21,11,153,35,0,211,131,68,131,160,137,16,250,5,
11393 196,131,160,137,200,160,199,156,67,248,0,255,255,65,140,10,48,177,115,56,
11394 35,130,60,19,134,79,89,240,52,177,115,56,39,12,156,123,144,217,251,15,135,
11395 34,167,30,20,170,154,255,232,12,47,244,0,97,28,17,224,39,238,32,40,71,4,
11396 120,39,12,156,4,253,228,5,137,195,39,30,228,54,124,4,253,228,128,194,115,
11397 68,9,252,15,128,232,104,201,126,56,191,35,64,90,193,41,241,13,25,47,199,23,
11398 228,105,3,86,225,1,100,224,156,199,130,36,249,144,10,192,76,71,250,16,15,
11399 18,61,96,17,62,200,3,72,128,136,143,247,32,22,75,64,137,248,64,22,79,90,39,
11400 249,64,38,84,12,167,20,52,223,196,2,230,238,45,214,36,120,32,72,158,208,4,
11401 102,238,45,194,2,201,197,186,196,143,4,9,19,218,0,92,221,202,61,228,143,4,
11402 9,19,218,8,35,55,113,110,16,22,78,81,239,36,120,32,72,158,208,64,73,197,12,
11403 255,0,13,18,60,128,159,212,128,169,76,17,156,185,100,76,255,163,64,65,26,
11404 57,114,200,153,255,70,144,33,13,18,232,50,75,226,104,6,149,3,41,199,246,
11405 130,12,128,28,142,156,120,203,175,158,8,194,207,1,6,81,20,79,88,11,237,84,
11406 11,161,32,63,247,255,255,255,255,255,255,137,235,16,221,170,129,116,36,0,0,
11407 0,0,0,0,0,0,28,196,7,255,128,0,0,0,0,0,2,61,123,164,137,162,164,218,67,74,
11408 134,162,120,128,255,224,0,0,0,0,0,0,71,173,33,129,52,84,155,72,105,80,212,
11409 79,16,63,252,0,0,0,0,0,0,3,244,143,146,22,230,192,60,176,0,0,0,0,0,0,33,
11410 214,2,251,82,1,73,180,134,204,134,36,96,33,159,255,255,255,255,255,255,144,
11411 235,16,221,169,0,164,218,67,102,67,18,48,48,207,255,255,255,255,255,255,
11412 196,60,17,145,56,134,204,241,226,158,8,200,156,42,220,9,158,65,196,34,92,
11413 42,26,137,147,120,64,74,37,196,54,100,49,35,188,36,5,68,184,208,113,187,
11414 194,80,212,75,146,1,73,196,54,100,49,35,188,38,57,37,56,240,0,0,0,0,0,0,0,
11415 0,32,235,248,68,48,156,2,24,94,24,0,243,119,10,139,144,123,242,3,102,238,
11416 18,239,115,72,217,160,11,223,16,23,55,113,241,32,145,36,57,188,18,16,102,3,
11417 5,120,35,34,89,32,15,180,152,173,127,0,218,235,88,0,228,180,227,200,127,
11418 248,0,0,0,0,0,0,197,107,240,64,6,77,220,24,38,78,74,113,67,77,130,4,12,155,
11419 185,52,48,156,148,226,134,155,4,10,194,96,129,132,166,238,45,194,2,201,193,
11420 130,100,228,167,20,52,216,32,113,41,187,139,112,128,178,114,104,97,57,41,
11421 197,13,54,8,32,48,216,32,130,195,224,130,19,97,124,134,23,6,0,57,137,62,77,
11422 12,38,12,0,179,18,124,45,22,190,96,128,141,176,134,28,98,79,180,152,139,
11423 218,45,124,193,1,27,97,16,32,196,159,24,230,204,246,194,40,89,137,62,210,
11424 98,103,92,217,158,216,70,7,49,39,193,130,100,182,17,194,140,73,246,147,16,
11425 250,9,146,216,72,6,49,39,193,131,22,194,72,73,137,62,210,98,31,65,139,97,
11426 40,32,196,159,14,234,70,86,194,88,89,137,62,210,98,63,93,72,202,216,76,10,
11427 49,39,198,33,180,153,37,108,38,134,152,147,237,38,38,117,13,164,201,43,97,
11428 56,40,196,159,36,65,57,163,149,176,158,26,98,79,180,152,165,210,9,205,28,
11429 173,133,0,243,18,124,98,22,180,72,130,115,71,43,97,68,72,196,159,105,49,51,
11430 168,90,209,34,9,205,28,173,133,33,19,18,124,154,24,76,185,164,227,138,89,
11431 18,119,0,7,145,39,201,161,132,188,64,124,137,62,49,11,90,36,65,57,163,149,
11432 210,166,37,34,79,180,152,153,212,45,104,145,4,230,142,87,74,160,84,137,62,
11433 72,130,115,71,43,171,234,134,200,147,237,38,41,116,130,115,71,43,171,235,5,
11434 72,147,227,16,218,76,146,186,254,184,108,137,62,210,98,103,80,218,76,146,
11435 186,254,192,68,137,62,29,212,140,174,207,178,23,34,79,180,152,143,215,82,
11436 50,187,62,208,60,137,62,12,19,37,210,182,21,34,79,180,152,135,208,76,151,
11437 74,224,68,137,62,49,205,153,238,175,186,23,34,79,180,152,153,215,54,103,
11438 186,190,240,92,137,62,22,139,95,48,64,70,235,251,225,210,36,251,73,136,189,
11439 162,215,204,16,17,186,255,2,14,98,79,152,32,35,108,48,64,242,36,249,130,2,
11440 55,75,6,212,224,72,200,51,128,114,108,28,100,128,0,0,0,0,0,0,0,12,110,127,
11441 48,98,115,249,201,117,243,249,195,21,159,206,38,47,63,156,86,8,75,144,94,
11442 82,1,38,73,79,208,67,95,233,1,6,128,14,79,129,186,40,249,18,149,182,207,
11443 144,200,155,188,248,204,105,184,207,142,199,137,175,201,0,159,72,10,5,21,
11444 221,10,120,74,129,124,36,98,232,228,74,81,62,160,20,10,107,186,21,114,32,
11445 105,137,194,70,46,142,68,165,19,235,1,64,170,187,161,119,34,66,146,36,104,
11446 137,194,70,46,142,68,165,19,236,1,64,174,187,161,95,37,134,204,23,225,35,
11447 23,71,34,82,137,246,128,160,89,93,208,167,147,195,201,194,70,46,142,68,165,
11448 19,238,1,64,182,187,161,71,105,20,19,177,139,163,145,41,68,16,7,6,15,82,70,
11449 72,115,96,32,106,15,0,0,0,0,0,91,60,165,195,201,194,8,134,149,216,162,0,
11450 192,41,225,8,2,48,177,36,1,149,13,196,15,0,200,209,97,199,128,99,32,176,
11451 195,192,113,57,143,0,167,133,32,230,80,28,202,139,175,238,2,48,189,192,20,
11452 1,119,80,87,193,186,129,89,56,72,197,209,200,193,185,35,23,71,109,13,219,
11453 36,98,232,237,156,13,26,208,211,14,102,19,87,137,91,95,128,0,10,96,24,92,0,
11454 0,83,2,53,56,0,0,165,3,28,204,160,160,226,100,226,200,211,76,241,240,0,1,
11455 102,8,22,75,64,137,73,20,230,105,133,7,19,39,22,70,154,103,143,128,0,11,48,
11456 20,28,76,156,113,75,34,78,62,0,0,45,3,103,31,0,0,22,65,44,57,137,62,33,179,
11457 216,162,152,192,131,18,124,162,27,61,138,41,108,32,196,159,16,217,232,235,
11458 81,76,104,73,137,62,81,13,158,142,181,20,184,16,98,79,136,108,244,244,168,
11459 166,56,36,196,159,40,134,207,79,74,138,93,10,49,39,194,173,192,158,158,149,
11460 20,188,20,98,79,133,91,129,61,109,74,41,124,30,68,159,16,217,236,83,108,96,
11461 68,137,62,81,13,158,197,54,182,17,34,79,136,108,244,117,169,182,52,38,68,
11462 159,40,134,207,71,90,155,92,8,145,39,196,54,122,122,84,219,28,19,34,79,148,
11463 67,103,167,165,77,174,133,72,147,225,86,224,79,79,74,155,94,10,145,39,194,
11464 173,192,158,182,165,54,190,206,25,212,35,208,226,100,150,211,201,29,162,44,
11465 140,35,103,0,255,192,0,0,0,0,0,0,206,25,228,35,208,226,100,150,211,201,29,
11466 162,44,140,35,103,0,255,192,0,0,0,0,0,0,206,25,244,35,208,226,100,150,211,
11467 201,29,162,44,140,35,103,0,255,192,0,0,0,0,0,0,206,26,4,35,208,226,100,150,
11468 211,201,29,162,44,140,35,103,1,0,0,0,0,0,0,0,0,206,26,20,35,208,226,100,
11469 150,211,201,29,162,44,140,35,103,1,0,0,0,0,0,0,0,0,206,26,36,35,208,226,
11470 100,150,211,201,29,162,44,140,35,103,1,0,64,0,0,0,0,0,0,206,26,52,35,208,
11471 226,100,150,211,201,29,162,44,140,35,103,1,0,64,0,0,0,0,0,0,206,26,68,35,
11472 208,226,100,150,211,201,29,162,44,140,35,103,1,0,64,0,0,0,0,0,0,206,26,84,
11473 35,208,226,100,150,211,201,29,162,44,140,35,103,1,0,128,0,0,0,0,0,0,195,
11474 154,99,16,38,36,0,251,68,117,179,216,162,128,68,72,1,241,13,158,197,20,150,
11475 25,18,0,125,162,58,217,232,235,117,100,162,136,25,18,0,125,162,58,217,232,
11476 235,116,36,162,145,2,226,64,15,136,108,244,117,186,178,81,73,129,113,32,7,
11477 196,54,122,58,221,9,40,165,64,200,144,3,237,17,214,207,79,75,171,37,20,80,
11478 200,144,3,237,17,214,207,79,75,161,37,20,138,23,18,0,124,67,103,167,165,
11479 213,146,138,77,11,137,0,62,33,179,211,210,232,73,69,42,133,196,128,31,10,
11480 183,2,125,89,40,163,5,196,128,31,10,183,2,125,9,40,164,96,200,144,3,224,
11481 221,64,172,157,89,40,163,134,68,128,31,6,234,5,100,232,73,69,35,133,68,128,
11482 31,104,142,182,125,89,40,180,0,168,144,3,237,17,214,207,161,37,22,144,19,
11483 18,0,124,67,103,213,146,139,80,9,137,0,62,33,179,232,73,69,172,5,90,40,153,
11484 59,68,117,179,216,166,192,77,162,137,147,136,108,246,41,180,176,219,69,19,
11485 39,104,142,182,122,58,221,89,41,178,6,218,40,153,59,68,117,179,209,214,232,
11486 73,77,162,6,90,40,153,56,134,207,71,91,171,37,54,152,25,104,162,100,226,27,
11487 61,29,110,132,148,218,160,109,162,137,147,180,71,91,61,61,46,172,148,217,
11488 67,109,20,76,157,162,58,217,233,233,116,36,166,209,67,45,20,76,156,67,103,
11489 167,165,213,146,155,77,12,180,81,50,113,13,158,158,151,66,74,109,84,50,209,
11490 68,201,194,173,192,159,86,74,108,193,150,138,38,78,21,110,4,250,18,83,104,
11491 193,182,138,38,78,13,212,10,201,213,146,155,56,109,162,137,147,131,117,2,
11492 178,116,36,166,209,194,237,20,76,157,162,58,217,245,100,167,16,2,237,20,76,
11493 157,162,58,217,244,36,167,18,2,173,20,76,156,67,103,213,146,156,80,10,180,
11494 81,50,113,13,159,66,74,113,97,175,221,48,216,110,64,4,42,22,189,179,0,196,
11495 133,0,185,80,32,28,78,99,193,18,80,36,4,19,159,141,172,0,178,90,4,74,73,0,
11496 22,209,68,201,187,129,4,2,8,3,132,64,60,36,4,0,91,240,168,177,69,118,144,
11497 157,91,116,116,32,32,1,53,216,221,218,170,139,3,234,219,165,0,255,152,185,
11498 11,251,232,231,188,47,86,227,105,18,1,255,184,170,59,41,92,23,240,110,173,
11499 198,209,208,36,3,253,188,183,177,82,110,80,224,93,122,32,32,4,144,253,170,
11500 34,22,140,7,236,161,25,232,237,105,64,63,230,160,158,102,127,59,205,11,217,
11501 66,51,210,128,127,237,65,60,204,254,119,155,171,197,34,168,48,6,90,194,1,0,
11502 39,75,88,72,8,9,33,186,194,80,64,76,13,214,19,2,130,96,110,150,189,0,65,6,
11503 51,214,20,128,65,17,11,214,19,130,137,121,211,210,211,144,6,39,75,88,80,0,
11504 201,119,235,10,8,41,86,231,71,88,80,129,79,135,186,122,133,224,34,25,69,
11505 234,80,3,91,141,172,40,96,139,113,180,181,133,36,21,110,54,142,134,176,165,
11506 1,176,23,213,47,0,216,134,234,215,128,111,117,181,232,128,209,3,70,230,107,
11507 64,5,139,168,209,235,10,32,36,144,102,235,136,3,146,27,172,40,160,146,132,
11508 103,172,40,192,115,3,117,133,28,22,113,163,69,172,41,103,1,66,188,17,145,
11509 52,168,4,202,113,67,76,130,227,76,194,13,240,108,0,0,83,224,0,2,193,0,104,
11510 146,84,97,48,0,1,94,192,56,169,24,145,179,192,0,5,112,8,56,16,32,128,56,18,
11511 52,125,230,86,147,190,140,28,50,21,13,39,31,23,60,145,158,57,12,141,47,129,
11512 6,155,194,188,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,
11513 163,201,68,14,49,39,199,197,211,116,240,242,113,197,232,18,180,254,36,3,17,
11514 46,18,243,35,100,128,172,156,178,70,163,154,76,34,248,146,164,108,248,75,
11515 204,141,146,28,217,115,137,27,95,27,241,173,236,162,160,224,200,2,206,9,
11516 113,13,148,192,209,18,22,164,146,37,193,57,162,4,249,39,196,128,24,2,178,
11517 66,213,136,68,201,16,77,209,131,31,192,242,88,96,92,191,151,34,100,136,38,
11518 232,255,252,92,221,199,197,12,68,209,82,66,212,11,155,185,41,197,13,55,38,
11519 3,66,213,47,135,254,72,12,162,99,133,116,112,0,1,72,66,14,16,16,50,37,202,
11520 160,150,154,66,14,20,8,57,192,28,24,80,113,50,113,100,105,166,120,248,0,0,
11521 179,1,65,196,201,199,20,178,36,227,224,0,2,208,54,113,240,0,1,100,11,181,
11522 192,0,5,178,1,18,160,65,24,131,20,145,25,188,48,132,122,28,76,146,218,121,
11523 35,180,69,145,132,108,224,31,248,0,0,0,0,0,0,25,188,56,132,122,28,76,146,
11524 218,121,35,180,69,145,132,108,224,31,248,0,0,0,0,0,0,40,160,45,110,23,30,
11525 176,33,184,0,0,183,32,29,235,2,27,199,23,0,0,23,4,51,120,129,8,244,56,153,
11526 37,180,242,71,104,139,35,8,217,192,63,240,0,0,0,0,0,0,51,120,145,8,244,56,
11527 153,37,180,242,71,104,139,35,8,217,192,64,0,0,0,0,0,0,0,51,120,161,8,244,
11528 56,153,37,180,242,71,104,139,35,8,217,192,64,0,0,0,0,0,0,0,51,120,177,8,
11529 244,56,153,37,180,242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,120,193,
11530 8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,120,
11531 209,8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,
11532 120,225,8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,32,0,0,0,0,0,0,
11533 32,227,194,0,97,57,162,4,246,104,5,34,92,35,68,225,161,166,220,16,16,137,
11534 112,52,41,73,29,185,1,65,196,201,197,145,166,153,246,72,3,137,204,120,34,
11535 74,8,199,1,67,17,162,112,201,84,128,97,144,78,25,42,16,131,169,1,205,66,8,
11536 35,68,225,161,166,239,128,0,10,192,64,196,104,156,50,96,0,2,172,73,240,117,
11537 96,57,170,97,4,104,156,52,52,221,240,0,1,82,1,74,9,129,125,240,0,1,82,32,
11538 148,25,174,137,58,23,51,190,0,0,42,69,64,195,32,156,50,96,0,2,160,81,238,2,
11539 3,107,173,218,3,192,
11540 };
11541 #elif defined(DUK_USE_DOUBLE_ME)
11542 DUK_INTERNAL const duk_uint8_t duk_builtins_data[4281] = {
11543 144,148,105,226,32,68,52,228,254,12,104,202,37,132,52,167,194,138,105,245,
11544 124,57,28,211,57,18,64,52,239,126,44,138,111,175,241,164,19,87,145,30,33,
11545 167,22,145,159,8,211,139,9,225,42,5,240,145,139,163,163,8,211,139,10,228,
11546 64,211,19,132,140,93,29,56,70,156,88,119,34,66,146,36,104,137,194,70,46,
11547 142,172,35,78,44,47,146,195,102,11,240,145,139,163,175,8,211,139,9,228,240,
11548 242,112,145,139,163,179,8,211,139,8,237,34,130,118,49,116,118,225,26,48,0,
11549 1,98,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
11550 33,8,66,26,180,105,97,167,68,150,34,33,154,112,0,1,91,247,35,79,111,237,
11551 198,174,232,47,31,23,95,17,13,31,249,96,211,49,50,53,214,77,141,24,0,0,181,
11552 10,228,240,242,15,128,140,65,128,134,188,0,0,90,167,97,181,224,0,2,213,62,
11553 53,224,0,2,213,66,237,120,0,0,181,81,204,107,192,0,5,170,150,67,94,0,0,45,
11554 84,245,90,240,0,1,106,169,162,215,128,0,11,85,93,150,188,0,0,90,171,111,53,
11555 109,22,162,26,48,0,1,84,23,201,146,243,225,26,39,12,145,136,104,192,0,5,61,
11556 11,228,201,121,240,100,19,134,72,196,33,195,14,40,203,112,64,190,76,232,
11557 145,153,136,0,0,31,15,224,0,0,0,25,152,0,0,30,15,224,0,0,0,25,120,144,13,
11558 96,155,194,56,80,206,36,67,141,20,228,70,57,81,206,100,131,156,39,132,168,
11559 23,194,70,46,137,208,21,200,129,166,39,9,24,186,39,72,119,34,66,146,36,104,
11560 137,194,70,46,137,212,23,201,97,179,5,248,72,197,209,58,194,121,60,60,156,
11561 36,98,232,157,129,29,164,80,78,198,46,137,218,146,121,25,71,146,9,209,5,
11562 209,61,48,126,14,138,152,30,67,186,23,143,139,175,131,202,135,228,72,85,
11563 144,83,60,179,30,94,209,233,102,30,98,105,230,103,30,114,121,231,104,30,
11564 122,137,231,233,30,130,153,232,106,30,138,169,232,235,30,144,67,193,25,19,
11565 136,108,207,30,41,224,140,137,194,173,192,153,228,5,242,100,188,248,70,137,
11566 195,36,79,78,47,147,37,231,193,144,78,25,34,122,145,111,36,74,232,176,13,
11567 17,61,234,226,93,207,148,160,84,75,141,7,27,161,32,33,18,225,80,212,76,154,
11568 2,2,70,65,56,100,237,34,140,209,2,67,32,156,50,118,145,64,186,230,61,205,
11569 35,103,155,32,36,141,19,134,78,210,40,206,16,36,70,137,195,39,105,20,11,
11570 174,99,220,210,54,121,210,1,137,33,1,228,207,16,17,70,146,66,3,201,164,32,
11571 0,65,112,152,56,196,159,31,23,77,211,195,201,199,23,160,72,214,246,81,6,12,
11572 73,241,214,111,31,23,60,145,158,56,50,72,81,67,230,232,242,80,19,49,39,199,
11573 89,188,124,92,242,70,120,227,64,194,75,154,72,12,9,73,6,111,21,120,12,40,
11574 144,19,39,25,0,225,144,168,105,56,248,185,228,140,241,200,96,64,100,42,26,
11575 78,62,46,121,35,52,18,92,116,1,36,64,47,158,64,49,98,66,100,156,242,65,23,
11576 196,149,35,103,194,94,100,108,144,230,203,156,64,66,37,201,16,11,32,249,
11577 132,4,34,92,44,93,146,55,152,72,24,137,112,151,153,27,36,5,100,229,144,8,
11578 162,98,92,210,5,76,73,241,214,111,31,23,60,145,158,57,44,48,46,92,185,164,
11579 160,72,151,41,0,50,107,179,244,59,36,93,127,92,6,19,172,3,11,216,0,56,224,
11580 151,29,102,241,241,115,201,25,227,164,64,106,37,199,197,211,116,240,242,
11581 113,197,233,144,40,248,185,228,140,241,196,75,132,109,24,72,128,43,39,84,
11582 129,13,173,161,144,168,105,56,98,78,100,142,214,215,69,1,13,173,161,144,
11583 168,105,57,34,78,100,142,214,215,69,16,67,107,105,110,114,168,254,24,147,
11584 153,35,181,181,212,32,67,107,105,110,114,168,254,72,147,153,35,181,181,212,
11585 36,65,130,3,144,8,26,252,200,13,30,85,16,16,64,90,242,231,192,64,161,163,
11586 203,31,26,172,193,17,4,23,105,159,96,27,172,251,16,32,196,4,14,137,112,17,
11587 136,48,164,28,134,80,215,202,1,132,130,8,12,39,52,64,155,31,24,56,36,1,189,
11588 207,132,0,35,233,35,195,62,3,196,149,36,100,72,160,2,200,232,44,227,0,11,
11589 37,160,68,142,128,36,157,25,200,32,26,79,90,4,73,43,192,122,54,71,65,103,
11590 44,248,14,134,140,151,227,138,231,208,45,96,148,248,134,140,151,227,138,
11591 231,240,1,255,254,10,74,146,56,128,104,4,147,152,72,6,144,28,174,143,8,1,
11592 30,1,165,3,96,31,0,211,3,21,11,153,35,0,211,131,68,131,160,137,16,250,5,
11593 196,131,160,137,200,160,199,156,67,248,0,255,255,65,140,10,48,177,115,56,
11594 35,130,60,19,134,79,89,240,52,177,115,56,39,12,156,123,144,217,251,15,135,
11595 34,167,30,20,170,154,255,232,12,47,244,0,97,28,17,224,39,238,32,40,71,4,
11596 120,39,12,156,4,253,228,5,137,195,39,30,228,54,124,4,253,228,128,194,115,
11597 68,9,252,15,128,232,104,201,126,56,191,35,64,90,193,41,241,13,25,47,199,23,
11598 228,105,3,86,225,1,100,224,156,199,130,36,249,144,10,192,76,71,250,16,15,
11599 18,61,96,17,62,200,3,72,128,136,143,247,32,22,75,64,137,248,64,22,79,90,39,
11600 249,64,38,84,12,167,20,52,223,196,2,230,238,45,214,36,120,32,72,158,208,4,
11601 102,238,45,194,2,201,197,186,196,143,4,9,19,218,0,92,221,202,61,228,143,4,
11602 9,19,218,8,35,55,113,110,16,22,78,81,239,36,120,32,72,158,208,64,73,197,12,
11603 255,0,13,18,60,128,159,212,128,169,76,17,156,185,100,76,255,163,64,65,26,
11604 57,114,200,153,255,70,144,33,13,18,232,50,75,226,104,6,149,3,41,199,246,
11605 130,12,128,28,142,156,120,203,175,158,8,194,207,1,6,81,20,79,88,11,237,84,
11606 11,161,32,127,255,247,191,255,255,255,255,137,235,16,221,170,129,116,36,0,
11607 0,0,0,0,16,0,0,12,196,0,0,15,135,240,0,0,0,2,61,123,164,137,162,164,218,67,
11608 74,134,162,120,128,0,1,224,254,0,0,0,0,71,173,33,129,52,84,155,72,105,80,
11609 212,79,16,0,0,60,63,192,0,0,0,3,244,143,146,22,230,192,0,0,176,60,0,0,0,0,
11610 33,214,2,251,82,1,73,180,134,204,134,36,96,127,255,159,161,255,255,255,255,
11611 144,235,16,221,169,0,164,218,67,102,67,18,48,63,255,207,240,255,255,255,
11612 255,196,60,17,145,56,134,204,241,226,158,8,200,156,42,220,9,158,65,196,34,
11613 92,42,26,137,147,120,64,74,37,196,54,100,49,35,188,36,5,68,184,208,113,187,
11614 194,80,212,75,146,1,73,196,54,100,49,35,188,38,57,37,56,240,0,0,0,0,0,0,0,
11615 0,32,235,248,68,48,156,2,24,94,24,0,243,119,10,139,144,123,242,3,102,238,
11616 18,239,115,72,217,160,11,223,16,23,55,113,241,32,145,36,57,188,18,16,102,3,
11617 5,120,35,34,89,32,15,180,152,173,127,0,218,235,88,0,228,180,227,200,0,0,
11618 248,127,0,0,0,0,197,107,240,64,6,77,220,24,38,78,74,113,67,77,130,4,12,155,
11619 185,52,48,156,148,226,134,155,4,10,194,96,129,132,166,238,45,194,2,201,193,
11620 130,100,228,167,20,52,216,32,113,41,187,139,112,128,178,114,104,97,57,41,
11621 197,13,54,8,32,48,216,32,130,195,224,130,19,97,124,134,23,6,0,57,137,62,77,
11622 12,38,12,0,179,18,124,45,22,190,96,128,141,176,134,28,98,79,180,152,139,
11623 218,45,124,193,1,27,97,16,32,196,159,24,230,204,246,194,40,89,137,62,210,
11624 98,103,92,217,158,216,70,7,49,39,193,130,100,182,17,194,140,73,246,147,16,
11625 250,9,146,216,72,6,49,39,193,131,22,194,72,73,137,62,210,98,31,65,139,97,
11626 40,32,196,159,14,234,70,86,194,88,89,137,62,210,98,63,93,72,202,216,76,10,
11627 49,39,198,33,180,153,37,108,38,134,152,147,237,38,38,117,13,164,201,43,97,
11628 56,40,196,159,36,65,57,163,149,176,158,26,98,79,180,152,165,210,9,205,28,
11629 173,133,0,243,18,124,98,22,180,72,130,115,71,43,97,68,72,196,159,105,49,51,
11630 168,90,209,34,9,205,28,173,133,33,19,18,124,154,24,76,185,164,227,138,89,
11631 18,119,0,7,145,39,201,161,132,188,64,124,137,62,49,11,90,36,65,57,163,149,
11632 210,166,37,34,79,180,152,153,212,45,104,145,4,230,142,87,74,160,84,137,62,
11633 72,130,115,71,43,171,234,134,200,147,237,38,41,116,130,115,71,43,171,235,5,
11634 72,147,227,16,218,76,146,186,254,184,108,137,62,210,98,103,80,218,76,146,
11635 186,254,192,68,137,62,29,212,140,174,207,178,23,34,79,180,152,143,215,82,
11636 50,187,62,208,60,137,62,12,19,37,210,182,21,34,79,180,152,135,208,76,151,
11637 74,224,68,137,62,49,205,153,238,175,186,23,34,79,180,152,153,215,54,103,
11638 186,190,240,92,137,62,22,139,95,48,64,70,235,251,225,210,36,251,73,136,189,
11639 162,215,204,16,17,186,255,2,14,98,79,152,32,35,108,48,64,242,36,249,130,2,
11640 55,75,6,212,224,72,200,51,128,114,108,28,100,128,0,0,0,0,0,0,0,12,110,127,
11641 48,98,115,249,201,117,243,249,195,21,159,206,38,47,63,156,86,8,75,144,94,
11642 82,1,38,73,79,208,67,95,233,1,6,128,14,79,129,186,40,249,18,149,182,207,
11643 144,200,155,188,248,204,105,184,207,142,199,137,175,201,0,159,72,10,5,21,
11644 221,10,120,74,129,124,36,98,232,228,74,81,62,160,20,10,107,186,21,114,32,
11645 105,137,194,70,46,142,68,165,19,235,1,64,170,187,161,119,34,66,146,36,104,
11646 137,194,70,46,142,68,165,19,236,1,64,174,187,161,95,37,134,204,23,225,35,
11647 23,71,34,82,137,246,128,160,89,93,208,167,147,195,201,194,70,46,142,68,165,
11648 19,238,1,64,182,187,161,71,105,20,19,177,139,163,145,41,68,16,7,6,15,82,70,
11649 72,115,96,0,15,106,32,0,0,0,0,91,60,165,195,201,194,8,134,149,216,162,0,
11650 192,41,225,8,2,48,177,36,1,149,13,196,15,0,200,209,97,199,128,99,32,176,
11651 195,192,113,57,143,0,167,133,32,230,80,28,202,139,175,238,2,48,189,192,20,
11652 1,119,80,87,193,186,129,89,56,72,197,209,200,193,185,35,23,71,109,13,219,
11653 36,98,232,237,156,13,26,208,211,14,102,19,87,137,91,95,128,0,10,96,24,92,0,
11654 0,83,2,53,56,0,0,165,3,28,204,160,160,226,100,226,200,211,76,241,240,0,1,
11655 102,8,22,75,64,137,73,20,230,105,133,7,19,39,22,70,154,103,143,128,0,11,48,
11656 20,28,76,156,113,75,34,78,62,0,0,45,3,103,31,0,0,22,65,44,57,137,62,33,179,
11657 216,162,152,192,131,18,124,162,27,61,138,41,108,32,196,159,16,217,232,235,
11658 81,76,104,73,137,62,81,13,158,142,181,20,184,16,98,79,136,108,244,244,168,
11659 166,56,36,196,159,40,134,207,79,74,138,93,10,49,39,194,173,192,158,158,149,
11660 20,188,20,98,79,133,91,129,61,109,74,41,124,30,68,159,16,217,236,83,108,96,
11661 68,137,62,81,13,158,197,54,182,17,34,79,136,108,244,117,169,182,52,38,68,
11662 159,40,134,207,71,90,155,92,8,145,39,196,54,122,122,84,219,28,19,34,79,148,
11663 67,103,167,165,77,174,133,72,147,225,86,224,79,79,74,155,94,10,145,39,194,
11664 173,192,158,182,165,54,190,206,25,212,35,208,226,100,150,211,201,29,162,44,
11665 140,35,103,0,0,3,192,252,0,0,0,0,206,25,228,35,208,226,100,150,211,201,29,
11666 162,44,140,35,103,0,0,3,192,252,0,0,0,0,206,25,244,35,208,226,100,150,211,
11667 201,29,162,44,140,35,103,0,0,3,192,252,0,0,0,0,206,26,4,35,208,226,100,150,
11668 211,201,29,162,44,140,35,103,0,0,0,1,0,0,0,0,0,206,26,20,35,208,226,100,
11669 150,211,201,29,162,44,140,35,103,0,0,0,1,0,0,0,0,0,206,26,36,35,208,226,
11670 100,150,211,201,29,162,44,140,35,103,0,0,0,65,0,0,0,0,0,206,26,52,35,208,
11671 226,100,150,211,201,29,162,44,140,35,103,0,0,0,65,0,0,0,0,0,206,26,68,35,
11672 208,226,100,150,211,201,29,162,44,140,35,103,0,0,0,65,0,0,0,0,0,206,26,84,
11673 35,208,226,100,150,211,201,29,162,44,140,35,103,0,0,0,129,0,0,0,0,0,195,
11674 154,99,16,38,36,0,251,68,117,179,216,162,128,68,72,1,241,13,158,197,20,150,
11675 25,18,0,125,162,58,217,232,235,117,100,162,136,25,18,0,125,162,58,217,232,
11676 235,116,36,162,145,2,226,64,15,136,108,244,117,186,178,81,73,129,113,32,7,
11677 196,54,122,58,221,9,40,165,64,200,144,3,237,17,214,207,79,75,171,37,20,80,
11678 200,144,3,237,17,214,207,79,75,161,37,20,138,23,18,0,124,67,103,167,165,
11679 213,146,138,77,11,137,0,62,33,179,211,210,232,73,69,42,133,196,128,31,10,
11680 183,2,125,89,40,163,5,196,128,31,10,183,2,125,9,40,164,96,200,144,3,224,
11681 221,64,172,157,89,40,163,134,68,128,31,6,234,5,100,232,73,69,35,133,68,128,
11682 31,104,142,182,125,89,40,180,0,168,144,3,237,17,214,207,161,37,22,144,19,
11683 18,0,124,67,103,213,146,139,80,9,137,0,62,33,179,232,73,69,172,5,90,40,153,
11684 59,68,117,179,216,166,192,77,162,137,147,136,108,246,41,180,176,219,69,19,
11685 39,104,142,182,122,58,221,89,41,178,6,218,40,153,59,68,117,179,209,214,232,
11686 73,77,162,6,90,40,153,56,134,207,71,91,171,37,54,152,25,104,162,100,226,27,
11687 61,29,110,132,148,218,160,109,162,137,147,180,71,91,61,61,46,172,148,217,
11688 67,109,20,76,157,162,58,217,233,233,116,36,166,209,67,45,20,76,156,67,103,
11689 167,165,213,146,155,77,12,180,81,50,113,13,158,158,151,66,74,109,84,50,209,
11690 68,201,194,173,192,159,86,74,108,193,150,138,38,78,21,110,4,250,18,83,104,
11691 193,182,138,38,78,13,212,10,201,213,146,155,56,109,162,137,147,131,117,2,
11692 178,116,36,166,209,194,237,20,76,157,162,58,217,245,100,167,16,2,237,20,76,
11693 157,162,58,217,244,36,167,18,2,173,20,76,156,67,103,213,146,156,80,10,180,
11694 81,50,113,13,159,66,74,113,97,175,221,48,216,110,64,4,42,22,189,179,0,196,
11695 133,0,185,80,32,28,78,99,193,18,80,36,4,19,159,141,172,0,178,90,4,74,73,0,
11696 22,209,68,201,187,129,4,2,8,3,132,64,60,36,0,171,240,84,6,149,113,72,176,
11697 157,91,116,116,32,88,181,129,32,11,42,218,221,131,234,219,165,1,8,187,152,
11698 255,188,231,235,248,47,86,227,105,18,2,56,175,185,255,244,17,91,40,110,173,
11699 198,209,208,36,7,188,189,179,240,238,82,97,80,93,122,32,125,144,132,160,12,
11700 22,162,42,7,236,161,25,232,237,105,64,158,160,230,63,205,59,127,102,11,217,
11701 66,51,210,129,61,65,236,127,154,118,254,205,171,197,34,168,48,6,90,194,1,0,
11702 39,75,88,72,8,9,33,186,194,80,64,76,13,214,19,2,130,96,110,150,189,0,65,6,
11703 51,214,20,128,65,17,11,214,19,130,137,121,211,210,211,144,6,39,75,88,80,0,
11704 201,119,235,10,8,41,86,231,71,88,80,129,79,135,186,122,133,224,34,25,69,
11705 234,80,3,91,141,172,40,96,139,113,180,181,133,36,21,110,54,142,134,176,165,
11706 1,176,23,213,47,0,216,134,234,215,128,111,117,181,232,128,209,3,70,230,107,
11707 64,5,139,168,209,235,10,32,36,144,102,235,136,3,146,27,172,40,160,146,132,
11708 103,172,40,192,115,3,117,133,28,22,113,163,69,172,41,103,1,66,188,17,145,
11709 52,168,4,202,113,67,76,130,227,76,194,13,240,108,0,0,83,224,0,2,193,0,104,
11710 146,84,97,48,0,1,94,192,56,169,24,145,179,192,0,5,112,8,56,16,32,128,56,18,
11711 52,125,230,86,147,190,140,28,50,21,13,39,31,23,60,145,158,57,12,141,47,129,
11712 6,155,194,188,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,
11713 163,201,68,14,49,39,199,197,211,116,240,242,113,197,232,18,180,254,36,3,17,
11714 46,18,243,35,100,128,172,156,178,70,163,154,76,34,248,146,164,108,248,75,
11715 204,141,146,28,217,115,137,27,95,27,241,173,236,162,160,224,200,2,206,9,
11716 113,13,148,192,209,18,22,164,146,37,193,57,162,4,249,39,196,128,24,2,178,
11717 66,213,136,68,201,16,77,209,131,31,192,242,88,96,92,191,151,34,100,136,38,
11718 232,255,252,92,221,199,197,12,68,209,82,66,212,11,155,185,41,197,13,55,38,
11719 3,66,213,47,135,254,72,12,162,99,133,116,112,0,1,72,66,14,16,16,50,37,202,
11720 160,150,154,66,14,20,8,57,192,28,24,80,113,50,113,100,105,166,120,248,0,0,
11721 179,1,65,196,201,199,20,178,36,227,224,0,2,208,54,113,240,0,1,100,11,181,
11722 192,0,5,178,1,18,160,65,24,131,20,145,25,188,48,132,122,28,76,146,218,121,
11723 35,180,69,145,132,108,224,0,0,120,31,128,0,0,0,25,188,56,132,122,28,76,146,
11724 218,121,35,180,69,145,132,108,224,0,0,120,31,128,0,0,0,40,160,45,110,23,30,
11725 176,33,184,0,0,183,32,29,235,2,27,199,23,0,0,23,4,51,120,129,8,244,56,153,
11726 37,180,242,71,104,139,35,8,217,192,0,0,240,63,0,0,0,0,51,120,145,8,244,56,
11727 153,37,180,242,71,104,139,35,8,217,192,0,0,0,64,0,0,0,0,51,120,161,8,244,
11728 56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,64,0,0,0,0,51,120,177,8,
11729 244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,120,193,
11730 8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,120,
11731 209,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,
11732 120,225,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,32,64,0,0,0,0,
11733 32,227,194,0,97,57,162,4,246,104,5,34,92,35,68,225,161,166,220,16,16,137,
11734 112,52,41,73,29,185,1,65,196,201,197,145,166,153,246,72,3,137,204,120,34,
11735 74,8,199,1,67,17,162,112,201,84,128,97,144,78,25,42,16,131,169,1,205,66,8,
11736 35,68,225,161,166,239,128,0,10,192,64,196,104,156,50,96,0,2,172,73,240,117,
11737 96,57,170,97,4,104,156,52,52,221,240,0,1,82,1,74,9,129,125,240,0,1,82,32,
11738 148,25,174,137,58,23,51,190,0,0,42,69,64,195,32,156,50,96,0,2,160,81,238,2,
11739 3,107,173,218,3,192,
11740 };
11741 #else
11742 #error invalid endianness defines
11743 #endif
11744 #endif  /* DUK_USE_ROM_OBJECTS */
11745 
11746 /* automatic undefs */
11747 #undef DUK__REFCINIT
11748 /*
11749  *  Error and fatal handling.
11750  */
11751 
11752 /* #include duk_internal.h -> already included */
11753 
11754 #define DUK__ERRFMT_BUFSIZE  256  /* size for formatting buffers */
11755 
11756 #if defined(DUK_USE_VERBOSE_ERRORS)
11757 
duk_err_handle_error_fmt(duk_hthread * thr,const char * filename,duk_uint_t line_and_code,const char * fmt,...)11758 DUK_INTERNAL DUK_COLD void duk_err_handle_error_fmt(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *fmt, ...) {
11759 	va_list ap;
11760 	char msg[DUK__ERRFMT_BUFSIZE];
11761 	va_start(ap, fmt);
11762 	(void) DUK_VSNPRINTF(msg, sizeof(msg), fmt, ap);
11763 	msg[sizeof(msg) - 1] = (char) 0;
11764 	duk_err_create_and_throw(thr, (duk_errcode_t) (line_and_code >> 24), msg, filename, (duk_int_t) (line_and_code & 0x00ffffffL));
11765 	va_end(ap);  /* dead code, but ensures portability (see Linux man page notes) */
11766 }
11767 
duk_err_handle_error(duk_hthread * thr,const char * filename,duk_uint_t line_and_code,const char * msg)11768 DUK_INTERNAL DUK_COLD void duk_err_handle_error(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *msg) {
11769 	duk_err_create_and_throw(thr, (duk_errcode_t) (line_and_code >> 24), msg, filename, (duk_int_t) (line_and_code & 0x00ffffffL));
11770 }
11771 
11772 #else  /* DUK_USE_VERBOSE_ERRORS */
11773 
duk_err_handle_error(duk_hthread * thr,duk_errcode_t code)11774 DUK_INTERNAL DUK_COLD void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code) {
11775 	duk_err_create_and_throw(thr, code);
11776 }
11777 
11778 #endif  /* DUK_USE_VERBOSE_ERRORS */
11779 
11780 /*
11781  *  Error throwing helpers
11782  */
11783 
11784 #if defined(DUK_USE_VERBOSE_ERRORS)
11785 #if defined(DUK_USE_PARANOID_ERRORS)
duk_err_require_type_index(duk_hthread * thr,const char * filename,duk_int_t linenumber,duk_idx_t idx,const char * expect_name)11786 DUK_INTERNAL DUK_COLD void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx, const char *expect_name) {
11787 	DUK_ERROR_RAW_FMT3(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
11788 	                   expect_name, duk_get_type_name(thr, idx), (long) idx);
11789 }
11790 #else
duk_err_require_type_index(duk_hthread * thr,const char * filename,duk_int_t linenumber,duk_idx_t idx,const char * expect_name)11791 DUK_INTERNAL DUK_COLD void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx, const char *expect_name) {
11792 	DUK_ERROR_RAW_FMT3(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
11793 	                   expect_name, duk_push_string_readable(thr, idx), (long) idx);
11794 }
11795 #endif
duk_err_error_internal(duk_hthread * thr,const char * filename,duk_int_t linenumber)11796 DUK_INTERNAL DUK_COLD void duk_err_error_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11797 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ERROR, DUK_STR_INTERNAL_ERROR);
11798 }
duk_err_error_alloc_failed(duk_hthread * thr,const char * filename,duk_int_t linenumber)11799 DUK_INTERNAL DUK_COLD void duk_err_error_alloc_failed(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11800 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ERROR, DUK_STR_ALLOC_FAILED);
11801 }
duk_err_error(duk_hthread * thr,const char * filename,duk_int_t linenumber,const char * message)11802 DUK_INTERNAL DUK_COLD void duk_err_error(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
11803 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ERROR, message);
11804 }
duk_err_range(duk_hthread * thr,const char * filename,duk_int_t linenumber,const char * message)11805 DUK_INTERNAL DUK_COLD void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
11806 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, message);
11807 }
duk_err_range_index(duk_hthread * thr,const char * filename,duk_int_t linenumber,duk_idx_t idx)11808 DUK_INTERNAL DUK_COLD void duk_err_range_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx) {
11809 	DUK_ERROR_RAW_FMT1(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, "invalid stack index %ld", (long) (idx));
11810 }
duk_err_range_push_beyond(duk_hthread * thr,const char * filename,duk_int_t linenumber)11811 DUK_INTERNAL DUK_COLD void duk_err_range_push_beyond(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11812 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
11813 }
duk_err_type_invalid_args(duk_hthread * thr,const char * filename,duk_int_t linenumber)11814 DUK_INTERNAL DUK_COLD void duk_err_type_invalid_args(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11815 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_ARGS);
11816 }
duk_err_type_invalid_state(duk_hthread * thr,const char * filename,duk_int_t linenumber)11817 DUK_INTERNAL DUK_COLD void duk_err_type_invalid_state(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11818 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_STATE);
11819 }
duk_err_type_invalid_trap_result(duk_hthread * thr,const char * filename,duk_int_t linenumber)11820 DUK_INTERNAL DUK_COLD void duk_err_type_invalid_trap_result(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11821 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_TRAP_RESULT);
11822 }
11823 #else
11824 /* The file/line arguments are NULL and 0, they're ignored by DUK_ERROR_RAW()
11825  * when non-verbose errors are used.
11826  */
11827 
11828 DUK_NORETURN(DUK_LOCAL_DECL void duk__err_shared(duk_hthread *thr, duk_errcode_t code));
duk__err_shared(duk_hthread * thr,duk_errcode_t code)11829 DUK_LOCAL void duk__err_shared(duk_hthread *thr, duk_errcode_t code) {
11830 	DUK_ERROR_RAW(thr, NULL, 0, code, NULL);
11831 }
duk_err_error(duk_hthread * thr)11832 DUK_INTERNAL DUK_COLD void duk_err_error(duk_hthread *thr) {
11833 	duk__err_shared(thr, DUK_ERR_ERROR);
11834 }
duk_err_range(duk_hthread * thr)11835 DUK_INTERNAL DUK_COLD void duk_err_range(duk_hthread *thr) {
11836 	duk__err_shared(thr, DUK_ERR_RANGE_ERROR);
11837 }
duk_err_eval(duk_hthread * thr)11838 DUK_INTERNAL DUK_COLD void duk_err_eval(duk_hthread *thr) {
11839 	duk__err_shared(thr, DUK_ERR_EVAL_ERROR);
11840 }
duk_err_reference(duk_hthread * thr)11841 DUK_INTERNAL DUK_COLD void duk_err_reference(duk_hthread *thr) {
11842 	duk__err_shared(thr, DUK_ERR_REFERENCE_ERROR);
11843 }
duk_err_syntax(duk_hthread * thr)11844 DUK_INTERNAL DUK_COLD void duk_err_syntax(duk_hthread *thr) {
11845 	duk__err_shared(thr, DUK_ERR_SYNTAX_ERROR);
11846 }
duk_err_type(duk_hthread * thr)11847 DUK_INTERNAL DUK_COLD void duk_err_type(duk_hthread *thr) {
11848 	duk__err_shared(thr, DUK_ERR_TYPE_ERROR);
11849 }
duk_err_uri(duk_hthread * thr)11850 DUK_INTERNAL DUK_COLD void duk_err_uri(duk_hthread *thr) {
11851 	duk__err_shared(thr, DUK_ERR_URI_ERROR);
11852 }
11853 #endif
11854 
11855 /*
11856  *  Default fatal error handler
11857  */
11858 
duk_default_fatal_handler(void * udata,const char * msg)11859 DUK_INTERNAL DUK_COLD void duk_default_fatal_handler(void *udata, const char *msg) {
11860 	DUK_UNREF(udata);
11861 	DUK_UNREF(msg);
11862 
11863 	msg = msg ? msg : "NULL";
11864 
11865 #if defined(DUK_USE_FATAL_HANDLER)
11866 	/* duk_config.h provided a custom default fatal handler. */
11867 	DUK_D(DUK_DPRINT("custom default fatal error handler called: %s", msg));
11868 	DUK_USE_FATAL_HANDLER(udata, msg);
11869 #elif defined(DUK_USE_CPP_EXCEPTIONS)
11870 	/* With C++ use a duk_fatal_exception which user code can catch in
11871 	 * a natural way.
11872 	 */
11873 	DUK_D(DUK_DPRINT("built-in default C++ fatal error handler called: %s", msg));
11874 	throw duk_fatal_exception(msg);
11875 #else
11876 	/* Default behavior is to abort() on error.  There's no printout
11877 	 * which makes this awkward, so it's always recommended to use an
11878 	 * explicit fatal error handler.
11879 	 *
11880 	 * ====================================================================
11881 	 * NOTE: If you are seeing this, you are most likely dealing with an
11882 	 * uncaught error.  You should provide a fatal error handler in Duktape
11883 	 * heap creation, and should consider using a protected call as your
11884 	 * first call into an empty Duktape context to properly handle errors.
11885 	 * See:
11886 	 *   - http://duktape.org/guide.html#error-handling
11887 	 *   - http://wiki.duktape.org/HowtoFatalErrors.html
11888 	 *   - http://duktape.org/api.html#taglist-protected
11889 	 * ====================================================================
11890 	 */
11891 	DUK_D(DUK_DPRINT("built-in default fatal error handler called: %s", msg));
11892 	DUK_ABORT();
11893 #endif
11894 
11895 	DUK_D(DUK_DPRINT("fatal error handler returned, enter forever loop"));
11896 	for (;;) {
11897 		/* Loop forever to ensure we don't return. */
11898 	}
11899 }
11900 
11901 /* automatic undefs */
11902 #undef DUK__ERRFMT_BUFSIZE
11903 /*
11904  *  Various Unicode help functions for character classification predicates,
11905  *  case conversion, decoding, etc.
11906  */
11907 
11908 /* #include duk_internal.h -> already included */
11909 
11910 /*
11911  *  Fast path tables
11912  */
11913 
11914 #if defined(DUK_USE_IDCHAR_FASTPATH)
11915 DUK_INTERNAL const duk_int8_t duk_is_idchar_tab[128] = {
11916 	/* 0: not IdentifierStart or IdentifierPart
11917 	 * 1: IdentifierStart and IdentifierPart
11918 	 * -1: IdentifierPart only
11919 	 */
11920 	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   /* 0x00...0x0f */
11921 	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   /* 0x10...0x1f */
11922 	0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   /* 0x20...0x2f */
11923 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,  0,  0,  0,  0,  0,   /* 0x30...0x3f */
11924 	0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,   /* 0x40...0x4f */
11925 	1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  1,   /* 0x50...0x5f */
11926 	0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,   /* 0x60...0x6f */
11927 	1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0    /* 0x70...0x7f */
11928 };
11929 #endif
11930 
11931 /*
11932  *  XUTF-8 and CESU-8 encoding/decoding
11933  */
11934 
duk_unicode_get_xutf8_length(duk_ucodepoint_t cp)11935 DUK_INTERNAL duk_small_int_t duk_unicode_get_xutf8_length(duk_ucodepoint_t cp) {
11936 	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
11937 	if (x < 0x80UL) {
11938 		/* 7 bits */
11939 		return 1;
11940 	} else if (x < 0x800UL) {
11941 		/* 11 bits */
11942 		return 2;
11943 	} else if (x < 0x10000UL) {
11944 		/* 16 bits */
11945 		return 3;
11946 	} else if (x < 0x200000UL) {
11947 		/* 21 bits */
11948 		return 4;
11949 	} else if (x < 0x4000000UL) {
11950 		/* 26 bits */
11951 		return 5;
11952 	} else if (x < (duk_ucodepoint_t) 0x80000000UL) {
11953 		/* 31 bits */
11954 		return 6;
11955 	} else {
11956 		/* 36 bits */
11957 		return 7;
11958 	}
11959 }
11960 
11961 #if defined(DUK_USE_ASSERTIONS)
duk_unicode_get_cesu8_length(duk_ucodepoint_t cp)11962 DUK_INTERNAL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp) {
11963 	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
11964 	if (x < 0x80UL) {
11965 		/* 7 bits */
11966 		return 1;
11967 	} else if (x < 0x800UL) {
11968 		/* 11 bits */
11969 		return 2;
11970 	} else if (x < 0x10000UL) {
11971 		/* 16 bits */
11972 		return 3;
11973 	} else {
11974 		/* Encoded as surrogate pair, each encoding to 3 bytes for
11975 		 * 6 bytes total.  Codepoints above U+10FFFF encode as 6 bytes
11976 		 * too, see duk_unicode_encode_cesu8().
11977 		  */
11978 		return 3 + 3;
11979 	}
11980 }
11981 #endif  /* DUK_USE_ASSERTIONS */
11982 
11983 DUK_INTERNAL const duk_uint8_t duk_unicode_xutf8_markers[7] = {
11984 	0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe
11985 };
11986 
11987 /* Encode to extended UTF-8; 'out' must have space for at least
11988  * DUK_UNICODE_MAX_XUTF8_LENGTH bytes.  Allows encoding of any
11989  * 32-bit (unsigned) codepoint.
11990  */
duk_unicode_encode_xutf8(duk_ucodepoint_t cp,duk_uint8_t * out)11991 DUK_INTERNAL duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_uint8_t *out) {
11992 	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
11993 	duk_small_int_t len;
11994 	duk_uint8_t marker;
11995 	duk_small_int_t i;
11996 
11997 	len = duk_unicode_get_xutf8_length(cp);
11998 	DUK_ASSERT(len > 0);
11999 
12000 	marker = duk_unicode_xutf8_markers[len - 1];  /* 64-bit OK because always >= 0 */
12001 
12002 	i = len;
12003 	DUK_ASSERT(i > 0);
12004 	do {
12005 		i--;
12006 		if (i > 0) {
12007 			out[i] = (duk_uint8_t) (0x80 + (x & 0x3f));
12008 			x >>= 6;
12009 		} else {
12010 			/* Note: masking of 'x' is not necessary because of
12011 			 * range check and shifting -> no bits overlapping
12012 			 * the marker should be set.
12013 			 */
12014 			out[0] = (duk_uint8_t) (marker + x);
12015 		}
12016 	} while (i > 0);
12017 
12018 	return len;
12019 }
12020 
12021 /* Encode to CESU-8; 'out' must have space for at least
12022  * DUK_UNICODE_MAX_CESU8_LENGTH bytes; codepoints above U+10FFFF
12023  * will encode to garbage but won't overwrite the output buffer.
12024  */
duk_unicode_encode_cesu8(duk_ucodepoint_t cp,duk_uint8_t * out)12025 DUK_INTERNAL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_uint8_t *out) {
12026 	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
12027 	duk_small_int_t len;
12028 
12029 	if (x < 0x80UL) {
12030 		out[0] = (duk_uint8_t) x;
12031 		len = 1;
12032 	} else if (x < 0x800UL) {
12033 		out[0] = (duk_uint8_t) (0xc0 + ((x >> 6) & 0x1f));
12034 		out[1] = (duk_uint8_t) (0x80 + (x & 0x3f));
12035 		len = 2;
12036 	} else if (x < 0x10000UL) {
12037 		/* surrogate pairs get encoded here */
12038 		out[0] = (duk_uint8_t) (0xe0 + ((x >> 12) & 0x0f));
12039 		out[1] = (duk_uint8_t) (0x80 + ((x >> 6) & 0x3f));
12040 		out[2] = (duk_uint8_t) (0x80 + (x & 0x3f));
12041 		len = 3;
12042 	} else {
12043 		/*
12044 		 *  Unicode codepoints above U+FFFF are encoded as surrogate
12045 		 *  pairs here.  This ensures that all CESU-8 codepoints are
12046 		 *  16-bit values as expected in ECMAScript.  The surrogate
12047 		 *  pairs always get a 3-byte encoding (each) in CESU-8.
12048 		 *  See: http://en.wikipedia.org/wiki/Surrogate_pair
12049 		 *
12050 		 *  20-bit codepoint, 10 bits (A and B) per surrogate pair:
12051 		 *
12052 		 *    x = 0b00000000 0000AAAA AAAAAABB BBBBBBBB
12053 		 *  sp1 = 0b110110AA AAAAAAAA  (0xd800 + ((x >> 10) & 0x3ff))
12054 		 *  sp2 = 0b110111BB BBBBBBBB  (0xdc00 + (x & 0x3ff))
12055 		 *
12056 		 *  Encoded into CESU-8:
12057 		 *
12058 		 *  sp1 -> 0b11101101  (0xe0 + ((sp1 >> 12) & 0x0f))
12059 		 *      -> 0b1010AAAA  (0x80 + ((sp1 >> 6) & 0x3f))
12060 		 *      -> 0b10AAAAAA  (0x80 + (sp1 & 0x3f))
12061 		 *  sp2 -> 0b11101101  (0xe0 + ((sp2 >> 12) & 0x0f))
12062 		 *      -> 0b1011BBBB  (0x80 + ((sp2 >> 6) & 0x3f))
12063 		 *      -> 0b10BBBBBB  (0x80 + (sp2 & 0x3f))
12064 		 *
12065 		 *  Note that 0x10000 must be subtracted first.  The code below
12066 		 *  avoids the sp1, sp2 temporaries which saves around 20 bytes
12067 		 *  of code.
12068 		 */
12069 
12070 		x -= 0x10000UL;
12071 
12072 		out[0] = (duk_uint8_t) (0xed);
12073 		out[1] = (duk_uint8_t) (0xa0 + ((x >> 16) & 0x0f));
12074 		out[2] = (duk_uint8_t) (0x80 + ((x >> 10) & 0x3f));
12075 		out[3] = (duk_uint8_t) (0xed);
12076 		out[4] = (duk_uint8_t) (0xb0 + ((x >> 6) & 0x0f));
12077 		out[5] = (duk_uint8_t) (0x80 + (x & 0x3f));
12078 		len = 6;
12079 	}
12080 
12081 	return len;
12082 }
12083 
12084 /* Decode helper.  Return zero on error. */
duk_unicode_decode_xutf8(duk_hthread * thr,const duk_uint8_t ** ptr,const duk_uint8_t * ptr_start,const duk_uint8_t * ptr_end,duk_ucodepoint_t * out_cp)12085 DUK_INTERNAL duk_small_int_t duk_unicode_decode_xutf8(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end, duk_ucodepoint_t *out_cp) {
12086 	const duk_uint8_t *p;
12087 	duk_uint32_t res;
12088 	duk_uint_fast8_t ch;
12089 	duk_small_int_t n;
12090 
12091 	DUK_UNREF(thr);
12092 
12093 	p = *ptr;
12094 	if (p < ptr_start || p >= ptr_end) {
12095 		goto fail;
12096 	}
12097 
12098 	/*
12099 	 *  UTF-8 decoder which accepts longer than standard byte sequences.
12100 	 *  This allows full 32-bit code points to be used.
12101 	 */
12102 
12103 	ch = (duk_uint_fast8_t) (*p++);
12104 	if (ch < 0x80) {
12105 		/* 0xxx xxxx   [7 bits] */
12106 		res = (duk_uint32_t) (ch & 0x7f);
12107 		n = 0;
12108 	} else if (ch < 0xc0) {
12109 		/* 10xx xxxx -> invalid */
12110 		goto fail;
12111 	} else if (ch < 0xe0) {
12112 		/* 110x xxxx   10xx xxxx   [11 bits] */
12113 		res = (duk_uint32_t) (ch & 0x1f);
12114 		n = 1;
12115 	} else if (ch < 0xf0) {
12116 		/* 1110 xxxx   10xx xxxx   10xx xxxx   [16 bits] */
12117 		res = (duk_uint32_t) (ch & 0x0f);
12118 		n = 2;
12119 	} else if (ch < 0xf8) {
12120 		/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx   [21 bits] */
12121 		res = (duk_uint32_t) (ch & 0x07);
12122 		n = 3;
12123 	} else if (ch < 0xfc) {
12124 		/* 1111 10xx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [26 bits] */
12125 		res = (duk_uint32_t) (ch & 0x03);
12126 		n = 4;
12127 	} else if (ch < 0xfe) {
12128 		/* 1111 110x   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [31 bits] */
12129 		res = (duk_uint32_t) (ch & 0x01);
12130 		n = 5;
12131 	} else if (ch < 0xff) {
12132 		/* 1111 1110   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [36 bits] */
12133 		res = (duk_uint32_t) (0);
12134 		n = 6;
12135 	} else {
12136 		/* 8-byte format could be:
12137 		 * 1111 1111   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [41 bits]
12138 		 *
12139 		 * However, this format would not have a zero bit following the
12140 		 * leading one bits and would not allow 0xFF to be used as an
12141 		 * "invalid xutf-8" marker for internal keys.  Further, 8-byte
12142 		 * encodings (up to 41 bit code points) are not currently needed.
12143 		 */
12144 		goto fail;
12145 	}
12146 
12147 	DUK_ASSERT(p >= ptr_start);  /* verified at beginning */
12148 	if (p + n > ptr_end) {
12149 		/* check pointer at end */
12150 		goto fail;
12151 	}
12152 
12153 	while (n > 0) {
12154 		DUK_ASSERT(p >= ptr_start && p < ptr_end);
12155 		ch = (duk_uint_fast8_t) (*p++);
12156 #if 0
12157 		if (ch & 0xc0 != 0x80) {
12158 			/* not a continuation byte */
12159 			p--;
12160 			*ptr = p;
12161 			*out_cp = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
12162 			return 1;
12163 		}
12164 #endif
12165 		res = (res << 6) + (duk_uint32_t) (ch & 0x3f);
12166 		n--;
12167 	}
12168 
12169 	*ptr = p;
12170 	*out_cp = res;
12171 	return 1;
12172 
12173  fail:
12174 	return 0;
12175 }
12176 
12177 /* used by e.g. duk_regexp_executor.c, string built-ins */
duk_unicode_decode_xutf8_checked(duk_hthread * thr,const duk_uint8_t ** ptr,const duk_uint8_t * ptr_start,const duk_uint8_t * ptr_end)12178 DUK_INTERNAL duk_ucodepoint_t duk_unicode_decode_xutf8_checked(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end) {
12179 	duk_ucodepoint_t cp;
12180 
12181 	if (duk_unicode_decode_xutf8(thr, ptr, ptr_start, ptr_end, &cp)) {
12182 		return cp;
12183 	}
12184 	DUK_ERROR_INTERNAL(thr);
12185 	DUK_WO_NORETURN(return 0;);
12186 }
12187 
12188 /* Compute (extended) utf-8 length without codepoint encoding validation,
12189  * used for string interning.
12190  *
12191  * NOTE: This algorithm is performance critical, more so than string hashing
12192  * in some cases.  It is needed when interning a string and needs to scan
12193  * every byte of the string with no skipping.  Having an ASCII fast path
12194  * is useful if possible in the algorithm.  The current algorithms were
12195  * chosen from several variants, based on x64 gcc -O2 testing.  See:
12196  * https://github.com/svaarala/duktape/pull/422
12197  *
12198  * NOTE: must match tools/dukutil.py:duk_unicode_unvalidated_utf8_length().
12199  */
12200 
12201 #if defined(DUK_USE_PREFER_SIZE)
12202 /* Small variant; roughly 150 bytes smaller than the fast variant. */
duk_unicode_unvalidated_utf8_length(const duk_uint8_t * data,duk_size_t blen)12203 DUK_INTERNAL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen) {
12204 	const duk_uint8_t *p;
12205 	const duk_uint8_t *p_end;
12206 	duk_size_t ncont;
12207 	duk_size_t clen;
12208 
12209 	p = data;
12210 	p_end = data + blen;
12211 	ncont = 0;
12212 	while (p != p_end) {
12213 		duk_uint8_t x;
12214 		x = *p++;
12215 		if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
12216 			ncont++;
12217 		}
12218 	}
12219 
12220 	DUK_ASSERT(ncont <= blen);
12221 	clen = blen - ncont;
12222 	DUK_ASSERT(clen <= blen);
12223 	return clen;
12224 }
12225 #else  /* DUK_USE_PREFER_SIZE */
12226 /* This seems like a good overall approach.  Fast path for ASCII in 4 byte
12227  * blocks.
12228  */
duk_unicode_unvalidated_utf8_length(const duk_uint8_t * data,duk_size_t blen)12229 DUK_INTERNAL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen) {
12230 	const duk_uint8_t *p;
12231 	const duk_uint8_t *p_end;
12232 	const duk_uint32_t *p32_end;
12233 	const duk_uint32_t *p32;
12234 	duk_size_t ncont;
12235 	duk_size_t clen;
12236 
12237 	ncont = 0;  /* number of continuation (non-initial) bytes in [0x80,0xbf] */
12238 	p = data;
12239 	p_end = data + blen;
12240 	if (blen < 16) {
12241 		goto skip_fastpath;
12242 	}
12243 
12244 	/* Align 'p' to 4; the input data may have arbitrary alignment.
12245 	 * End of string check not needed because blen >= 16.
12246 	 */
12247 	while (((duk_size_t) (const void *) p) & 0x03U) {
12248 		duk_uint8_t x;
12249 		x = *p++;
12250 		if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
12251 			ncont++;
12252 		}
12253 	}
12254 
12255 	/* Full, aligned 4-byte reads. */
12256 	p32_end = (const duk_uint32_t *) (const void *) (p + ((duk_size_t) (p_end - p) & (duk_size_t) (~0x03)));
12257 	p32 = (const duk_uint32_t *) (const void *) p;
12258 	while (p32 != (const duk_uint32_t *) p32_end) {
12259 		duk_uint32_t x;
12260 		x = *p32++;
12261 		if (DUK_LIKELY((x & 0x80808080UL) == 0)) {
12262 			;  /* ASCII fast path */
12263 		} else {
12264 			/* Flip highest bit of each byte which changes
12265 			 * the bit pattern 10xxxxxx into 00xxxxxx which
12266 			 * allows an easy bit mask test.
12267 			 */
12268 			x ^= 0x80808080UL;
12269 			if (DUK_UNLIKELY(!(x & 0xc0000000UL))) {
12270 				ncont++;
12271 			}
12272 			if (DUK_UNLIKELY(!(x & 0x00c00000UL))) {
12273 				ncont++;
12274 			}
12275 			if (DUK_UNLIKELY(!(x & 0x0000c000UL))) {
12276 				ncont++;
12277 			}
12278 			if (DUK_UNLIKELY(!(x & 0x000000c0UL))) {
12279 				ncont++;
12280 			}
12281 		}
12282 	}
12283 	p = (const duk_uint8_t *) p32;
12284 	/* Fall through to handle the rest. */
12285 
12286  skip_fastpath:
12287 	while (p != p_end) {
12288 		duk_uint8_t x;
12289 		x = *p++;
12290 		if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
12291 			ncont++;
12292 		}
12293 	}
12294 
12295 	DUK_ASSERT(ncont <= blen);
12296 	clen = blen - ncont;
12297 	DUK_ASSERT(clen <= blen);
12298 	return clen;
12299 }
12300 #endif  /* DUK_USE_PREFER_SIZE */
12301 
12302 /* Check whether a string is UTF-8 compatible or not. */
duk_unicode_is_utf8_compatible(const duk_uint8_t * buf,duk_size_t len)12303 DUK_INTERNAL duk_bool_t duk_unicode_is_utf8_compatible(const duk_uint8_t *buf, duk_size_t len) {
12304 	duk_size_t i = 0;
12305 #if !defined(DUK_USE_PREFER_SIZE)
12306 	duk_size_t len_safe;
12307 #endif
12308 
12309 	/* Many practical strings are ASCII only, so use a fast path check
12310 	 * to check chunks of bytes at once with minimal branch cost.
12311 	 */
12312 #if !defined(DUK_USE_PREFER_SIZE)
12313 	len_safe = len & ~0x03UL;
12314 	for (; i < len_safe; i += 4) {
12315 		duk_uint8_t t = buf[i] | buf[i + 1] | buf[i + 2] | buf[i + 3];
12316 		if (DUK_UNLIKELY((t & 0x80U) != 0U)) {
12317 			/* At least one byte was outside 0x00-0x7f, break
12318 			 * out to slow path (and remain there).
12319 			 *
12320 			 * XXX: We could also deal with the problem character
12321 			 * and resume fast path later.
12322 			 */
12323 			break;
12324 		}
12325 	}
12326 #endif
12327 
12328 	for (; i < len;) {
12329 		duk_uint8_t t;
12330 		duk_size_t left;
12331 		duk_size_t ncont;
12332 		duk_uint32_t cp;
12333 		duk_uint32_t mincp;
12334 
12335 		t = buf[i++];
12336 		if (DUK_LIKELY((t & 0x80U) == 0U)) {
12337 			/* Fast path, ASCII. */
12338 			continue;
12339 		}
12340 
12341 		/* Non-ASCII start byte, slow path.
12342 		 *
12343 		 * 10xx xxxx          -> continuation byte
12344 		 * 110x xxxx + 1*CONT -> [0x80, 0x7ff]
12345 		 * 1110 xxxx + 2*CONT -> [0x800, 0xffff], must reject [0xd800,0xdfff]
12346 		 * 1111 0xxx + 3*CONT -> [0x10000, 0x10ffff]
12347 		 */
12348 		left = len - i;
12349 		if (t <= 0xdfU) {  /* 1101 1111 = 0xdf */
12350 			if (t <= 0xbfU) {  /* 1011 1111 = 0xbf */
12351 				return 0;
12352 			}
12353 			ncont = 1;
12354 			mincp = 0x80UL;
12355 			cp = t & 0x1fU;
12356 		} else if (t <= 0xefU) {  /* 1110 1111 = 0xef */
12357 			ncont = 2;
12358 			mincp = 0x800UL;
12359 			cp = t & 0x0fU;
12360 		} else if (t <= 0xf7U) {  /* 1111 0111 = 0xf7 */
12361 			ncont = 3;
12362 			mincp = 0x10000UL;
12363 			cp = t & 0x07U;
12364 		} else {
12365 			return 0;
12366 		}
12367 		if (left < ncont) {
12368 			return 0;
12369 		}
12370 		while (ncont > 0U) {
12371 			t = buf[i++];
12372 			if ((t & 0xc0U) != 0x80U) {  /* 10xx xxxx */
12373 				return 0;
12374 			}
12375 			cp = (cp << 6) + (t & 0x3fU);
12376 			ncont--;
12377 		}
12378 		if (cp < mincp || cp > 0x10ffffUL || (cp >= 0xd800UL && cp <= 0xdfffUL)) {
12379 			return 0;
12380 		}
12381 	}
12382 
12383 	return 1;
12384 }
12385 
12386 /*
12387  *  Unicode range matcher
12388  *
12389  *  Matches a codepoint against a packed bitstream of character ranges.
12390  *  Used for slow path Unicode matching.
12391  */
12392 
12393 /* Must match tools/extract_chars.py, generate_match_table3(). */
duk__uni_decode_value(duk_bitdecoder_ctx * bd_ctx)12394 DUK_LOCAL duk_uint32_t duk__uni_decode_value(duk_bitdecoder_ctx *bd_ctx) {
12395 	duk_uint32_t t;
12396 
12397 	t = (duk_uint32_t) duk_bd_decode(bd_ctx, 4);
12398 	if (t <= 0x0eU) {
12399 		return t;
12400 	}
12401 	t = (duk_uint32_t) duk_bd_decode(bd_ctx, 8);
12402 	if (t <= 0xfdU) {
12403 		return t + 0x0f;
12404 	}
12405 	if (t == 0xfeU) {
12406 		t = (duk_uint32_t) duk_bd_decode(bd_ctx, 12);
12407 		return t + 0x0fU + 0xfeU;
12408 	} else {
12409 		t = (duk_uint32_t) duk_bd_decode(bd_ctx, 24);
12410 		return t + 0x0fU + 0xfeU + 0x1000UL;
12411 	}
12412 }
12413 
duk__uni_range_match(const duk_uint8_t * unitab,duk_size_t unilen,duk_codepoint_t cp)12414 DUK_LOCAL duk_small_int_t duk__uni_range_match(const duk_uint8_t *unitab, duk_size_t unilen, duk_codepoint_t cp) {
12415 	duk_bitdecoder_ctx bd_ctx;
12416 	duk_codepoint_t prev_re;
12417 
12418 	duk_memzero(&bd_ctx, sizeof(bd_ctx));
12419 	bd_ctx.data = (const duk_uint8_t *) unitab;
12420 	bd_ctx.length = (duk_size_t) unilen;
12421 
12422 	prev_re = 0;
12423 	for (;;) {
12424 		duk_codepoint_t r1, r2;
12425 		r1 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);
12426 		if (r1 == 0) {
12427 			break;
12428 		}
12429 		r2 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);
12430 
12431 		r1 = prev_re + r1;
12432 		r2 = r1 + r2;
12433 		prev_re = r2;
12434 
12435 		/* [r1,r2] is the range */
12436 
12437 		DUK_DDD(DUK_DDDPRINT("duk__uni_range_match: cp=%06lx range=[0x%06lx,0x%06lx]",
12438 		                     (unsigned long) cp, (unsigned long) r1, (unsigned long) r2));
12439 		if (cp >= r1 && cp <= r2) {
12440 			return 1;
12441 		}
12442 	}
12443 
12444 	return 0;
12445 }
12446 
12447 /*
12448  *  "WhiteSpace" production check.
12449  */
12450 
duk_unicode_is_whitespace(duk_codepoint_t cp)12451 DUK_INTERNAL duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp) {
12452 	/*
12453 	 *  E5 Section 7.2 specifies six characters specifically as
12454 	 *  white space:
12455 	 *
12456 	 *    0009;<control>;Cc;0;S;;;;;N;CHARACTER TABULATION;;;;
12457 	 *    000B;<control>;Cc;0;S;;;;;N;LINE TABULATION;;;;
12458 	 *    000C;<control>;Cc;0;WS;;;;;N;FORM FEED (FF);;;;
12459 	 *    0020;SPACE;Zs;0;WS;;;;;N;;;;;
12460 	 *    00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
12461 	 *    FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;;
12462 	 *
12463 	 *  It also specifies any Unicode category 'Zs' characters as white
12464 	 *  space.  These can be extracted with the "tools/extract_chars.py" script.
12465 	 *  Current result:
12466 	 *
12467 	 *    RAW OUTPUT:
12468 	 *    ===========
12469 	 *    0020;SPACE;Zs;0;WS;;;;;N;;;;;
12470 	 *    00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
12471 	 *    1680;OGHAM SPACE MARK;Zs;0;WS;;;;;N;;;;;
12472 	 *    180E;MONGOLIAN VOWEL SEPARATOR;Zs;0;WS;;;;;N;;;;;
12473 	 *    2000;EN QUAD;Zs;0;WS;2002;;;;N;;;;;
12474 	 *    2001;EM QUAD;Zs;0;WS;2003;;;;N;;;;;
12475 	 *    2002;EN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12476 	 *    2003;EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12477 	 *    2004;THREE-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12478 	 *    2005;FOUR-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12479 	 *    2006;SIX-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12480 	 *    2007;FIGURE SPACE;Zs;0;WS;<noBreak> 0020;;;;N;;;;;
12481 	 *    2008;PUNCTUATION SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12482 	 *    2009;THIN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12483 	 *    200A;HAIR SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12484 	 *    202F;NARROW NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;;;;;
12485 	 *    205F;MEDIUM MATHEMATICAL SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12486 	 *    3000;IDEOGRAPHIC SPACE;Zs;0;WS;<wide> 0020;;;;N;;;;;
12487 	 *
12488 	 *    RANGES:
12489 	 *    =======
12490 	 *    0x0020
12491 	 *    0x00a0
12492 	 *    0x1680
12493 	 *    0x180e
12494 	 *    0x2000 ... 0x200a
12495 	 *    0x202f
12496 	 *    0x205f
12497 	 *    0x3000
12498 	 *
12499 	 *  A manual decoder (below) is probably most compact for this.
12500 	 */
12501 
12502 	duk_uint_fast8_t lo;
12503 	duk_uint_fast32_t hi;
12504 
12505 	/* cp == -1 (EOF) never matches and causes return value 0 */
12506 
12507 	lo = (duk_uint_fast8_t) (cp & 0xff);
12508 	hi = (duk_uint_fast32_t) (cp >> 8);  /* does not fit into an uchar */
12509 
12510 	if (hi == 0x0000UL) {
12511 		if (lo == 0x09U || lo == 0x0bU || lo == 0x0cU ||
12512 		    lo == 0x20U || lo == 0xa0U) {
12513 			return 1;
12514 		}
12515 	} else if (hi == 0x0020UL) {
12516 		if (lo <= 0x0aU || lo == 0x2fU || lo == 0x5fU) {
12517 			return 1;
12518 		}
12519 	} else if (cp == 0x1680L || cp == 0x180eL || cp == 0x3000L ||
12520 	           cp == 0xfeffL) {
12521 		return 1;
12522 	}
12523 
12524 	return 0;
12525 }
12526 
12527 /*
12528  *  "LineTerminator" production check.
12529  */
12530 
duk_unicode_is_line_terminator(duk_codepoint_t cp)12531 DUK_INTERNAL duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp) {
12532 	/*
12533 	 *  E5 Section 7.3
12534 	 *
12535 	 *  A LineTerminatorSequence essentially merges <CR> <LF> sequences
12536 	 *  into a single line terminator.  This must be handled by the caller.
12537 	 */
12538 
12539 	if (cp == 0x000aL || cp == 0x000dL || cp == 0x2028L ||
12540 	    cp == 0x2029L) {
12541 		return 1;
12542 	}
12543 
12544 	return 0;
12545 }
12546 
12547 /*
12548  *  "IdentifierStart" production check.
12549  */
12550 
duk_unicode_is_identifier_start(duk_codepoint_t cp)12551 DUK_INTERNAL duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp) {
12552 	/*
12553 	 *  E5 Section 7.6:
12554 	 *
12555 	 *    IdentifierStart:
12556 	 *      UnicodeLetter
12557 	 *      $
12558 	 *      _
12559 	 *      \ UnicodeEscapeSequence
12560 	 *
12561 	 *  IdentifierStart production has one multi-character production:
12562 	 *
12563 	 *    \ UnicodeEscapeSequence
12564 	 *
12565 	 *  The '\' character is -not- matched by this function.  Rather, the caller
12566 	 *  should decode the escape and then call this function to check whether the
12567 	 *  decoded character is acceptable (see discussion in E5 Section 7.6).
12568 	 *
12569 	 *  The "UnicodeLetter" alternative of the production allows letters
12570 	 *  from various Unicode categories.  These can be extracted with the
12571 	 *  "tools/extract_chars.py" script.
12572 	 *
12573 	 *  Because the result has hundreds of Unicode codepoint ranges, matching
12574 	 *  for any values >= 0x80 are done using a very slow range-by-range scan
12575 	 *  and a packed range format.
12576 	 *
12577 	 *  The ASCII portion (codepoints 0x00 ... 0x7f) is fast-pathed below because
12578 	 *  it matters the most.  The ASCII related ranges of IdentifierStart are:
12579 	 *
12580 	 *    0x0041 ... 0x005a     ['A' ... 'Z']
12581 	 *    0x0061 ... 0x007a     ['a' ... 'z']
12582 	 *    0x0024                ['$']
12583 	 *    0x005f                ['_']
12584 	 */
12585 
12586 	/* ASCII (and EOF) fast path -- quick accept and reject */
12587 	if (cp <= 0x7fL) {
12588 #if defined(DUK_USE_IDCHAR_FASTPATH)
12589 		return (cp >= 0) && (duk_is_idchar_tab[cp] > 0);
12590 #else
12591 		if ((cp >= 'a' && cp <= 'z') ||
12592 		    (cp >= 'A' && cp <= 'Z') ||
12593 		    cp == '_' || cp == '$') {
12594 			return 1;
12595 		}
12596 		return 0;
12597 #endif
12598 	}
12599 
12600 	/* Non-ASCII slow path (range-by-range linear comparison), very slow */
12601 
12602 #if defined(DUK_USE_SOURCE_NONBMP)
12603 	if (duk__uni_range_match(duk_unicode_ids_noa,
12604 	                         (duk_size_t) sizeof(duk_unicode_ids_noa),
12605 	                         (duk_codepoint_t) cp)) {
12606 		return 1;
12607 	}
12608 	return 0;
12609 #else
12610 	if (cp < 0x10000L) {
12611 		if (duk__uni_range_match(duk_unicode_ids_noabmp,
12612 		                         sizeof(duk_unicode_ids_noabmp),
12613 		                         (duk_codepoint_t) cp)) {
12614 			return 1;
12615 		}
12616 		return 0;
12617 	} else {
12618 		/* without explicit non-BMP support, assume non-BMP characters
12619 		 * are always accepted as identifier characters.
12620 		 */
12621 		return 1;
12622 	}
12623 #endif
12624 }
12625 
12626 /*
12627  *  "IdentifierPart" production check.
12628  */
12629 
duk_unicode_is_identifier_part(duk_codepoint_t cp)12630 DUK_INTERNAL duk_small_int_t duk_unicode_is_identifier_part(duk_codepoint_t cp) {
12631 	/*
12632 	 *  E5 Section 7.6:
12633 	 *
12634 	 *    IdentifierPart:
12635 	 *      IdentifierStart
12636 	 *      UnicodeCombiningMark
12637 	 *      UnicodeDigit
12638 	 *      UnicodeConnectorPunctuation
12639 	 *      <ZWNJ>  [U+200C]
12640 	 *      <ZWJ>   [U+200D]
12641 	 *
12642 	 *  IdentifierPart production has one multi-character production
12643 	 *  as part of its IdentifierStart alternative.  The '\' character
12644 	 *  of an escape sequence is not matched here, see discussion in
12645 	 *  duk_unicode_is_identifier_start().
12646 	 *
12647 	 *  To match non-ASCII characters (codepoints >= 0x80), a very slow
12648 	 *  linear range-by-range scan is used.  The codepoint is first compared
12649 	 *  to the IdentifierStart ranges, and if it doesn't match, then to a
12650 	 *  set consisting of code points in IdentifierPart but not in
12651 	 *  IdentifierStart.  This is done to keep the unicode range data small,
12652 	 *  at the expense of speed.
12653 	 *
12654 	 *  The ASCII fast path consists of:
12655 	 *
12656 	 *    0x0030 ... 0x0039     ['0' ... '9', UnicodeDigit]
12657 	 *    0x0041 ... 0x005a     ['A' ... 'Z', IdentifierStart]
12658 	 *    0x0061 ... 0x007a     ['a' ... 'z', IdentifierStart]
12659 	 *    0x0024                ['$', IdentifierStart]
12660 	 *    0x005f                ['_', IdentifierStart and
12661 	 *                                UnicodeConnectorPunctuation]
12662 	 *
12663 	 *  UnicodeCombiningMark has no code points <= 0x7f.
12664 	 *
12665 	 *  The matching code reuses the "identifier start" tables, and then
12666 	 *  consults a separate range set for characters in "identifier part"
12667 	 *  but not in "identifier start".  These can be extracted with the
12668 	 *  "tools/extract_chars.py" script.
12669 	 *
12670 	 *  UnicodeCombiningMark -> categories Mn, Mc
12671 	 *  UnicodeDigit -> categories Nd
12672 	 *  UnicodeConnectorPunctuation -> categories Pc
12673 	 */
12674 
12675 	/* ASCII (and EOF) fast path -- quick accept and reject */
12676 	if (cp <= 0x7fL) {
12677 #if defined(DUK_USE_IDCHAR_FASTPATH)
12678 		return (cp >= 0) && (duk_is_idchar_tab[cp] != 0);
12679 #else
12680 		if ((cp >= 'a' && cp <= 'z') ||
12681 		    (cp >= 'A' && cp <= 'Z') ||
12682 		    (cp >= '0' && cp <= '9') ||
12683 		    cp == '_' || cp == '$') {
12684 			return 1;
12685 		}
12686 		return 0;
12687 #endif
12688 	}
12689 
12690 	/* Non-ASCII slow path (range-by-range linear comparison), very slow */
12691 
12692 #if defined(DUK_USE_SOURCE_NONBMP)
12693 	if (duk__uni_range_match(duk_unicode_ids_noa,
12694 	                         sizeof(duk_unicode_ids_noa),
12695 	                         (duk_codepoint_t) cp) ||
12696 	    duk__uni_range_match(duk_unicode_idp_m_ids_noa,
12697 	                         sizeof(duk_unicode_idp_m_ids_noa),
12698 	                         (duk_codepoint_t) cp)) {
12699 		return 1;
12700 	}
12701 	return 0;
12702 #else
12703 	if (cp < 0x10000L) {
12704 		if (duk__uni_range_match(duk_unicode_ids_noabmp,
12705 		                         sizeof(duk_unicode_ids_noabmp),
12706 		                         (duk_codepoint_t) cp) ||
12707 		    duk__uni_range_match(duk_unicode_idp_m_ids_noabmp,
12708 		                         sizeof(duk_unicode_idp_m_ids_noabmp),
12709 		                         (duk_codepoint_t) cp)) {
12710 			return 1;
12711 		}
12712 		return 0;
12713 	} else {
12714 		/* without explicit non-BMP support, assume non-BMP characters
12715 		 * are always accepted as identifier characters.
12716 		 */
12717 		return 1;
12718 	}
12719 #endif
12720 }
12721 
12722 /*
12723  *  Unicode letter check.
12724  */
12725 
duk_unicode_is_letter(duk_codepoint_t cp)12726 DUK_INTERNAL duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp) {
12727 	/*
12728 	 *  Unicode letter is now taken to be the categories:
12729 	 *
12730 	 *    Lu, Ll, Lt, Lm, Lo
12731 	 *
12732 	 *  (Not sure if this is exactly correct.)
12733 	 *
12734 	 *  The ASCII fast path consists of:
12735 	 *
12736 	 *    0x0041 ... 0x005a     ['A' ... 'Z']
12737 	 *    0x0061 ... 0x007a     ['a' ... 'z']
12738 	 */
12739 
12740 	/* ASCII (and EOF) fast path -- quick accept and reject */
12741 	if (cp <= 0x7fL) {
12742 		if ((cp >= 'a' && cp <= 'z') ||
12743 		    (cp >= 'A' && cp <= 'Z')) {
12744 			return 1;
12745 		}
12746 		return 0;
12747 	}
12748 
12749 	/* Non-ASCII slow path (range-by-range linear comparison), very slow */
12750 
12751 #if defined(DUK_USE_SOURCE_NONBMP)
12752 	if (duk__uni_range_match(duk_unicode_ids_noa,
12753 	                         sizeof(duk_unicode_ids_noa),
12754 	                         (duk_codepoint_t) cp) &&
12755 	    !duk__uni_range_match(duk_unicode_ids_m_let_noa,
12756 	                          sizeof(duk_unicode_ids_m_let_noa),
12757 	                          (duk_codepoint_t) cp)) {
12758 		return 1;
12759 	}
12760 	return 0;
12761 #else
12762 	if (cp < 0x10000L) {
12763 		if (duk__uni_range_match(duk_unicode_ids_noabmp,
12764 		                         sizeof(duk_unicode_ids_noabmp),
12765 		                         (duk_codepoint_t) cp) &&
12766 		    !duk__uni_range_match(duk_unicode_ids_m_let_noabmp,
12767 		                          sizeof(duk_unicode_ids_m_let_noabmp),
12768 		                          (duk_codepoint_t) cp)) {
12769 			return 1;
12770 		}
12771 		return 0;
12772 	} else {
12773 		/* without explicit non-BMP support, assume non-BMP characters
12774 		 * are always accepted as letters.
12775 		 */
12776 		return 1;
12777 	}
12778 #endif
12779 }
12780 
12781 /*
12782  *  Complex case conversion helper which decodes a bit-packed conversion
12783  *  control stream generated by tools/extract_caseconv.py.  The conversion
12784  *  is very slow because it runs through the conversion data in a linear
12785  *  fashion to save space (which is why ASCII characters have a special
12786  *  fast path before arriving here).
12787  *
12788  *  The particular bit counts etc have been determined experimentally to
12789  *  be small but still sufficient, and must match the Python script
12790  *  (tools/extract_caseconv.py).
12791  *
12792  *  The return value is the case converted codepoint or -1 if the conversion
12793  *  results in multiple characters (this is useful for regexp Canonicalization
12794  *  operation).  If 'buf' is not NULL, the result codepoint(s) are also
12795  *  appended to the hbuffer.
12796  *
12797  *  Context and locale specific rules must be checked before consulting
12798  *  this function.
12799  */
12800 
12801 DUK_LOCAL
duk__slow_case_conversion(duk_hthread * thr,duk_bufwriter_ctx * bw,duk_codepoint_t cp,duk_bitdecoder_ctx * bd_ctx)12802 duk_codepoint_t duk__slow_case_conversion(duk_hthread *thr,
12803                                           duk_bufwriter_ctx *bw,
12804                                           duk_codepoint_t cp,
12805                                           duk_bitdecoder_ctx *bd_ctx) {
12806 	duk_small_int_t skip = 0;
12807 	duk_small_int_t n;
12808 	duk_small_int_t t;
12809 	duk_small_int_t count;
12810 	duk_codepoint_t tmp_cp;
12811 	duk_codepoint_t start_i;
12812 	duk_codepoint_t start_o;
12813 
12814 	DUK_ASSERT(bd_ctx != NULL);
12815 	DUK_UNREF(thr);
12816 
12817 	DUK_DDD(DUK_DDDPRINT("slow case conversion for codepoint: %ld", (long) cp));
12818 
12819 	/* range conversion with a "skip" */
12820 	DUK_DDD(DUK_DDDPRINT("checking ranges"));
12821 	for (;;) {
12822 		skip++;
12823 		n = (duk_small_int_t) duk_bd_decode(bd_ctx, 6);
12824 		if (n == 0x3f) {
12825 			/* end marker */
12826 			break;
12827 		}
12828 		DUK_DDD(DUK_DDDPRINT("skip=%ld, n=%ld", (long) skip, (long) n));
12829 
12830 		while (n--) {
12831 			start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12832 			start_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12833 			count = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
12834 			DUK_DDD(DUK_DDDPRINT("range: start_i=%ld, start_o=%ld, count=%ld, skip=%ld",
12835 			                     (long) start_i, (long) start_o, (long) count, (long) skip));
12836 
12837 			if (cp >= start_i) {
12838 				tmp_cp = cp - start_i;  /* always >= 0 */
12839 				if (tmp_cp < (duk_codepoint_t) count * (duk_codepoint_t) skip &&
12840 				    (tmp_cp % (duk_codepoint_t) skip) == 0) {
12841 					DUK_DDD(DUK_DDDPRINT("range matches input codepoint"));
12842 					cp = start_o + tmp_cp;
12843 					goto single;
12844 				}
12845 			}
12846 		}
12847 	}
12848 
12849 	/* 1:1 conversion */
12850 	n = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
12851 	DUK_DDD(DUK_DDDPRINT("checking 1:1 conversions (count %ld)", (long) n));
12852 	while (n--) {
12853 		start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12854 		start_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12855 		DUK_DDD(DUK_DDDPRINT("1:1 conversion %ld -> %ld", (long) start_i, (long) start_o));
12856 		if (cp == start_i) {
12857 			DUK_DDD(DUK_DDDPRINT("1:1 matches input codepoint"));
12858 			cp = start_o;
12859 			goto single;
12860 		}
12861 	}
12862 
12863 	/* complex, multicharacter conversion */
12864 	n = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
12865 	DUK_DDD(DUK_DDDPRINT("checking 1:n conversions (count %ld)", (long) n));
12866 	while (n--) {
12867 		start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12868 		t = (duk_small_int_t) duk_bd_decode(bd_ctx, 2);
12869 		DUK_DDD(DUK_DDDPRINT("1:n conversion %ld -> %ld chars", (long) start_i, (long) t));
12870 		if (cp == start_i) {
12871 			DUK_DDD(DUK_DDDPRINT("1:n matches input codepoint"));
12872 			if (bw != NULL) {
12873 				while (t--) {
12874 					tmp_cp = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12875 					DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) tmp_cp);
12876 				}
12877 			}
12878 			return -1;
12879 		} else {
12880 			while (t--) {
12881 				(void) duk_bd_decode(bd_ctx, 16);
12882 			}
12883 		}
12884 	}
12885 
12886 	/* default: no change */
12887 	DUK_DDD(DUK_DDDPRINT("no rule matches, output is same as input"));
12888 	/* fall through */
12889 
12890  single:
12891 	if (bw != NULL) {
12892 		DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) cp);
12893 	}
12894 	return cp;
12895 }
12896 
12897 /*
12898  *  Case conversion helper, with context/local sensitivity.
12899  *  For proper case conversion, one needs to know the character
12900  *  and the preceding and following characters, as well as
12901  *  locale/language.
12902  */
12903 
12904 /* XXX: add 'language' argument when locale/language sensitive rule
12905  * support added.
12906  */
12907 DUK_LOCAL
duk__case_transform_helper(duk_hthread * thr,duk_bufwriter_ctx * bw,duk_codepoint_t cp,duk_codepoint_t prev,duk_codepoint_t next,duk_bool_t uppercase)12908 duk_codepoint_t duk__case_transform_helper(duk_hthread *thr,
12909                                            duk_bufwriter_ctx *bw,
12910                                            duk_codepoint_t cp,
12911                                            duk_codepoint_t prev,
12912                                            duk_codepoint_t next,
12913                                            duk_bool_t uppercase) {
12914 	duk_bitdecoder_ctx bd_ctx;
12915 
12916 	/* fast path for ASCII */
12917 	if (cp < 0x80L) {
12918 		/* XXX: there are language sensitive rules for the ASCII range.
12919 		 * If/when language/locale support is implemented, they need to
12920 		 * be implemented here for the fast path.  There are no context
12921 		 * sensitive rules for ASCII range.
12922 		 */
12923 
12924 		if (uppercase) {
12925 			if (cp >= 'a' && cp <= 'z') {
12926 				cp = cp - 'a' + 'A';
12927 			}
12928 		} else {
12929 			if (cp >= 'A' && cp <= 'Z') {
12930 				cp = cp - 'A' + 'a';
12931 			}
12932 		}
12933 
12934 		if (bw != NULL) {
12935 			DUK_BW_WRITE_RAW_U8(thr, bw, (duk_uint8_t) cp);
12936 		}
12937 		return cp;
12938 	}
12939 
12940 	/* context and locale specific rules which cannot currently be represented
12941 	 * in the caseconv bitstream: hardcoded rules in C
12942 	 */
12943 	if (uppercase) {
12944 		/* XXX: turkish / azeri */
12945 	} else {
12946 		/*
12947 		 *  Final sigma context specific rule.  This is a rather tricky
12948 		 *  rule and this handling is probably not 100% correct now.
12949 		 *  The rule is not locale/language specific so it is supported.
12950 		 */
12951 
12952 		if (cp == 0x03a3L &&    /* U+03A3 = GREEK CAPITAL LETTER SIGMA */
12953 		    duk_unicode_is_letter(prev) &&        /* prev exists and is not a letter */
12954 		    !duk_unicode_is_letter(next)) {       /* next does not exist or next is not a letter */
12955 			/* Capital sigma occurred at "end of word", lowercase to
12956 			 * U+03C2 = GREEK SMALL LETTER FINAL SIGMA.  Otherwise
12957 			 * fall through and let the normal rules lowercase it to
12958 			 * U+03C3 = GREEK SMALL LETTER SIGMA.
12959 			 */
12960 			cp = 0x03c2L;
12961 			goto singlechar;
12962 		}
12963 
12964 		/* XXX: lithuanian not implemented */
12965 		/* XXX: lithuanian, explicit dot rules */
12966 		/* XXX: turkish / azeri, lowercase rules */
12967 	}
12968 
12969 	/* 1:1 or special conversions, but not locale/context specific: script generated rules */
12970 	duk_memzero(&bd_ctx, sizeof(bd_ctx));
12971 	if (uppercase) {
12972 		bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_uc;
12973 		bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_uc);
12974 	} else {
12975 		bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_lc;
12976 		bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_lc);
12977 	}
12978 	return duk__slow_case_conversion(thr, bw, cp, &bd_ctx);
12979 
12980  singlechar:
12981 	if (bw != NULL) {
12982 		DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) cp);
12983 	}
12984 	return cp;
12985 
12986  /* unused now, not needed until Turkish/Azeri */
12987 #if 0
12988  nochar:
12989 	return -1;
12990 #endif
12991 }
12992 
12993 /*
12994  *  Replace valstack top with case converted version.
12995  */
12996 
duk_unicode_case_convert_string(duk_hthread * thr,duk_bool_t uppercase)12997 DUK_INTERNAL void duk_unicode_case_convert_string(duk_hthread *thr, duk_bool_t uppercase) {
12998 	duk_hstring *h_input;
12999 	duk_bufwriter_ctx bw_alloc;
13000 	duk_bufwriter_ctx *bw;
13001 	const duk_uint8_t *p, *p_start, *p_end;
13002 	duk_codepoint_t prev, curr, next;
13003 
13004 	h_input = duk_require_hstring(thr, -1);  /* Accept symbols. */
13005 	DUK_ASSERT(h_input != NULL);
13006 
13007 	bw = &bw_alloc;
13008 	DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));
13009 
13010 	/* [ ... input buffer ] */
13011 
13012 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
13013 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
13014 	p = p_start;
13015 
13016 	prev = -1; DUK_UNREF(prev);
13017 	curr = -1;
13018 	next = -1;
13019 	for (;;) {
13020 		prev = curr;
13021 		curr = next;
13022 		next = -1;
13023 		if (p < p_end) {
13024 			next = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
13025 		} else {
13026 			/* end of input and last char has been processed */
13027 			if (curr < 0) {
13028 				break;
13029 			}
13030 		}
13031 
13032 		/* on first round, skip */
13033 		if (curr >= 0) {
13034 			/* XXX: could add a fast path to process chunks of input codepoints,
13035 			 * but relative benefit would be quite small.
13036 			 */
13037 
13038 			/* Ensure space for maximum multi-character result; estimate is overkill. */
13039 			DUK_BW_ENSURE(thr, bw, 8 * DUK_UNICODE_MAX_XUTF8_LENGTH);
13040 
13041 			duk__case_transform_helper(thr,
13042 			                           bw,
13043 			                           (duk_codepoint_t) curr,
13044 			                           prev,
13045 			                           next,
13046 			                           uppercase);
13047 		}
13048 	}
13049 
13050 	DUK_BW_COMPACT(thr, bw);
13051 	(void) duk_buffer_to_string(thr, -1);  /* Safe, output is encoded. */
13052 	/* invalidates h_buf pointer */
13053 	duk_remove_m2(thr);
13054 }
13055 
13056 #if defined(DUK_USE_REGEXP_SUPPORT)
13057 
13058 /*
13059  *  Canonicalize() abstract operation needed for canonicalization of individual
13060  *  codepoints during regexp compilation and execution, see E5 Section 15.10.2.8.
13061  *  Note that codepoints are canonicalized one character at a time, so no context
13062  *  specific rules can apply.  Locale specific rules can apply, though.
13063  */
13064 
duk_unicode_re_canonicalize_char(duk_hthread * thr,duk_codepoint_t cp)13065 DUK_INTERNAL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr, duk_codepoint_t cp) {
13066 #if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
13067 	/* Fast canonicalization lookup at the cost of 128kB footprint. */
13068 	DUK_ASSERT(cp >= 0);
13069 	DUK_UNREF(thr);
13070 	if (DUK_LIKELY(cp < 0x10000L)) {
13071 		return (duk_codepoint_t) duk_unicode_re_canon_lookup[cp];
13072 	}
13073 	return cp;
13074 #else  /* DUK_USE_REGEXP_CANON_WORKAROUND */
13075 	duk_codepoint_t y;
13076 
13077 	y = duk__case_transform_helper(thr,
13078 	                               NULL,    /* NULL is allowed, no output */
13079 	                               cp,      /* curr char */
13080 	                               -1,      /* prev char */
13081 	                               -1,      /* next char */
13082 	                               1);      /* uppercase */
13083 
13084 	if ((y < 0) || (cp >= 0x80 && y < 0x80)) {
13085 		/* multiple codepoint conversion or non-ASCII mapped to ASCII
13086 		 * --> leave as is.
13087 		 */
13088 		return cp;
13089 	}
13090 
13091 	return y;
13092 #endif  /* DUK_USE_REGEXP_CANON_WORKAROUND */
13093 }
13094 
13095 /*
13096  *  E5 Section 15.10.2.6 "IsWordChar" abstract operation.  Assume
13097  *  x < 0 for characters read outside the string.
13098  */
13099 
duk_unicode_re_is_wordchar(duk_codepoint_t x)13100 DUK_INTERNAL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t x) {
13101 	/*
13102 	 *  Note: the description in E5 Section 15.10.2.6 has a typo, it
13103 	 *  contains 'A' twice and lacks 'a'; the intent is [0-9a-zA-Z_].
13104 	 */
13105 	if ((x >= '0' && x <= '9') ||
13106 	    (x >= 'a' && x <= 'z') ||
13107 	    (x >= 'A' && x <= 'Z') ||
13108 	    (x == '_')) {
13109 		return 1;
13110 	}
13111 	return 0;
13112 }
13113 
13114 /*
13115  *  Regexp range tables
13116  */
13117 
13118 /* exposed because lexer needs these too */
13119 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_digit[2] = {
13120 	(duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,
13121 };
13122 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_white[22] = {
13123 	(duk_uint16_t) 0x0009UL, (duk_uint16_t) 0x000DUL,
13124 	(duk_uint16_t) 0x0020UL, (duk_uint16_t) 0x0020UL,
13125 	(duk_uint16_t) 0x00A0UL, (duk_uint16_t) 0x00A0UL,
13126 	(duk_uint16_t) 0x1680UL, (duk_uint16_t) 0x1680UL,
13127 	(duk_uint16_t) 0x180EUL, (duk_uint16_t) 0x180EUL,
13128 	(duk_uint16_t) 0x2000UL, (duk_uint16_t) 0x200AUL,
13129 	(duk_uint16_t) 0x2028UL, (duk_uint16_t) 0x2029UL,
13130 	(duk_uint16_t) 0x202FUL, (duk_uint16_t) 0x202FUL,
13131 	(duk_uint16_t) 0x205FUL, (duk_uint16_t) 0x205FUL,
13132 	(duk_uint16_t) 0x3000UL, (duk_uint16_t) 0x3000UL,
13133 	(duk_uint16_t) 0xFEFFUL, (duk_uint16_t) 0xFEFFUL,
13134 };
13135 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_wordchar[8] = {
13136 	(duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,
13137 	(duk_uint16_t) 0x0041UL, (duk_uint16_t) 0x005AUL,
13138 	(duk_uint16_t) 0x005FUL, (duk_uint16_t) 0x005FUL,
13139 	(duk_uint16_t) 0x0061UL, (duk_uint16_t) 0x007AUL,
13140 };
13141 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_digit[4] = {
13142 	(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,
13143 	(duk_uint16_t) 0x003AUL, (duk_uint16_t) 0xFFFFUL,
13144 };
13145 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_white[24] = {
13146 	(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x0008UL,
13147 	(duk_uint16_t) 0x000EUL, (duk_uint16_t) 0x001FUL,
13148 	(duk_uint16_t) 0x0021UL, (duk_uint16_t) 0x009FUL,
13149 	(duk_uint16_t) 0x00A1UL, (duk_uint16_t) 0x167FUL,
13150 	(duk_uint16_t) 0x1681UL, (duk_uint16_t) 0x180DUL,
13151 	(duk_uint16_t) 0x180FUL, (duk_uint16_t) 0x1FFFUL,
13152 	(duk_uint16_t) 0x200BUL, (duk_uint16_t) 0x2027UL,
13153 	(duk_uint16_t) 0x202AUL, (duk_uint16_t) 0x202EUL,
13154 	(duk_uint16_t) 0x2030UL, (duk_uint16_t) 0x205EUL,
13155 	(duk_uint16_t) 0x2060UL, (duk_uint16_t) 0x2FFFUL,
13156 	(duk_uint16_t) 0x3001UL, (duk_uint16_t) 0xFEFEUL,
13157 	(duk_uint16_t) 0xFF00UL, (duk_uint16_t) 0xFFFFUL,
13158 };
13159 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_wordchar[10] = {
13160 	(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,
13161 	(duk_uint16_t) 0x003AUL, (duk_uint16_t) 0x0040UL,
13162 	(duk_uint16_t) 0x005BUL, (duk_uint16_t) 0x005EUL,
13163 	(duk_uint16_t) 0x0060UL, (duk_uint16_t) 0x0060UL,
13164 	(duk_uint16_t) 0x007BUL, (duk_uint16_t) 0xFFFFUL,
13165 };
13166 
13167 #endif  /* DUK_USE_REGEXP_SUPPORT */
13168 /*
13169  *  Macro support functions for reading/writing raw data.
13170  *
13171  *  These are done using memcpy to ensure they're valid even for unaligned
13172  *  reads/writes on platforms where alignment counts.  On x86 at least gcc
13173  *  is able to compile these into a bswap+mov.  "Always inline" is used to
13174  *  ensure these macros compile to minimal code.
13175  */
13176 
13177 /* #include duk_internal.h -> already included */
13178 
13179 union duk__u16_union {
13180 	duk_uint8_t b[2];
13181 	duk_uint16_t x;
13182 };
13183 typedef union duk__u16_union duk__u16_union;
13184 
13185 union duk__u32_union {
13186 	duk_uint8_t b[4];
13187 	duk_uint32_t x;
13188 };
13189 typedef union duk__u32_union duk__u32_union;
13190 
13191 #if defined(DUK_USE_64BIT_OPS)
13192 union duk__u64_union {
13193 	duk_uint8_t b[8];
13194 	duk_uint64_t x;
13195 };
13196 typedef union duk__u64_union duk__u64_union;
13197 #endif
13198 
duk_raw_read_u16_be(const duk_uint8_t * p)13199 DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint16_t duk_raw_read_u16_be(const duk_uint8_t *p) {
13200 	duk__u16_union u;
13201 	duk_memcpy((void *) u.b, (const void *) p, (size_t) 2);
13202 	u.x = DUK_NTOH16(u.x);
13203 	return u.x;
13204 }
13205 
duk_raw_read_u32_be(const duk_uint8_t * p)13206 DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint32_t duk_raw_read_u32_be(const duk_uint8_t *p) {
13207 	duk__u32_union u;
13208 	duk_memcpy((void *) u.b, (const void *) p, (size_t) 4);
13209 	u.x = DUK_NTOH32(u.x);
13210 	return u.x;
13211 }
13212 
duk_raw_read_float_be(const duk_uint8_t * p)13213 DUK_INTERNAL DUK_ALWAYS_INLINE duk_float_t duk_raw_read_float_be(const duk_uint8_t *p) {
13214 	duk_float_union fu;
13215 	duk_memcpy((void *) fu.uc, (const void *) p, (size_t) 4);
13216 	duk_fltunion_big_to_host(&fu);
13217 	return fu.f;
13218 }
13219 
duk_raw_read_double_be(const duk_uint8_t * p)13220 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_raw_read_double_be(const duk_uint8_t *p) {
13221 	duk_double_union du;
13222 	duk_memcpy((void *) du.uc, (const void *) p, (size_t) 8);
13223 	duk_dblunion_big_to_host(&du);
13224 	return du.d;
13225 }
13226 
duk_raw_readinc_u16_be(const duk_uint8_t ** p)13227 DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint16_t duk_raw_readinc_u16_be(const duk_uint8_t **p) {
13228 	duk_uint16_t res = duk_raw_read_u16_be(*p);
13229 	*p += 2;
13230 	return res;
13231 }
13232 
duk_raw_readinc_u32_be(const duk_uint8_t ** p)13233 DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint32_t duk_raw_readinc_u32_be(const duk_uint8_t **p) {
13234 	duk_uint32_t res = duk_raw_read_u32_be(*p);
13235 	*p += 4;
13236 	return res;
13237 }
13238 
duk_raw_readinc_float_be(const duk_uint8_t ** p)13239 DUK_INTERNAL DUK_ALWAYS_INLINE duk_float_t duk_raw_readinc_float_be(const duk_uint8_t **p) {
13240 	duk_float_t res = duk_raw_read_float_be(*p);
13241 	*p += 4;
13242 	return res;
13243 }
13244 
duk_raw_readinc_double_be(const duk_uint8_t ** p)13245 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_raw_readinc_double_be(const duk_uint8_t **p) {
13246 	duk_double_t res = duk_raw_read_double_be(*p);
13247 	*p += 8;
13248 	return res;
13249 }
13250 
duk_raw_write_u16_be(duk_uint8_t * p,duk_uint16_t val)13251 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u16_be(duk_uint8_t *p, duk_uint16_t val) {
13252 	duk__u16_union u;
13253 	u.x = DUK_HTON16(val);
13254 	duk_memcpy((void *) p, (const void *) u.b, (size_t) 2);
13255 }
13256 
duk_raw_write_u32_be(duk_uint8_t * p,duk_uint32_t val)13257 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u32_be(duk_uint8_t *p, duk_uint32_t val) {
13258 	duk__u32_union u;
13259 	u.x = DUK_HTON32(val);
13260 	duk_memcpy((void *) p, (const void *) u.b, (size_t) 4);
13261 }
13262 
duk_raw_write_float_be(duk_uint8_t * p,duk_float_t val)13263 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_float_be(duk_uint8_t *p, duk_float_t val) {
13264 	duk_float_union fu;
13265 	fu.f = val;
13266 	duk_fltunion_host_to_big(&fu);
13267 	duk_memcpy((void *) p, (const void *) fu.uc, (size_t) 4);
13268 }
13269 
duk_raw_write_double_be(duk_uint8_t * p,duk_double_t val)13270 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_double_be(duk_uint8_t *p, duk_double_t val) {
13271 	duk_double_union du;
13272 	du.d = val;
13273 	duk_dblunion_host_to_big(&du);
13274 	duk_memcpy((void *) p, (const void *) du.uc, (size_t) 8);
13275 }
13276 
duk_raw_write_xutf8(duk_uint8_t * p,duk_ucodepoint_t val)13277 DUK_INTERNAL duk_small_int_t duk_raw_write_xutf8(duk_uint8_t *p, duk_ucodepoint_t val) {
13278 	duk_small_int_t len = duk_unicode_encode_xutf8(val, p);
13279 	return len;
13280 }
13281 
duk_raw_write_cesu8(duk_uint8_t * p,duk_ucodepoint_t val)13282 DUK_INTERNAL duk_small_int_t duk_raw_write_cesu8(duk_uint8_t *p, duk_ucodepoint_t val) {
13283 	duk_small_int_t len = duk_unicode_encode_cesu8(val, p);
13284 	return len;
13285 }
13286 
duk_raw_writeinc_u16_be(duk_uint8_t ** p,duk_uint16_t val)13287 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_writeinc_u16_be(duk_uint8_t **p, duk_uint16_t val) {
13288 	duk_raw_write_u16_be(*p, val);
13289 	*p += 2;
13290 }
13291 
duk_raw_writeinc_u32_be(duk_uint8_t ** p,duk_uint32_t val)13292 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_writeinc_u32_be(duk_uint8_t **p, duk_uint32_t val) {
13293 	duk_raw_write_u32_be(*p, val);
13294 	*p += 4;
13295 }
13296 
duk_raw_writeinc_float_be(duk_uint8_t ** p,duk_float_t val)13297 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_writeinc_float_be(duk_uint8_t **p, duk_float_t val) {
13298 	duk_raw_write_float_be(*p, val);
13299 	*p += 4;
13300 }
13301 
duk_raw_writeinc_double_be(duk_uint8_t ** p,duk_double_t val)13302 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_writeinc_double_be(duk_uint8_t **p, duk_double_t val) {
13303 	duk_raw_write_double_be(*p, val);
13304 	*p += 8;
13305 }
13306 
duk_raw_writeinc_xutf8(duk_uint8_t ** p,duk_ucodepoint_t val)13307 DUK_INTERNAL void duk_raw_writeinc_xutf8(duk_uint8_t **p, duk_ucodepoint_t val) {
13308 	duk_small_int_t len = duk_unicode_encode_xutf8(val, *p);
13309 	*p += len;
13310 }
13311 
duk_raw_writeinc_cesu8(duk_uint8_t ** p,duk_ucodepoint_t val)13312 DUK_INTERNAL void duk_raw_writeinc_cesu8(duk_uint8_t **p, duk_ucodepoint_t val) {
13313 	duk_small_int_t len = duk_unicode_encode_cesu8(val, *p);
13314 	*p += len;
13315 }
13316 /*
13317  *  Misc util stuff.
13318  */
13319 
13320 /* #include duk_internal.h -> already included */
13321 
13322 /*
13323  *  Lowercase digits for radix values 2 to 36.  Also doubles as lowercase
13324  *  hex nybble table.
13325  */
13326 
13327 DUK_INTERNAL const duk_uint8_t duk_lc_digits[36] = {
13328 	DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
13329 	DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
13330 	DUK_ASC_8, DUK_ASC_9, DUK_ASC_LC_A, DUK_ASC_LC_B,
13331 	DUK_ASC_LC_C, DUK_ASC_LC_D, DUK_ASC_LC_E, DUK_ASC_LC_F,
13332 	DUK_ASC_LC_G, DUK_ASC_LC_H, DUK_ASC_LC_I, DUK_ASC_LC_J,
13333 	DUK_ASC_LC_K, DUK_ASC_LC_L, DUK_ASC_LC_M, DUK_ASC_LC_N,
13334 	DUK_ASC_LC_O, DUK_ASC_LC_P, DUK_ASC_LC_Q, DUK_ASC_LC_R,
13335 	DUK_ASC_LC_S, DUK_ASC_LC_T, DUK_ASC_LC_U, DUK_ASC_LC_V,
13336 	DUK_ASC_LC_W, DUK_ASC_LC_X, DUK_ASC_LC_Y, DUK_ASC_LC_Z
13337 };
13338 
13339 DUK_INTERNAL const duk_uint8_t duk_uc_nybbles[16] = {
13340 	DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
13341 	DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
13342 	DUK_ASC_8, DUK_ASC_9, DUK_ASC_UC_A, DUK_ASC_UC_B,
13343 	DUK_ASC_UC_C, DUK_ASC_UC_D, DUK_ASC_UC_E, DUK_ASC_UC_F
13344 };
13345 
13346 /*
13347  *  Table for hex decoding ASCII hex digits
13348  */
13349 
13350 DUK_INTERNAL const duk_int8_t duk_hex_dectab[256] = {
13351 	/* -1 if invalid */
13352 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x00-0x0f */
13353 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x10-0x1f */
13354 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x20-0x2f */
13355 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,  /* 0x30-0x3f */
13356 	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x40-0x4f */
13357 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x50-0x5f */
13358 	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x60-0x6f */
13359 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x70-0x7f */
13360 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x80-0x8f */
13361 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x90-0x9f */
13362 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xa0-0xaf */
13363 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xb0-0xbf */
13364 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xc0-0xcf */
13365 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xd0-0xdf */
13366 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xe0-0xef */
13367 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1   /* 0xf0-0xff */
13368 };
13369 
13370 #if defined(DUK_USE_HEX_FASTPATH)
13371 /* Preshifted << 4.  Must use 16-bit entry to allow negative value signaling. */
13372 DUK_INTERNAL const duk_int16_t duk_hex_dectab_shift4[256] = {
13373 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x00-0x0f */
13374 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x10-0x1f */
13375 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x20-0x2f */
13376 	0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x30-0x3f */
13377 	  -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x40-0x4f */
13378 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x50-0x5f */
13379 	  -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x60-0x6f */
13380 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x70-0x7f */
13381 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x80-0x8f */
13382 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x90-0x9f */
13383 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xa0-0xaf */
13384 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xb0-0xbf */
13385 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xc0-0xcf */
13386 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xd0-0xdf */
13387 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xe0-0xef */
13388 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1   /* 0xf0-0xff */
13389 };
13390 #endif
13391 
13392 /*
13393  *  Table for hex encoding bytes
13394  */
13395 
13396 #if defined(DUK_USE_HEX_FASTPATH)
13397 /* Lookup to encode one byte directly into 2 characters:
13398  *
13399  *   def genhextab(bswap):
13400  *       for i in xrange(256):
13401  *           t = chr(i).encode('hex')
13402  *           if bswap:
13403  *               t = t[1] + t[0]
13404  *           print('0x' + t.encode('hex') + 'U')
13405  *   print('big endian'); genhextab(False)
13406  *   print('little endian'); genhextab(True)
13407 */
13408 DUK_INTERNAL const duk_uint16_t duk_hex_enctab[256] = {
13409 #if defined(DUK_USE_INTEGER_BE)
13410 	0x3030U, 0x3031U, 0x3032U, 0x3033U, 0x3034U, 0x3035U, 0x3036U, 0x3037U,
13411 	0x3038U, 0x3039U, 0x3061U, 0x3062U, 0x3063U, 0x3064U, 0x3065U, 0x3066U,
13412 	0x3130U, 0x3131U, 0x3132U, 0x3133U, 0x3134U, 0x3135U, 0x3136U, 0x3137U,
13413 	0x3138U, 0x3139U, 0x3161U, 0x3162U, 0x3163U, 0x3164U, 0x3165U, 0x3166U,
13414 	0x3230U, 0x3231U, 0x3232U, 0x3233U, 0x3234U, 0x3235U, 0x3236U, 0x3237U,
13415 	0x3238U, 0x3239U, 0x3261U, 0x3262U, 0x3263U, 0x3264U, 0x3265U, 0x3266U,
13416 	0x3330U, 0x3331U, 0x3332U, 0x3333U, 0x3334U, 0x3335U, 0x3336U, 0x3337U,
13417 	0x3338U, 0x3339U, 0x3361U, 0x3362U, 0x3363U, 0x3364U, 0x3365U, 0x3366U,
13418 	0x3430U, 0x3431U, 0x3432U, 0x3433U, 0x3434U, 0x3435U, 0x3436U, 0x3437U,
13419 	0x3438U, 0x3439U, 0x3461U, 0x3462U, 0x3463U, 0x3464U, 0x3465U, 0x3466U,
13420 	0x3530U, 0x3531U, 0x3532U, 0x3533U, 0x3534U, 0x3535U, 0x3536U, 0x3537U,
13421 	0x3538U, 0x3539U, 0x3561U, 0x3562U, 0x3563U, 0x3564U, 0x3565U, 0x3566U,
13422 	0x3630U, 0x3631U, 0x3632U, 0x3633U, 0x3634U, 0x3635U, 0x3636U, 0x3637U,
13423 	0x3638U, 0x3639U, 0x3661U, 0x3662U, 0x3663U, 0x3664U, 0x3665U, 0x3666U,
13424 	0x3730U, 0x3731U, 0x3732U, 0x3733U, 0x3734U, 0x3735U, 0x3736U, 0x3737U,
13425 	0x3738U, 0x3739U, 0x3761U, 0x3762U, 0x3763U, 0x3764U, 0x3765U, 0x3766U,
13426 	0x3830U, 0x3831U, 0x3832U, 0x3833U, 0x3834U, 0x3835U, 0x3836U, 0x3837U,
13427 	0x3838U, 0x3839U, 0x3861U, 0x3862U, 0x3863U, 0x3864U, 0x3865U, 0x3866U,
13428 	0x3930U, 0x3931U, 0x3932U, 0x3933U, 0x3934U, 0x3935U, 0x3936U, 0x3937U,
13429 	0x3938U, 0x3939U, 0x3961U, 0x3962U, 0x3963U, 0x3964U, 0x3965U, 0x3966U,
13430 	0x6130U, 0x6131U, 0x6132U, 0x6133U, 0x6134U, 0x6135U, 0x6136U, 0x6137U,
13431 	0x6138U, 0x6139U, 0x6161U, 0x6162U, 0x6163U, 0x6164U, 0x6165U, 0x6166U,
13432 	0x6230U, 0x6231U, 0x6232U, 0x6233U, 0x6234U, 0x6235U, 0x6236U, 0x6237U,
13433 	0x6238U, 0x6239U, 0x6261U, 0x6262U, 0x6263U, 0x6264U, 0x6265U, 0x6266U,
13434 	0x6330U, 0x6331U, 0x6332U, 0x6333U, 0x6334U, 0x6335U, 0x6336U, 0x6337U,
13435 	0x6338U, 0x6339U, 0x6361U, 0x6362U, 0x6363U, 0x6364U, 0x6365U, 0x6366U,
13436 	0x6430U, 0x6431U, 0x6432U, 0x6433U, 0x6434U, 0x6435U, 0x6436U, 0x6437U,
13437 	0x6438U, 0x6439U, 0x6461U, 0x6462U, 0x6463U, 0x6464U, 0x6465U, 0x6466U,
13438 	0x6530U, 0x6531U, 0x6532U, 0x6533U, 0x6534U, 0x6535U, 0x6536U, 0x6537U,
13439 	0x6538U, 0x6539U, 0x6561U, 0x6562U, 0x6563U, 0x6564U, 0x6565U, 0x6566U,
13440 	0x6630U, 0x6631U, 0x6632U, 0x6633U, 0x6634U, 0x6635U, 0x6636U, 0x6637U,
13441 	0x6638U, 0x6639U, 0x6661U, 0x6662U, 0x6663U, 0x6664U, 0x6665U, 0x6666U
13442 #else  /* DUK_USE_INTEGER_BE */
13443 	0x3030U, 0x3130U, 0x3230U, 0x3330U, 0x3430U, 0x3530U, 0x3630U, 0x3730U,
13444 	0x3830U, 0x3930U, 0x6130U, 0x6230U, 0x6330U, 0x6430U, 0x6530U, 0x6630U,
13445 	0x3031U, 0x3131U, 0x3231U, 0x3331U, 0x3431U, 0x3531U, 0x3631U, 0x3731U,
13446 	0x3831U, 0x3931U, 0x6131U, 0x6231U, 0x6331U, 0x6431U, 0x6531U, 0x6631U,
13447 	0x3032U, 0x3132U, 0x3232U, 0x3332U, 0x3432U, 0x3532U, 0x3632U, 0x3732U,
13448 	0x3832U, 0x3932U, 0x6132U, 0x6232U, 0x6332U, 0x6432U, 0x6532U, 0x6632U,
13449 	0x3033U, 0x3133U, 0x3233U, 0x3333U, 0x3433U, 0x3533U, 0x3633U, 0x3733U,
13450 	0x3833U, 0x3933U, 0x6133U, 0x6233U, 0x6333U, 0x6433U, 0x6533U, 0x6633U,
13451 	0x3034U, 0x3134U, 0x3234U, 0x3334U, 0x3434U, 0x3534U, 0x3634U, 0x3734U,
13452 	0x3834U, 0x3934U, 0x6134U, 0x6234U, 0x6334U, 0x6434U, 0x6534U, 0x6634U,
13453 	0x3035U, 0x3135U, 0x3235U, 0x3335U, 0x3435U, 0x3535U, 0x3635U, 0x3735U,
13454 	0x3835U, 0x3935U, 0x6135U, 0x6235U, 0x6335U, 0x6435U, 0x6535U, 0x6635U,
13455 	0x3036U, 0x3136U, 0x3236U, 0x3336U, 0x3436U, 0x3536U, 0x3636U, 0x3736U,
13456 	0x3836U, 0x3936U, 0x6136U, 0x6236U, 0x6336U, 0x6436U, 0x6536U, 0x6636U,
13457 	0x3037U, 0x3137U, 0x3237U, 0x3337U, 0x3437U, 0x3537U, 0x3637U, 0x3737U,
13458 	0x3837U, 0x3937U, 0x6137U, 0x6237U, 0x6337U, 0x6437U, 0x6537U, 0x6637U,
13459 	0x3038U, 0x3138U, 0x3238U, 0x3338U, 0x3438U, 0x3538U, 0x3638U, 0x3738U,
13460 	0x3838U, 0x3938U, 0x6138U, 0x6238U, 0x6338U, 0x6438U, 0x6538U, 0x6638U,
13461 	0x3039U, 0x3139U, 0x3239U, 0x3339U, 0x3439U, 0x3539U, 0x3639U, 0x3739U,
13462 	0x3839U, 0x3939U, 0x6139U, 0x6239U, 0x6339U, 0x6439U, 0x6539U, 0x6639U,
13463 	0x3061U, 0x3161U, 0x3261U, 0x3361U, 0x3461U, 0x3561U, 0x3661U, 0x3761U,
13464 	0x3861U, 0x3961U, 0x6161U, 0x6261U, 0x6361U, 0x6461U, 0x6561U, 0x6661U,
13465 	0x3062U, 0x3162U, 0x3262U, 0x3362U, 0x3462U, 0x3562U, 0x3662U, 0x3762U,
13466 	0x3862U, 0x3962U, 0x6162U, 0x6262U, 0x6362U, 0x6462U, 0x6562U, 0x6662U,
13467 	0x3063U, 0x3163U, 0x3263U, 0x3363U, 0x3463U, 0x3563U, 0x3663U, 0x3763U,
13468 	0x3863U, 0x3963U, 0x6163U, 0x6263U, 0x6363U, 0x6463U, 0x6563U, 0x6663U,
13469 	0x3064U, 0x3164U, 0x3264U, 0x3364U, 0x3464U, 0x3564U, 0x3664U, 0x3764U,
13470 	0x3864U, 0x3964U, 0x6164U, 0x6264U, 0x6364U, 0x6464U, 0x6564U, 0x6664U,
13471 	0x3065U, 0x3165U, 0x3265U, 0x3365U, 0x3465U, 0x3565U, 0x3665U, 0x3765U,
13472 	0x3865U, 0x3965U, 0x6165U, 0x6265U, 0x6365U, 0x6465U, 0x6565U, 0x6665U,
13473 	0x3066U, 0x3166U, 0x3266U, 0x3366U, 0x3466U, 0x3566U, 0x3666U, 0x3766U,
13474 	0x3866U, 0x3966U, 0x6166U, 0x6266U, 0x6366U, 0x6466U, 0x6566U, 0x6666U
13475 #endif  /* DUK_USE_INTEGER_BE */
13476 };
13477 #endif  /* DUK_USE_HEX_FASTPATH */
13478 
13479 /*
13480  *  Arbitrary byteswap for potentially unaligned values
13481  *
13482  *  Used to byteswap pointers e.g. in debugger code.
13483  */
13484 
13485 #if defined(DUK_USE_DEBUGGER_SUPPORT)  /* For now only needed by the debugger. */
duk_byteswap_bytes(duk_uint8_t * p,duk_small_uint_t len)13486 DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len) {
13487 	duk_uint8_t tmp;
13488 	duk_uint8_t *q = p + len - 1;
13489 
13490 	while (p - q < 0) {
13491 		tmp = *p;
13492 		*p = *q;
13493 		*q = tmp;
13494 		p++;
13495 		q--;
13496 	}
13497 }
13498 #endif
13499 /*
13500  *  Hobject ECMAScript [[Class]].
13501  */
13502 
13503 /* #include duk_internal.h -> already included */
13504 
13505 #if (DUK_STRIDX_UC_ARGUMENTS > 255)
13506 #error constant too large
13507 #endif
13508 #if (DUK_STRIDX_UC_ARRAY > 255)
13509 #error constant too large
13510 #endif
13511 #if (DUK_STRIDX_UC_BOOLEAN > 255)
13512 #error constant too large
13513 #endif
13514 #if (DUK_STRIDX_UC_DATE > 255)
13515 #error constant too large
13516 #endif
13517 #if (DUK_STRIDX_UC_ERROR > 255)
13518 #error constant too large
13519 #endif
13520 #if (DUK_STRIDX_UC_FUNCTION > 255)
13521 #error constant too large
13522 #endif
13523 #if (DUK_STRIDX_JSON > 255)
13524 #error constant too large
13525 #endif
13526 #if (DUK_STRIDX_MATH > 255)
13527 #error constant too large
13528 #endif
13529 #if (DUK_STRIDX_UC_NUMBER > 255)
13530 #error constant too large
13531 #endif
13532 #if (DUK_STRIDX_UC_OBJECT > 255)
13533 #error constant too large
13534 #endif
13535 #if (DUK_STRIDX_REG_EXP > 255)
13536 #error constant too large
13537 #endif
13538 #if (DUK_STRIDX_UC_STRING > 255)
13539 #error constant too large
13540 #endif
13541 #if (DUK_STRIDX_GLOBAL > 255)
13542 #error constant too large
13543 #endif
13544 #if (DUK_STRIDX_OBJ_ENV > 255)
13545 #error constant too large
13546 #endif
13547 #if (DUK_STRIDX_DEC_ENV > 255)
13548 #error constant too large
13549 #endif
13550 #if (DUK_STRIDX_UC_POINTER > 255)
13551 #error constant too large
13552 #endif
13553 #if (DUK_STRIDX_UC_THREAD > 255)
13554 #error constant too large
13555 #endif
13556 #if (DUK_STRIDX_ARRAY_BUFFER > 255)
13557 #error constant too large
13558 #endif
13559 #if (DUK_STRIDX_DATA_VIEW > 255)
13560 #error constant too large
13561 #endif
13562 #if (DUK_STRIDX_INT8_ARRAY > 255)
13563 #error constant too large
13564 #endif
13565 #if (DUK_STRIDX_UINT8_ARRAY > 255)
13566 #error constant too large
13567 #endif
13568 #if (DUK_STRIDX_UINT8_CLAMPED_ARRAY > 255)
13569 #error constant too large
13570 #endif
13571 #if (DUK_STRIDX_INT16_ARRAY > 255)
13572 #error constant too large
13573 #endif
13574 #if (DUK_STRIDX_UINT16_ARRAY > 255)
13575 #error constant too large
13576 #endif
13577 #if (DUK_STRIDX_INT32_ARRAY > 255)
13578 #error constant too large
13579 #endif
13580 #if (DUK_STRIDX_UINT32_ARRAY > 255)
13581 #error constant too large
13582 #endif
13583 #if (DUK_STRIDX_FLOAT32_ARRAY > 255)
13584 #error constant too large
13585 #endif
13586 #if (DUK_STRIDX_FLOAT64_ARRAY > 255)
13587 #error constant too large
13588 #endif
13589 #if (DUK_STRIDX_EMPTY_STRING > 255)
13590 #error constant too large
13591 #endif
13592 
13593 /* Note: assumes that these string indexes are 8-bit, genstrings.py must ensure that */
13594 DUK_INTERNAL duk_uint8_t duk_class_number_to_stridx[32] = {
13595 	DUK_STRIDX_EMPTY_STRING,  /* NONE, intentionally empty */
13596 	DUK_STRIDX_UC_OBJECT,
13597 	DUK_STRIDX_UC_ARRAY,
13598 	DUK_STRIDX_UC_FUNCTION,
13599 	DUK_STRIDX_UC_ARGUMENTS,
13600 	DUK_STRIDX_UC_BOOLEAN,
13601 	DUK_STRIDX_UC_DATE,
13602 	DUK_STRIDX_UC_ERROR,
13603 	DUK_STRIDX_JSON,
13604 	DUK_STRIDX_MATH,
13605 	DUK_STRIDX_UC_NUMBER,
13606 	DUK_STRIDX_REG_EXP,
13607 	DUK_STRIDX_UC_STRING,
13608 	DUK_STRIDX_GLOBAL,
13609 	DUK_STRIDX_UC_SYMBOL,
13610 	DUK_STRIDX_OBJ_ENV,
13611 	DUK_STRIDX_DEC_ENV,
13612 	DUK_STRIDX_UC_POINTER,
13613 	DUK_STRIDX_UC_THREAD,
13614 	DUK_STRIDX_ARRAY_BUFFER,
13615 	DUK_STRIDX_DATA_VIEW,
13616 	DUK_STRIDX_INT8_ARRAY,
13617 	DUK_STRIDX_UINT8_ARRAY,
13618 	DUK_STRIDX_UINT8_CLAMPED_ARRAY,
13619 	DUK_STRIDX_INT16_ARRAY,
13620 	DUK_STRIDX_UINT16_ARRAY,
13621 	DUK_STRIDX_INT32_ARRAY,
13622 	DUK_STRIDX_UINT32_ARRAY,
13623 	DUK_STRIDX_FLOAT32_ARRAY,
13624 	DUK_STRIDX_FLOAT64_ARRAY,
13625 	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
13626 	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
13627 };
13628 /*
13629  *  Default allocation functions.
13630  *
13631  *  Assumes behavior such as malloc allowing zero size, yielding
13632  *  a NULL or a unique pointer which is a no-op for free.
13633  */
13634 
13635 /* #include duk_internal.h -> already included */
13636 
13637 #if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
duk_default_alloc_function(void * udata,duk_size_t size)13638 DUK_INTERNAL void *duk_default_alloc_function(void *udata, duk_size_t size) {
13639 	void *res;
13640 	DUK_UNREF(udata);
13641 	res = DUK_ANSI_MALLOC(size);
13642 	DUK_DDD(DUK_DDDPRINT("default alloc function: %lu -> %p",
13643 	                     (unsigned long) size, (void *) res));
13644 	return res;
13645 }
13646 
duk_default_realloc_function(void * udata,void * ptr,duk_size_t newsize)13647 DUK_INTERNAL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize) {
13648 	void *res;
13649 	DUK_UNREF(udata);
13650 	res = DUK_ANSI_REALLOC(ptr, newsize);
13651 	DUK_DDD(DUK_DDDPRINT("default realloc function: %p %lu -> %p",
13652 	                     (void *) ptr, (unsigned long) newsize, (void *) res));
13653 	return res;
13654 }
13655 
duk_default_free_function(void * udata,void * ptr)13656 DUK_INTERNAL void duk_default_free_function(void *udata, void *ptr) {
13657 	DUK_DDD(DUK_DDDPRINT("default free function: %p", (void *) ptr));
13658 	DUK_UNREF(udata);
13659 	DUK_ANSI_FREE(ptr);
13660 }
13661 #endif  /* DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS */
13662 /*
13663  *  Buffer
13664  */
13665 
13666 /* #include duk_internal.h -> already included */
13667 
duk_resize_buffer(duk_hthread * thr,duk_idx_t idx,duk_size_t new_size)13668 DUK_EXTERNAL void *duk_resize_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t new_size) {
13669 	duk_hbuffer_dynamic *h;
13670 
13671 	DUK_ASSERT_API_ENTRY(thr);
13672 
13673 	h = (duk_hbuffer_dynamic *) duk_require_hbuffer(thr, idx);
13674 	DUK_ASSERT(h != NULL);
13675 
13676 	if (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) {
13677 		DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
13678 		DUK_WO_NORETURN(return NULL;);
13679 	}
13680 
13681 	/* Maximum size check is handled by callee. */
13682 	duk_hbuffer_resize(thr, h, new_size);
13683 
13684 	return DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);
13685 }
13686 
duk_steal_buffer(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size)13687 DUK_EXTERNAL void *duk_steal_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
13688 	duk_hbuffer_dynamic *h;
13689 	void *ptr;
13690 	duk_size_t sz;
13691 
13692 	DUK_ASSERT_API_ENTRY(thr);
13693 
13694 	h = (duk_hbuffer_dynamic *) duk_require_hbuffer(thr, idx);
13695 	DUK_ASSERT(h != NULL);
13696 
13697 	if (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) {
13698 		DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
13699 		DUK_WO_NORETURN(return NULL;);
13700 	}
13701 
13702 	/* Forget the previous allocation, setting size to 0 and alloc to
13703 	 * NULL.  Caller is responsible for freeing the previous allocation.
13704 	 * Getting the allocation and clearing it is done in the same API
13705 	 * call to avoid any chance of a realloc.
13706 	 */
13707 	ptr = DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);
13708 	sz = DUK_HBUFFER_DYNAMIC_GET_SIZE(h);
13709 	if (out_size) {
13710 		*out_size = sz;
13711 	}
13712 	DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(thr->heap, h);
13713 	DUK_HBUFFER_DYNAMIC_SET_SIZE(h, 0);
13714 
13715 	return ptr;
13716 }
13717 
duk_config_buffer(duk_hthread * thr,duk_idx_t idx,void * ptr,duk_size_t len)13718 DUK_EXTERNAL void duk_config_buffer(duk_hthread *thr, duk_idx_t idx, void *ptr, duk_size_t len) {
13719 	duk_hbuffer_external *h;
13720 
13721 	DUK_ASSERT_API_ENTRY(thr);
13722 
13723 	h = (duk_hbuffer_external *) duk_require_hbuffer(thr, idx);
13724 	DUK_ASSERT(h != NULL);
13725 
13726 	if (!DUK_HBUFFER_HAS_EXTERNAL(h)) {
13727 		DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
13728 		DUK_WO_NORETURN(return;);
13729 	}
13730 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h));
13731 
13732 	DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(thr->heap, h, ptr);
13733 	DUK_HBUFFER_EXTERNAL_SET_SIZE(h, len);
13734 }
13735 /*
13736  *  Bytecode dump/load
13737  *
13738  *  The bytecode load primitive is more important performance-wise than the
13739  *  dump primitive.
13740  *
13741  *  Unlike most Duktape API calls, bytecode dump/load is not guaranteed to be
13742  *  memory safe for invalid arguments - caller beware!  There's little point
13743  *  in trying to achieve memory safety unless bytecode instructions are also
13744  *  validated which is not easy to do with indirect register references etc.
13745  */
13746 
13747 /* #include duk_internal.h -> already included */
13748 
13749 #if defined(DUK_USE_BYTECODE_DUMP_SUPPORT)
13750 
13751 #define DUK__SER_MARKER  0xbf
13752 #define DUK__SER_STRING  0x00
13753 #define DUK__SER_NUMBER  0x01
13754 #define DUK__BYTECODE_INITIAL_ALLOC 256
13755 #define DUK__NO_FORMALS  0xffffffffUL
13756 
13757 /*
13758  *  Dump/load helpers, xxx_raw() helpers do no buffer checks
13759  */
13760 
duk__load_string_raw(duk_hthread * thr,const duk_uint8_t * p)13761 DUK_LOCAL const duk_uint8_t *duk__load_string_raw(duk_hthread *thr, const duk_uint8_t *p) {
13762 	duk_uint32_t len;
13763 
13764 	len = DUK_RAW_READINC_U32_BE(p);
13765 	duk_push_lstring(thr, (const char *) p, len);
13766 	p += len;
13767 	return p;
13768 }
13769 
duk__load_buffer_raw(duk_hthread * thr,const duk_uint8_t * p)13770 DUK_LOCAL const duk_uint8_t *duk__load_buffer_raw(duk_hthread *thr, const duk_uint8_t *p) {
13771 	duk_uint32_t len;
13772 	duk_uint8_t *buf;
13773 
13774 	len = DUK_RAW_READINC_U32_BE(p);
13775 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) len);
13776 	DUK_ASSERT(buf != NULL);
13777 	duk_memcpy((void *) buf, (const void *) p, (size_t) len);
13778 	p += len;
13779 	return p;
13780 }
13781 
duk__dump_hstring_raw(duk_uint8_t * p,duk_hstring * h)13782 DUK_LOCAL duk_uint8_t *duk__dump_hstring_raw(duk_uint8_t *p, duk_hstring *h) {
13783 	duk_size_t len;
13784 	duk_uint32_t tmp32;
13785 
13786 	DUK_ASSERT(h != NULL);
13787 
13788 	len = DUK_HSTRING_GET_BYTELEN(h);
13789 	DUK_ASSERT(len <= 0xffffffffUL);  /* string limits */
13790 	tmp32 = (duk_uint32_t) len;
13791 	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
13792 	duk_memcpy((void *) p,
13793 	           (const void *) DUK_HSTRING_GET_DATA(h),
13794 	           len);
13795 	p += len;
13796 	return p;
13797 }
13798 
duk__dump_hbuffer_raw(duk_hthread * thr,duk_uint8_t * p,duk_hbuffer * h)13799 DUK_LOCAL duk_uint8_t *duk__dump_hbuffer_raw(duk_hthread *thr, duk_uint8_t *p, duk_hbuffer *h) {
13800 	duk_size_t len;
13801 	duk_uint32_t tmp32;
13802 
13803 	DUK_ASSERT(thr != NULL);
13804 	DUK_ASSERT(h != NULL);
13805 	DUK_UNREF(thr);
13806 
13807 	len = DUK_HBUFFER_GET_SIZE(h);
13808 	DUK_ASSERT(len <= 0xffffffffUL);  /* buffer limits */
13809 	tmp32 = (duk_uint32_t) len;
13810 	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
13811 	/* When len == 0, buffer data pointer may be NULL. */
13812 	duk_memcpy_unsafe((void *) p,
13813 	                  (const void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h),
13814 	                  len);
13815 	p += len;
13816 	return p;
13817 }
13818 
duk__dump_string_prop(duk_hthread * thr,duk_uint8_t * p,duk_bufwriter_ctx * bw_ctx,duk_hobject * func,duk_small_uint_t stridx)13819 DUK_LOCAL duk_uint8_t *duk__dump_string_prop(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func, duk_small_uint_t stridx) {
13820 	duk_hstring *h_str;
13821 	duk_tval *tv;
13822 
13823 	tv = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, (duk_hobject *) func, stridx);
13824 	if (tv != NULL && DUK_TVAL_IS_STRING(tv)) {
13825 		h_str = DUK_TVAL_GET_STRING(tv);
13826 		DUK_ASSERT(h_str != NULL);
13827 	} else {
13828 		h_str = DUK_HTHREAD_STRING_EMPTY_STRING(thr);
13829 		DUK_ASSERT(h_str != NULL);
13830 	}
13831 	DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
13832 	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(h_str), p);
13833 	p = duk__dump_hstring_raw(p, h_str);
13834 	return p;
13835 }
13836 
duk__dump_buffer_prop(duk_hthread * thr,duk_uint8_t * p,duk_bufwriter_ctx * bw_ctx,duk_hobject * func,duk_small_uint_t stridx)13837 DUK_LOCAL duk_uint8_t *duk__dump_buffer_prop(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func, duk_small_uint_t stridx) {
13838 	duk_tval *tv;
13839 
13840 	tv = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, (duk_hobject *) func, stridx);
13841 	if (tv != NULL && DUK_TVAL_IS_BUFFER(tv)) {
13842 		duk_hbuffer *h_buf;
13843 		h_buf = DUK_TVAL_GET_BUFFER(tv);
13844 		DUK_ASSERT(h_buf != NULL);
13845 		DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
13846 		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HBUFFER_GET_SIZE(h_buf), p);
13847 		p = duk__dump_hbuffer_raw(thr, p, h_buf);
13848 	} else {
13849 		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
13850 		DUK_RAW_WRITEINC_U32_BE(p, 0);
13851 	}
13852 	return p;
13853 }
13854 
duk__dump_uint32_prop(duk_hthread * thr,duk_uint8_t * p,duk_bufwriter_ctx * bw_ctx,duk_hobject * func,duk_small_uint_t stridx,duk_uint32_t def_value)13855 DUK_LOCAL duk_uint8_t *duk__dump_uint32_prop(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func, duk_small_uint_t stridx, duk_uint32_t def_value) {
13856 	duk_tval *tv;
13857 	duk_uint32_t val;
13858 
13859 	tv = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, (duk_hobject *) func, stridx);
13860 	if (tv != NULL && DUK_TVAL_IS_NUMBER(tv)) {
13861 		val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv);
13862 	} else {
13863 		val = def_value;
13864 	}
13865 	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
13866 	DUK_RAW_WRITEINC_U32_BE(p, val);
13867 	return p;
13868 }
13869 
duk__dump_varmap(duk_hthread * thr,duk_uint8_t * p,duk_bufwriter_ctx * bw_ctx,duk_hobject * func)13870 DUK_LOCAL duk_uint8_t *duk__dump_varmap(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
13871 	duk_hobject *h;
13872 
13873 	h = duk_hobject_get_varmap(thr, (duk_hobject *) func);
13874 	if (h != NULL) {
13875 		duk_uint_fast32_t i;
13876 
13877 		/* We know _Varmap only has own properties so walk property
13878 		 * table directly.  We also know _Varmap is dense and all
13879 		 * values are numbers; assert for these.  GC and finalizers
13880 		 * shouldn't affect _Varmap so side effects should be fine.
13881 		 */
13882 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
13883 			duk_hstring *key;
13884 			duk_tval *tv_val;
13885 			duk_uint32_t val;
13886 
13887 			key = DUK_HOBJECT_E_GET_KEY(thr->heap, h, i);
13888 			DUK_ASSERT(key != NULL);  /* _Varmap is dense */
13889 			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h, i));
13890 			tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h, i);
13891 			DUK_ASSERT(tv_val != NULL);
13892 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_val));  /* known to be number; in fact an integer */
13893 #if defined(DUK_USE_FASTINT)
13894 			DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv_val));
13895 			DUK_ASSERT(DUK_TVAL_GET_FASTINT(tv_val) == (duk_int64_t) DUK_TVAL_GET_FASTINT_U32(tv_val));  /* known to be 32-bit */
13896 			val = DUK_TVAL_GET_FASTINT_U32(tv_val);
13897 #else
13898 			val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv_val);
13899 #endif
13900 
13901 			DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
13902 			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(key) + 4U, p);
13903 			p = duk__dump_hstring_raw(p, key);
13904 			DUK_RAW_WRITEINC_U32_BE(p, val);
13905 		}
13906 	}
13907 	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
13908 	DUK_RAW_WRITEINC_U32_BE(p, 0);  /* end of _Varmap */
13909 	return p;
13910 }
13911 
duk__dump_formals(duk_hthread * thr,duk_uint8_t * p,duk_bufwriter_ctx * bw_ctx,duk_hobject * func)13912 DUK_LOCAL duk_uint8_t *duk__dump_formals(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
13913 	duk_harray *h;
13914 
13915 	h = duk_hobject_get_formals(thr, (duk_hobject *) func);
13916 	if (h != NULL) {
13917 		duk_uint32_t i;
13918 
13919 		/* Here we rely on _Formals being a dense array containing
13920 		 * strings.  This should be the case unless _Formals has been
13921 		 * tweaked by the application (which we don't support right
13922 		 * now).
13923 		 */
13924 
13925 		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
13926 		DUK_ASSERT(h->length != DUK__NO_FORMALS);  /* limits */
13927 		DUK_RAW_WRITEINC_U32_BE(p, h->length);
13928 
13929 		for (i = 0; i < h->length; i++) {
13930 			duk_tval *tv_val;
13931 			duk_hstring *varname;
13932 
13933 			tv_val = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, (duk_hobject *) h, i);
13934 			DUK_ASSERT(tv_val != NULL);
13935 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv_val));
13936 
13937 			varname = DUK_TVAL_GET_STRING(tv_val);
13938 			DUK_ASSERT(varname != NULL);
13939 			DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(varname) >= 1);
13940 
13941 			DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
13942 			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(varname), p);
13943 			p = duk__dump_hstring_raw(p, varname);
13944 		}
13945 	} else {
13946 		DUK_DD(DUK_DDPRINT("dumping function without _Formals, emit marker to indicate missing _Formals"));
13947 		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
13948 		DUK_RAW_WRITEINC_U32_BE(p, DUK__NO_FORMALS);  /* marker: no formals */
13949 	}
13950 	return p;
13951 }
13952 
duk__dump_func(duk_hthread * thr,duk_hcompfunc * func,duk_bufwriter_ctx * bw_ctx,duk_uint8_t * p)13953 static duk_uint8_t *duk__dump_func(duk_hthread *thr, duk_hcompfunc *func, duk_bufwriter_ctx *bw_ctx, duk_uint8_t *p) {
13954 	duk_tval *tv, *tv_end;
13955 	duk_instr_t *ins, *ins_end;
13956 	duk_hobject **fn, **fn_end;
13957 	duk_hstring *h_str;
13958 	duk_uint32_t count_instr;
13959 	duk_uint32_t tmp32;
13960 	duk_uint16_t tmp16;
13961 	duk_double_t d;
13962 
13963 	DUK_DD(DUK_DDPRINT("dumping function %p to %p: "
13964 	                   "consts=[%p,%p[ (%ld bytes, %ld items), "
13965 	                   "funcs=[%p,%p[ (%ld bytes, %ld items), "
13966 	                   "code=[%p,%p[ (%ld bytes, %ld items)",
13967 	                   (void *) func,
13968 	                   (void *) p,
13969 	                   (void *) DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, func),
13970 	                   (void *) DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, func),
13971 	                   (long) DUK_HCOMPFUNC_GET_CONSTS_SIZE(thr->heap, func),
13972 	                   (long) DUK_HCOMPFUNC_GET_CONSTS_COUNT(thr->heap, func),
13973 	                   (void *) DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, func),
13974 	                   (void *) DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, func),
13975 	                   (long) DUK_HCOMPFUNC_GET_FUNCS_SIZE(thr->heap, func),
13976 	                   (long) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, func),
13977 	                   (void *) DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, func),
13978 	                   (void *) DUK_HCOMPFUNC_GET_CODE_END(thr->heap, func),
13979 	                   (long) DUK_HCOMPFUNC_GET_CODE_SIZE(thr->heap, func),
13980 	                   (long) DUK_HCOMPFUNC_GET_CODE_COUNT(thr->heap, func)));
13981 
13982 	DUK_ASSERT(DUK_USE_ESBC_MAX_BYTES <= 0x7fffffffUL);  /* ensures no overflow */
13983 	count_instr = (duk_uint32_t) DUK_HCOMPFUNC_GET_CODE_COUNT(thr->heap, func);
13984 	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 3U * 4U + 2U * 2U + 3U * 4U + count_instr * 4U, p);
13985 
13986 	/* Fixed header info. */
13987 	tmp32 = count_instr;
13988 	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
13989 	tmp32 = (duk_uint32_t) DUK_HCOMPFUNC_GET_CONSTS_COUNT(thr->heap, func);
13990 	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
13991 	tmp32 = (duk_uint32_t) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, func);
13992 	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
13993 	tmp16 = func->nregs;
13994 	DUK_RAW_WRITEINC_U16_BE(p, tmp16);
13995 	tmp16 = func->nargs;
13996 	DUK_RAW_WRITEINC_U16_BE(p, tmp16);
13997 #if defined(DUK_USE_DEBUGGER_SUPPORT)
13998 	tmp32 = func->start_line;
13999 	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
14000 	tmp32 = func->end_line;
14001 	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
14002 #else
14003 	DUK_RAW_WRITEINC_U32_BE(p, 0);
14004 	DUK_RAW_WRITEINC_U32_BE(p, 0);
14005 #endif
14006 	tmp32 = DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) func);  /* masks flags, only duk_hobject flags */
14007 	tmp32 &= ~(DUK_HOBJECT_FLAG_HAVE_FINALIZER);  /* finalizer flag is lost */
14008 	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
14009 
14010 	/* Bytecode instructions: endian conversion needed unless
14011 	 * platform is big endian.
14012 	 */
14013 	ins = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, func);
14014 	ins_end = DUK_HCOMPFUNC_GET_CODE_END(thr->heap, func);
14015 	DUK_ASSERT((duk_size_t) (ins_end - ins) == (duk_size_t) count_instr);
14016 #if defined(DUK_USE_INTEGER_BE)
14017 	duk_memcpy_unsafe((void *) p, (const void *) ins, (size_t) (ins_end - ins) * 4);
14018 	p += (size_t) (ins_end - ins) * 4;
14019 #else
14020 	while (ins != ins_end) {
14021 		tmp32 = (duk_uint32_t) (*ins);
14022 		DUK_RAW_WRITEINC_U32_BE(p, tmp32);
14023 		ins++;
14024 	}
14025 #endif
14026 
14027 	/* Constants: variable size encoding. */
14028 	tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, func);
14029 	tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, func);
14030 	while (tv != tv_end) {
14031 		/* constants are strings or numbers now */
14032 		DUK_ASSERT(DUK_TVAL_IS_STRING(tv) ||
14033 		           DUK_TVAL_IS_NUMBER(tv));
14034 
14035 		if (DUK_TVAL_IS_STRING(tv)) {
14036 			h_str = DUK_TVAL_GET_STRING(tv);
14037 			DUK_ASSERT(h_str != NULL);
14038 			DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
14039 			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1U + 4U + DUK_HSTRING_GET_BYTELEN(h_str), p);
14040 			*p++ = DUK__SER_STRING;
14041 			p = duk__dump_hstring_raw(p, h_str);
14042 		} else {
14043 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
14044 			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1U + 8U, p);
14045 			*p++ = DUK__SER_NUMBER;
14046 			d = DUK_TVAL_GET_NUMBER(tv);
14047 			DUK_RAW_WRITEINC_DOUBLE_BE(p, d);
14048 		}
14049 		tv++;
14050 	}
14051 
14052 	/* Inner functions recursively. */
14053 	fn = (duk_hobject **) DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, func);
14054 	fn_end = (duk_hobject **) DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, func);
14055 	while (fn != fn_end) {
14056 		/* XXX: This causes recursion up to inner function depth
14057 		 * which is normally not an issue, e.g. mark-and-sweep uses
14058 		 * a recursion limiter to avoid C stack issues.  Avoiding
14059 		 * this would mean some sort of a work list or just refusing
14060 		 * to serialize deep functions.
14061 		 */
14062 		DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(*fn));
14063 		p = duk__dump_func(thr, (duk_hcompfunc *) *fn, bw_ctx, p);
14064 		fn++;
14065 	}
14066 
14067 	/* Lexenv and varenv are not dumped. */
14068 
14069 	/* Object extra properties.
14070 	 *
14071 	 * There are some difference between function templates and functions.
14072 	 * For example, function templates don't have .length and nargs is
14073 	 * normally used to instantiate the functions.
14074 	 */
14075 
14076 	p = duk__dump_uint32_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_LENGTH, (duk_uint32_t) func->nargs);
14077 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
14078 	p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_NAME);
14079 #endif
14080 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
14081 	p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_FILE_NAME);
14082 #endif
14083 #if defined(DUK_USE_PC2LINE)
14084 	p = duk__dump_buffer_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_INT_PC2LINE);
14085 #endif
14086 	p = duk__dump_varmap(thr, p, bw_ctx, (duk_hobject *) func);
14087 	p = duk__dump_formals(thr, p, bw_ctx, (duk_hobject *) func);
14088 
14089 	DUK_DD(DUK_DDPRINT("serialized function %p -> final pointer %p", (void *) func, (void *) p));
14090 
14091 	return p;
14092 }
14093 
14094 /* Load a function from bytecode.  The function object returned here must
14095  * match what is created by duk_js_push_closure() with respect to its flags,
14096  * properties, etc.
14097  *
14098  * NOTE: there are intentionally no input buffer length / bound checks.
14099  * Adding them would be easy but wouldn't ensure memory safety as untrusted
14100  * or broken bytecode is unsafe during execution unless the opcodes themselves
14101  * are validated (which is quite complex, especially for indirect opcodes).
14102  */
14103 
14104 #define DUK__ASSERT_LEFT(n) do { \
14105 		DUK_ASSERT((duk_size_t) (p_end - p) >= (duk_size_t) (n)); \
14106 	} while (0)
14107 
duk__load_func(duk_hthread * thr,const duk_uint8_t * p,const duk_uint8_t * p_end)14108 static const duk_uint8_t *duk__load_func(duk_hthread *thr, const duk_uint8_t *p, const duk_uint8_t *p_end) {
14109 	duk_hcompfunc *h_fun;
14110 	duk_hbuffer *h_data;
14111 	duk_size_t data_size;
14112 	duk_uint32_t count_instr, count_const, count_funcs;
14113 	duk_uint32_t n;
14114 	duk_uint32_t tmp32;
14115 	duk_small_uint_t const_type;
14116 	duk_uint8_t *fun_data;
14117 	duk_uint8_t *q;
14118 	duk_idx_t idx_base;
14119 	duk_tval *tv1;
14120 	duk_uarridx_t arr_idx;
14121 	duk_uarridx_t arr_limit;
14122 	duk_hobject *func_env;
14123 	duk_bool_t need_pop;
14124 
14125 	/* XXX: There's some overlap with duk_js_closure() here, but
14126 	 * seems difficult to share code.  Ensure that the final function
14127 	 * looks the same as created by duk_js_closure().
14128 	 */
14129 
14130 	DUK_ASSERT(thr != NULL);
14131 
14132 	DUK_DD(DUK_DDPRINT("loading function, p=%p, p_end=%p", (const void *) p, (const void *) p_end));
14133 
14134 	DUK__ASSERT_LEFT(3 * 4);
14135 	count_instr = DUK_RAW_READINC_U32_BE(p);
14136 	count_const = DUK_RAW_READINC_U32_BE(p);
14137 	count_funcs = DUK_RAW_READINC_U32_BE(p);
14138 
14139 	data_size = sizeof(duk_tval) * count_const +
14140 	            sizeof(duk_hobject *) * count_funcs +
14141 	            sizeof(duk_instr_t) * count_instr;
14142 
14143 	DUK_DD(DUK_DDPRINT("instr=%ld, const=%ld, funcs=%ld, data_size=%ld",
14144 	                   (long) count_instr, (long) count_const,
14145 	                   (long) count_const, (long) data_size));
14146 
14147 	/* Value stack is used to ensure reachability of constants and
14148 	 * inner functions being loaded.  Require enough space to handle
14149 	 * large functions correctly.
14150 	 */
14151 	duk_require_stack(thr, (duk_idx_t) (2 + count_const + count_funcs));
14152 	idx_base = duk_get_top(thr);
14153 
14154 	/* Push function object, init flags etc.  This must match
14155 	 * duk_js_push_closure() quite carefully.
14156 	 */
14157 	h_fun = duk_push_hcompfunc(thr);
14158 	DUK_ASSERT(h_fun != NULL);
14159 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) h_fun));
14160 	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, h_fun) == NULL);
14161 	DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, h_fun) == NULL);
14162 	DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, h_fun) == NULL);
14163 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_fun) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
14164 
14165 	h_fun->nregs = DUK_RAW_READINC_U16_BE(p);
14166 	h_fun->nargs = DUK_RAW_READINC_U16_BE(p);
14167 #if defined(DUK_USE_DEBUGGER_SUPPORT)
14168 	h_fun->start_line = DUK_RAW_READINC_U32_BE(p);
14169 	h_fun->end_line = DUK_RAW_READINC_U32_BE(p);
14170 #else
14171 	p += 8;  /* skip line info */
14172 #endif
14173 
14174 	/* duk_hcompfunc flags; quite version specific */
14175 	tmp32 = DUK_RAW_READINC_U32_BE(p);
14176 	DUK_HEAPHDR_SET_FLAGS((duk_heaphdr *) h_fun, tmp32);  /* masks flags to only change duk_hobject flags */
14177 
14178 	/* standard prototype (no need to set here, already set) */
14179 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_fun) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
14180 #if 0
14181 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, &h_fun->obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
14182 #endif
14183 
14184 	/* assert just a few critical flags */
14185 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h_fun) == DUK_HTYPE_OBJECT);
14186 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(&h_fun->obj));
14187 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(&h_fun->obj));
14188 	DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(&h_fun->obj));
14189 	DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(&h_fun->obj));
14190 	DUK_ASSERT(!DUK_HOBJECT_IS_PROXY(&h_fun->obj));
14191 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(&h_fun->obj));
14192 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(&h_fun->obj));
14193 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(&h_fun->obj));
14194 
14195 	/* Create function 'data' buffer but don't attach it yet. */
14196 	fun_data = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, data_size);
14197 	DUK_ASSERT(fun_data != NULL);
14198 
14199 	/* Load bytecode instructions. */
14200 	DUK_ASSERT(sizeof(duk_instr_t) == 4);
14201 	DUK__ASSERT_LEFT(count_instr * sizeof(duk_instr_t));
14202 #if defined(DUK_USE_INTEGER_BE)
14203 	q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;
14204 	duk_memcpy((void *) q,
14205 	           (const void *) p,
14206 	           sizeof(duk_instr_t) * count_instr);
14207 	p += sizeof(duk_instr_t) * count_instr;
14208 #else
14209 	q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;
14210 	for (n = count_instr; n > 0; n--) {
14211 		*((duk_instr_t *) (void *) q) = DUK_RAW_READINC_U32_BE(p);
14212 		q += sizeof(duk_instr_t);
14213 	}
14214 #endif
14215 
14216 	/* Load constants onto value stack but don't yet copy to buffer. */
14217 	for (n = count_const; n > 0; n--) {
14218 		DUK__ASSERT_LEFT(1);
14219 		const_type = DUK_RAW_READINC_U8(p);
14220 		switch (const_type) {
14221 		case DUK__SER_STRING: {
14222 			p = duk__load_string_raw(thr, p);
14223 			break;
14224 		}
14225 		case DUK__SER_NUMBER: {
14226 			/* Important to do a fastint check so that constants are
14227 			 * properly read back as fastints.
14228 			 */
14229 			duk_tval tv_tmp;
14230 			duk_double_t val;
14231 			DUK__ASSERT_LEFT(8);
14232 			val = DUK_RAW_READINC_DOUBLE_BE(p);
14233 			DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(&tv_tmp, val);
14234 			duk_push_tval(thr, &tv_tmp);
14235 			break;
14236 		}
14237 		default: {
14238 			goto format_error;
14239 		}
14240 		}
14241 	}
14242 
14243 	/* Load inner functions to value stack, but don't yet copy to buffer. */
14244 	for (n = count_funcs; n > 0; n--) {
14245 		p = duk__load_func(thr, p, p_end);
14246 		if (p == NULL) {
14247 			goto format_error;
14248 		}
14249 	}
14250 
14251 	/* With constants and inner functions on value stack, we can now
14252 	 * atomically finish the function 'data' buffer, bump refcounts,
14253 	 * etc.
14254 	 *
14255 	 * Here we take advantage of the value stack being just a duk_tval
14256 	 * array: we can just memcpy() the constants as long as we incref
14257 	 * them afterwards.
14258 	 */
14259 
14260 	h_data = (duk_hbuffer *) duk_known_hbuffer(thr, idx_base + 1);
14261 	DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC(h_data));
14262 	DUK_HCOMPFUNC_SET_DATA(thr->heap, h_fun, h_data);
14263 	DUK_HBUFFER_INCREF(thr, h_data);
14264 
14265 	tv1 = duk_get_tval(thr, idx_base + 2);  /* may be NULL if no constants or inner funcs */
14266 	DUK_ASSERT((count_const == 0 && count_funcs == 0) || tv1 != NULL);
14267 
14268 	q = fun_data;
14269 	duk_memcpy_unsafe((void *) q, (const void *) tv1, sizeof(duk_tval) * count_const);
14270 	for (n = count_const; n > 0; n--) {
14271 		DUK_TVAL_INCREF_FAST(thr, (duk_tval *) (void *) q);  /* no side effects */
14272 		q += sizeof(duk_tval);
14273 	}
14274 	tv1 += count_const;
14275 
14276 	DUK_HCOMPFUNC_SET_FUNCS(thr->heap, h_fun, (duk_hobject **) (void *) q);
14277 	for (n = count_funcs; n > 0; n--) {
14278 		duk_hobject *h_obj;
14279 
14280 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv1));
14281 		h_obj = DUK_TVAL_GET_OBJECT(tv1);
14282 		DUK_ASSERT(h_obj != NULL);
14283 		tv1++;
14284 		DUK_HOBJECT_INCREF(thr, h_obj);
14285 
14286 		*((duk_hobject **) (void *) q) = h_obj;
14287 		q += sizeof(duk_hobject *);
14288 	}
14289 
14290 	DUK_HCOMPFUNC_SET_BYTECODE(thr->heap, h_fun, (duk_instr_t *) (void *) q);
14291 
14292 	/* The function object is now reachable and refcounts are fine,
14293 	 * so we can pop off all the temporaries.
14294 	 */
14295 	DUK_DDD(DUK_DDDPRINT("function is reachable, reset top; func: %!iT", duk_get_tval(thr, idx_base)));
14296 	duk_set_top(thr, idx_base + 1);
14297 
14298 	/* Setup function properties. */
14299 	tmp32 = DUK_RAW_READINC_U32_BE(p);
14300 	duk_push_u32(thr, tmp32);
14301 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);
14302 
14303 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
14304 	p = duk__load_string_raw(thr, p);  /* -> [ func funcname ] */
14305 	func_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
14306 	DUK_ASSERT(func_env != NULL);
14307 	need_pop = 0;
14308 	if (DUK_HOBJECT_HAS_NAMEBINDING((duk_hobject *) h_fun)) {
14309 		/* Original function instance/template had NAMEBINDING.
14310 		 * Must create a lexical environment on loading to allow
14311 		 * recursive functions like 'function foo() { foo(); }'.
14312 		 */
14313 		duk_hdecenv *new_env;
14314 
14315 		new_env = duk_hdecenv_alloc(thr,
14316 		                            DUK_HOBJECT_FLAG_EXTENSIBLE |
14317 		                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
14318 		DUK_ASSERT(new_env != NULL);
14319 		DUK_ASSERT(new_env->thread == NULL);  /* Closed. */
14320 		DUK_ASSERT(new_env->varmap == NULL);
14321 		DUK_ASSERT(new_env->regbase_byteoff == 0);
14322 		DUK_HDECENV_ASSERT_VALID(new_env);
14323 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
14324 		DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, func_env);
14325 		DUK_HOBJECT_INCREF(thr, func_env);
14326 
14327 		func_env = (duk_hobject *) new_env;
14328 
14329 		duk_push_hobject(thr, (duk_hobject *) new_env);
14330 
14331 		duk_dup_m2(thr);                                  /* -> [ func funcname env funcname ] */
14332 		duk_dup(thr, idx_base);                           /* -> [ func funcname env funcname func ] */
14333 		duk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_NONE);  /* -> [ func funcname env ] */
14334 
14335 		need_pop = 1;  /* Need to pop env, but -after- updating h_fun and increfs. */
14336 	}
14337 	DUK_ASSERT(func_env != NULL);
14338 	DUK_HCOMPFUNC_SET_LEXENV(thr->heap, h_fun, func_env);
14339 	DUK_HCOMPFUNC_SET_VARENV(thr->heap, h_fun, func_env);
14340 	DUK_HOBJECT_INCREF(thr, func_env);
14341 	DUK_HOBJECT_INCREF(thr, func_env);
14342 	if (need_pop) {
14343 		duk_pop(thr);
14344 	}
14345 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
14346 #endif  /* DUK_USE_FUNC_NAME_PROPERTY */
14347 
14348 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
14349 	p = duk__load_string_raw(thr, p);
14350 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_C);
14351 #endif  /* DUK_USE_FUNC_FILENAME_PROPERTY */
14352 
14353 	if (DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) h_fun)) {
14354 		/* Restore empty external .prototype only for constructable
14355 		 * functions.  The prototype object should inherit from
14356 		 * Object.prototype.
14357 		 */
14358 		duk_push_object(thr);
14359 		DUK_ASSERT(!duk_is_bare_object(thr, -1));
14360 		duk_dup_m2(thr);
14361 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC);  /* func.prototype.constructor = func */
14362 		duk_compact_m1(thr);
14363 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W);
14364 	}
14365 
14366 #if defined(DUK_USE_PC2LINE)
14367 	p = duk__load_buffer_raw(thr, p);
14368 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_PC2LINE, DUK_PROPDESC_FLAGS_WC);
14369 #endif  /* DUK_USE_PC2LINE */
14370 
14371 	duk_push_bare_object(thr);  /* _Varmap */
14372 	for (;;) {
14373 		/* XXX: awkward */
14374 		p = duk__load_string_raw(thr, p);
14375 		if (duk_get_length(thr, -1) == 0) {
14376 			duk_pop(thr);
14377 			break;
14378 		}
14379 		tmp32 = DUK_RAW_READINC_U32_BE(p);
14380 		duk_push_u32(thr, tmp32);
14381 		duk_put_prop(thr, -3);
14382 	}
14383 	duk_compact_m1(thr);
14384 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VARMAP, DUK_PROPDESC_FLAGS_NONE);
14385 
14386 	/* _Formals may have been missing in the original function, which is
14387 	 * handled using a marker length.
14388 	 */
14389 	arr_limit = DUK_RAW_READINC_U32_BE(p);
14390 	if (arr_limit != DUK__NO_FORMALS) {
14391 		duk_push_bare_array(thr);  /* _Formals */
14392 		for (arr_idx = 0; arr_idx < arr_limit; arr_idx++) {
14393 			p = duk__load_string_raw(thr, p);
14394 			duk_put_prop_index(thr, -2, arr_idx);
14395 		}
14396 		duk_compact_m1(thr);
14397 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_FORMALS, DUK_PROPDESC_FLAGS_NONE);
14398 	} else {
14399 		DUK_DD(DUK_DDPRINT("no _Formals in dumped function"));
14400 	}
14401 
14402 	/* Return with final function pushed on stack top. */
14403 	DUK_DD(DUK_DDPRINT("final loaded function: %!iT", duk_get_tval(thr, -1)));
14404 	DUK_ASSERT_TOP(thr, idx_base + 1);
14405 	return p;
14406 
14407  format_error:
14408 	return NULL;
14409 }
14410 
duk_dump_function(duk_hthread * thr)14411 DUK_EXTERNAL void duk_dump_function(duk_hthread *thr) {
14412 	duk_hcompfunc *func;
14413 	duk_bufwriter_ctx bw_ctx_alloc;
14414 	duk_bufwriter_ctx *bw_ctx = &bw_ctx_alloc;
14415 	duk_uint8_t *p;
14416 
14417 	DUK_ASSERT_API_ENTRY(thr);
14418 
14419 	/* Bound functions don't have all properties so we'd either need to
14420 	 * lookup the non-bound target function or reject bound functions.
14421 	 * For now, bound functions are rejected with TypeError.
14422 	 */
14423 	func = duk_require_hcompfunc(thr, -1);
14424 	DUK_ASSERT(func != NULL);
14425 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(&func->obj));
14426 
14427 	/* Estimating the result size beforehand would be costly, so
14428 	 * start with a reasonable size and extend as needed.
14429 	 */
14430 	DUK_BW_INIT_PUSHBUF(thr, bw_ctx, DUK__BYTECODE_INITIAL_ALLOC);
14431 	p = DUK_BW_GET_PTR(thr, bw_ctx);
14432 	*p++ = DUK__SER_MARKER;
14433 	p = duk__dump_func(thr, func, bw_ctx, p);
14434 	DUK_BW_SET_PTR(thr, bw_ctx, p);
14435 	DUK_BW_COMPACT(thr, bw_ctx);
14436 
14437 	DUK_DD(DUK_DDPRINT("serialized result: %!T", duk_get_tval(thr, -1)));
14438 
14439 	duk_remove_m2(thr);  /* [ ... func buf ] -> [ ... buf ] */
14440 }
14441 
duk_load_function(duk_hthread * thr)14442 DUK_EXTERNAL void duk_load_function(duk_hthread *thr) {
14443 	const duk_uint8_t *p_buf, *p, *p_end;
14444 	duk_size_t sz;
14445 
14446 	DUK_ASSERT_API_ENTRY(thr);
14447 
14448 	p_buf = (duk_uint8_t *) duk_require_buffer(thr, -1, &sz);
14449 	DUK_ASSERT(p_buf != NULL);
14450 
14451 	/* The caller is responsible for being sure that bytecode being loaded
14452 	 * is valid and trusted.  Invalid bytecode can cause memory unsafe
14453 	 * behavior directly during loading or later during bytecode execution
14454 	 * (instruction validation would be quite complex to implement).
14455 	 *
14456 	 * This signature check is the only sanity check for detecting
14457 	 * accidental invalid inputs.  The initial byte ensures no ordinary
14458 	 * string or Symbol will be accepted by accident.
14459 	 */
14460 	p = p_buf;
14461 	p_end = p_buf + sz;
14462 	if (sz < 1 || p[0] != DUK__SER_MARKER) {
14463 		goto format_error;
14464 	}
14465 	p++;
14466 
14467 	p = duk__load_func(thr, p, p_end);
14468 	if (p == NULL) {
14469 		goto format_error;
14470 	}
14471 
14472 	duk_remove_m2(thr);  /* [ ... buf func ] -> [ ... func ] */
14473 	return;
14474 
14475  format_error:
14476 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BYTECODE);
14477 	DUK_WO_NORETURN(return;);
14478 }
14479 
14480 #else  /* DUK_USE_BYTECODE_DUMP_SUPPORT */
14481 
duk_dump_function(duk_hthread * thr)14482 DUK_EXTERNAL void duk_dump_function(duk_hthread *thr) {
14483 	DUK_ASSERT_API_ENTRY(thr);
14484 	DUK_ERROR_UNSUPPORTED(thr);
14485 	DUK_WO_NORETURN(return;);
14486 }
14487 
duk_load_function(duk_hthread * thr)14488 DUK_EXTERNAL void duk_load_function(duk_hthread *thr) {
14489 	DUK_ASSERT_API_ENTRY(thr);
14490 	DUK_ERROR_UNSUPPORTED(thr);
14491 	DUK_WO_NORETURN(return;);
14492 }
14493 
14494 #endif  /* DUK_USE_BYTECODE_DUMP_SUPPORT */
14495 
14496 /* automatic undefs */
14497 #undef DUK__ASSERT_LEFT
14498 #undef DUK__BYTECODE_INITIAL_ALLOC
14499 #undef DUK__NO_FORMALS
14500 #undef DUK__SER_MARKER
14501 #undef DUK__SER_NUMBER
14502 #undef DUK__SER_STRING
14503 /*
14504  *  Calls.
14505  *
14506  *  Protected variants should avoid ever throwing an error.  Must be careful
14507  *  to catch errors related to value stack manipulation and property lookup,
14508  *  not just the call itself.
14509  *
14510  *  The only exception is when arguments are insane, e.g. nargs/nrets are out
14511  *  of bounds; in such cases an error is thrown for two reasons.  First, we
14512  *  can't always respect the value stack input/output guarantees in such cases
14513  *  so the caller would end up with the value stack in an unexpected state.
14514  *  Second, an attempt to create an error might itself fail (although this
14515  *  could be avoided by pushing a preallocated object/string or a primitive
14516  *  value).
14517  */
14518 
14519 /* #include duk_internal.h -> already included */
14520 
14521 /*
14522  *  Helpers
14523  */
14524 
14525 struct duk__pcall_prop_args {
14526 	duk_idx_t obj_idx;
14527 	duk_idx_t nargs;
14528 	duk_small_uint_t call_flags;
14529 };
14530 typedef struct duk__pcall_prop_args duk__pcall_prop_args;
14531 
14532 struct duk__pcall_method_args {
14533 	duk_idx_t nargs;
14534 	duk_small_uint_t call_flags;
14535 };
14536 typedef struct duk__pcall_method_args duk__pcall_method_args;
14537 
14538 struct duk__pcall_args {
14539 	duk_idx_t nargs;
14540 	duk_small_uint_t call_flags;
14541 };
14542 typedef struct duk__pcall_args duk__pcall_args;
14543 
14544 /* Compute and validate idx_func for a certain 'nargs' and 'other'
14545  * parameter count (1 or 2, depending on whether 'this' binding is
14546  * present).
14547  */
duk__call_get_idx_func(duk_hthread * thr,duk_idx_t nargs,duk_idx_t other)14548 DUK_LOCAL duk_idx_t duk__call_get_idx_func(duk_hthread *thr, duk_idx_t nargs, duk_idx_t other) {
14549 	duk_idx_t idx_func;
14550 
14551 	/* XXX: byte arithmetic? */
14552 
14553 	DUK_ASSERT(other >= 0);
14554 
14555 	idx_func = duk_get_top(thr) - nargs - other;
14556 	if (DUK_UNLIKELY((idx_func | nargs) < 0)) {  /* idx_func < 0 || nargs < 0; OR sign bits */
14557 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14558 		DUK_WO_NORETURN(return 0;);
14559 	}
14560 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14561 	return idx_func;
14562 }
14563 
14564 /* Compute idx_func, assume index will be valid.  This is a valid assumption
14565  * for protected calls: nargs < 0 is checked explicitly and duk_safe_call()
14566  * validates the argument count.
14567  */
duk__call_get_idx_func_unvalidated(duk_hthread * thr,duk_idx_t nargs,duk_idx_t other)14568 DUK_LOCAL duk_idx_t duk__call_get_idx_func_unvalidated(duk_hthread *thr, duk_idx_t nargs, duk_idx_t other) {
14569 	duk_idx_t idx_func;
14570 
14571 	/* XXX: byte arithmetic? */
14572 
14573 	DUK_ASSERT(nargs >= 0);
14574 	DUK_ASSERT(other >= 0);
14575 
14576 	idx_func = duk_get_top(thr) - nargs - other;
14577 	DUK_ASSERT(idx_func >= 0);
14578 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14579 	return idx_func;
14580 }
14581 
14582 /* Prepare value stack for a method call through an object property.
14583  * May currently throw an error e.g. when getting the property.
14584  */
duk__call_prop_prep_stack(duk_hthread * thr,duk_idx_t normalized_obj_idx,duk_idx_t nargs)14585 DUK_LOCAL void duk__call_prop_prep_stack(duk_hthread *thr, duk_idx_t normalized_obj_idx, duk_idx_t nargs) {
14586 	DUK_CTX_ASSERT_VALID(thr);
14587 	DUK_ASSERT(nargs >= 0);
14588 
14589 	DUK_DDD(DUK_DDDPRINT("duk__call_prop_prep_stack, normalized_obj_idx=%ld, nargs=%ld, stacktop=%ld",
14590 	                     (long) normalized_obj_idx, (long) nargs, (long) duk_get_top(thr)));
14591 
14592 	/* [... key arg1 ... argN] */
14593 
14594 	/* duplicate key */
14595 	duk_dup(thr, -nargs - 1);  /* Note: -nargs alone would fail for nargs == 0, this is OK */
14596 	(void) duk_get_prop(thr, normalized_obj_idx);
14597 
14598 	DUK_DDD(DUK_DDDPRINT("func: %!T", (duk_tval *) duk_get_tval(thr, -1)));
14599 
14600 #if defined(DUK_USE_VERBOSE_ERRORS)
14601 	if (DUK_UNLIKELY(!duk_is_callable(thr, -1))) {
14602 		duk_tval *tv_base;
14603 		duk_tval *tv_key;
14604 
14605 		/* tv_targ is passed on stack top (at index -1). */
14606 		tv_base = DUK_GET_TVAL_POSIDX(thr, normalized_obj_idx);
14607 		tv_key = DUK_GET_TVAL_NEGIDX(thr, -nargs - 2);
14608 		DUK_ASSERT(tv_base >= thr->valstack_bottom && tv_base < thr->valstack_top);
14609 		DUK_ASSERT(tv_key >= thr->valstack_bottom && tv_key < thr->valstack_top);
14610 
14611 		duk_call_setup_propcall_error(thr, tv_base, tv_key);
14612 	}
14613 #endif
14614 
14615 	/* [... key arg1 ... argN func] */
14616 
14617 	duk_replace(thr, -nargs - 2);
14618 
14619 	/* [... func arg1 ... argN] */
14620 
14621 	duk_dup(thr, normalized_obj_idx);
14622 	duk_insert(thr, -nargs - 1);
14623 
14624 	/* [... func this arg1 ... argN] */
14625 }
14626 
duk_call(duk_hthread * thr,duk_idx_t nargs)14627 DUK_EXTERNAL void duk_call(duk_hthread *thr, duk_idx_t nargs) {
14628 	duk_small_uint_t call_flags;
14629 	duk_idx_t idx_func;
14630 
14631 	DUK_ASSERT_API_ENTRY(thr);
14632 
14633 	idx_func = duk__call_get_idx_func(thr, nargs, 1);
14634 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14635 
14636 	duk_insert_undefined(thr, idx_func + 1);
14637 
14638 	call_flags = 0;  /* not protected, respect reclimit, not constructor */
14639 	duk_handle_call_unprotected(thr, idx_func, call_flags);
14640 }
14641 
duk_call_method(duk_hthread * thr,duk_idx_t nargs)14642 DUK_EXTERNAL void duk_call_method(duk_hthread *thr, duk_idx_t nargs) {
14643 	duk_small_uint_t call_flags;
14644 	duk_idx_t idx_func;
14645 
14646 	DUK_ASSERT_API_ENTRY(thr);
14647 
14648 	idx_func = duk__call_get_idx_func(thr, nargs, 2);
14649 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14650 
14651 	call_flags = 0;  /* not protected, respect reclimit, not constructor */
14652 	duk_handle_call_unprotected(thr, idx_func, call_flags);
14653 }
14654 
duk_call_prop(duk_hthread * thr,duk_idx_t obj_idx,duk_idx_t nargs)14655 DUK_EXTERNAL void duk_call_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t nargs) {
14656 	/*
14657 	 *  XXX: if duk_handle_call() took values through indices, this could be
14658 	 *  made much more sensible.  However, duk_handle_call() needs to fudge
14659 	 *  the 'this' and 'func' values to handle bound functions, which is now
14660 	 *  done "in-place", so this is not a trivial change.
14661 	 */
14662 
14663 	DUK_ASSERT_API_ENTRY(thr);
14664 
14665 	obj_idx = duk_require_normalize_index(thr, obj_idx);  /* make absolute */
14666 	if (DUK_UNLIKELY(nargs < 0)) {
14667 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14668 		DUK_WO_NORETURN(return;);
14669 	}
14670 
14671 	duk__call_prop_prep_stack(thr, obj_idx, nargs);
14672 
14673 	duk_call_method(thr, nargs);
14674 }
14675 
duk__pcall_raw(duk_hthread * thr,void * udata)14676 DUK_LOCAL duk_ret_t duk__pcall_raw(duk_hthread *thr, void *udata) {
14677 	duk__pcall_args *args;
14678 	duk_idx_t idx_func;
14679 	duk_int_t ret;
14680 
14681 	DUK_CTX_ASSERT_VALID(thr);
14682 	DUK_ASSERT(udata != NULL);
14683 
14684 	args = (duk__pcall_args *) udata;
14685 	idx_func = duk__call_get_idx_func_unvalidated(thr, args->nargs, 1);
14686 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14687 
14688 	duk_insert_undefined(thr, idx_func + 1);
14689 
14690 	ret = duk_handle_call_unprotected(thr, idx_func, args->call_flags);
14691 	DUK_ASSERT(ret == 0);
14692 	DUK_UNREF(ret);
14693 
14694 	return 1;
14695 }
14696 
duk_pcall(duk_hthread * thr,duk_idx_t nargs)14697 DUK_EXTERNAL duk_int_t duk_pcall(duk_hthread *thr, duk_idx_t nargs) {
14698 	duk__pcall_args args;
14699 
14700 	DUK_ASSERT_API_ENTRY(thr);
14701 
14702 	args.nargs = nargs;
14703 	if (DUK_UNLIKELY(nargs < 0)) {
14704 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14705 		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
14706 	}
14707 	args.call_flags = 0;
14708 
14709 	return duk_safe_call(thr, duk__pcall_raw, (void *) &args /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/);
14710 }
14711 
duk__pcall_method_raw(duk_hthread * thr,void * udata)14712 DUK_LOCAL duk_ret_t duk__pcall_method_raw(duk_hthread *thr, void *udata) {
14713 	duk__pcall_method_args *args;
14714 	duk_idx_t idx_func;
14715 	duk_int_t ret;
14716 
14717 	DUK_CTX_ASSERT_VALID(thr);
14718 	DUK_ASSERT(udata != NULL);
14719 
14720 	args = (duk__pcall_method_args *) udata;
14721 
14722 	idx_func = duk__call_get_idx_func_unvalidated(thr, args->nargs, 2);
14723 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14724 
14725 	ret = duk_handle_call_unprotected(thr, idx_func, args->call_flags);
14726 	DUK_ASSERT(ret == 0);
14727 	DUK_UNREF(ret);
14728 
14729 	return 1;
14730 }
14731 
duk_pcall_method_flags(duk_hthread * thr,duk_idx_t nargs,duk_small_uint_t call_flags)14732 DUK_INTERNAL duk_int_t duk_pcall_method_flags(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags) {
14733 	duk__pcall_method_args args;
14734 
14735 	DUK_ASSERT_API_ENTRY(thr);
14736 
14737 	args.nargs = nargs;
14738 	if (DUK_UNLIKELY(nargs < 0)) {
14739 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14740 		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
14741 	}
14742 	args.call_flags = call_flags;
14743 
14744 	return duk_safe_call(thr, duk__pcall_method_raw, (void *) &args /*udata*/, nargs + 2 /*nargs*/, 1 /*nrets*/);
14745 }
14746 
duk_pcall_method(duk_hthread * thr,duk_idx_t nargs)14747 DUK_EXTERNAL duk_int_t duk_pcall_method(duk_hthread *thr, duk_idx_t nargs) {
14748 	DUK_ASSERT_API_ENTRY(thr);
14749 
14750 	return duk_pcall_method_flags(thr, nargs, 0);
14751 }
14752 
duk__pcall_prop_raw(duk_hthread * thr,void * udata)14753 DUK_LOCAL duk_ret_t duk__pcall_prop_raw(duk_hthread *thr, void *udata) {
14754 	duk__pcall_prop_args *args;
14755 	duk_idx_t obj_idx;
14756 	duk_int_t ret;
14757 
14758 	DUK_CTX_ASSERT_VALID(thr);
14759 	DUK_ASSERT(udata != NULL);
14760 
14761 	args = (duk__pcall_prop_args *) udata;
14762 
14763 	obj_idx = duk_require_normalize_index(thr, args->obj_idx);  /* make absolute */
14764 	duk__call_prop_prep_stack(thr, obj_idx, args->nargs);
14765 
14766 	ret = duk_handle_call_unprotected_nargs(thr, args->nargs, args->call_flags);
14767 	DUK_ASSERT(ret == 0);
14768 	DUK_UNREF(ret);
14769 	return 1;
14770 }
14771 
duk_pcall_prop(duk_hthread * thr,duk_idx_t obj_idx,duk_idx_t nargs)14772 DUK_EXTERNAL duk_int_t duk_pcall_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t nargs) {
14773 	duk__pcall_prop_args args;
14774 
14775 	DUK_ASSERT_API_ENTRY(thr);
14776 
14777 	args.obj_idx = obj_idx;
14778 	args.nargs = nargs;
14779 	if (DUK_UNLIKELY(nargs < 0)) {
14780 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14781 		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
14782 	}
14783 	args.call_flags = 0;
14784 
14785 	return duk_safe_call(thr, duk__pcall_prop_raw, (void *) &args /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/);
14786 }
14787 
duk_safe_call(duk_hthread * thr,duk_safe_call_function func,void * udata,duk_idx_t nargs,duk_idx_t nrets)14788 DUK_EXTERNAL duk_int_t duk_safe_call(duk_hthread *thr, duk_safe_call_function func, void *udata, duk_idx_t nargs, duk_idx_t nrets) {
14789 	duk_int_t rc;
14790 
14791 	DUK_ASSERT_API_ENTRY(thr);
14792 
14793 	/* nargs condition; fail if: top - bottom < nargs
14794 	 *                      <=>  top < bottom + nargs
14795 	 * nrets condition; fail if: end - (top - nargs) < nrets
14796 	 *                      <=>  end - top + nargs < nrets
14797 	 *                      <=>  end + nargs < top + nrets
14798 	 */
14799 	/* XXX: check for any reserve? */
14800 
14801 	if (DUK_UNLIKELY((nargs | nrets) < 0 ||  /* nargs < 0 || nrets < 0; OR sign bits */
14802 	                 thr->valstack_top < thr->valstack_bottom + nargs ||        /* nargs too large compared to top */
14803 	                 thr->valstack_end + nargs < thr->valstack_top + nrets)) {  /* nrets too large compared to reserve */
14804 		DUK_D(DUK_DPRINT("not enough stack reserve for safe call or invalid arguments: "
14805 		                 "nargs=%ld < 0 (?), nrets=%ld < 0 (?), top=%ld < bottom=%ld + nargs=%ld (?), "
14806 		                 "end=%ld + nargs=%ld < top=%ld + nrets=%ld (?)",
14807 		                  (long) nargs,
14808 		                  (long) nrets,
14809 		                  (long) (thr->valstack_top - thr->valstack),
14810 		                  (long) (thr->valstack_bottom - thr->valstack),
14811 		                  (long) nargs,
14812 		                  (long) (thr->valstack_end - thr->valstack),
14813 		                  (long) nargs,
14814 		                  (long) (thr->valstack_top - thr->valstack),
14815 		                  (long) nrets));
14816 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14817 		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
14818 	}
14819 
14820 	rc = duk_handle_safe_call(thr,           /* thread */
14821 	                          func,          /* func */
14822 	                          udata,         /* udata */
14823 	                          nargs,         /* num_stack_args */
14824 	                          nrets);        /* num_stack_res */
14825 
14826 	return rc;
14827 }
14828 
duk_new(duk_hthread * thr,duk_idx_t nargs)14829 DUK_EXTERNAL void duk_new(duk_hthread *thr, duk_idx_t nargs) {
14830 	duk_idx_t idx_func;
14831 
14832 	DUK_ASSERT_API_ENTRY(thr);
14833 
14834 	idx_func = duk__call_get_idx_func(thr, nargs, 1);
14835 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14836 
14837 	duk_push_object(thr);  /* default instance; internal proto updated by call handling */
14838 	duk_insert(thr, idx_func + 1);
14839 
14840 	duk_handle_call_unprotected(thr, idx_func, DUK_CALL_FLAG_CONSTRUCT);
14841 }
14842 
duk__pnew_helper(duk_hthread * thr,void * udata)14843 DUK_LOCAL duk_ret_t duk__pnew_helper(duk_hthread *thr, void *udata) {
14844 	duk_idx_t nargs;
14845 
14846 	DUK_ASSERT(udata != NULL);
14847 	nargs = *((duk_idx_t *) udata);
14848 
14849 	duk_new(thr, nargs);
14850 	return 1;
14851 }
14852 
duk_pnew(duk_hthread * thr,duk_idx_t nargs)14853 DUK_EXTERNAL duk_int_t duk_pnew(duk_hthread *thr, duk_idx_t nargs) {
14854 	duk_int_t rc;
14855 
14856 	DUK_ASSERT_API_ENTRY(thr);
14857 
14858 	/* For now, just use duk_safe_call() to wrap duk_new().  We can't
14859 	 * simply use a protected duk_handle_call() because pushing the
14860 	 * default instance might throw.
14861 	 */
14862 
14863 	if (DUK_UNLIKELY(nargs < 0)) {
14864 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14865 		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
14866 	}
14867 
14868 	rc = duk_safe_call(thr, duk__pnew_helper, (void *) &nargs /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/);
14869 	return rc;
14870 }
14871 
duk_is_constructor_call(duk_hthread * thr)14872 DUK_EXTERNAL duk_bool_t duk_is_constructor_call(duk_hthread *thr) {
14873 	duk_activation *act;
14874 
14875 	DUK_ASSERT_API_ENTRY(thr);
14876 
14877 	act = thr->callstack_curr;
14878 	if (act != NULL) {
14879 		return ((act->flags & DUK_ACT_FLAG_CONSTRUCT) != 0 ? 1 : 0);
14880 	}
14881 	return 0;
14882 }
14883 
duk_require_constructor_call(duk_hthread * thr)14884 DUK_EXTERNAL void duk_require_constructor_call(duk_hthread *thr) {
14885 	DUK_ASSERT_API_ENTRY(thr);
14886 
14887 	if (!duk_is_constructor_call(thr)) {
14888 		DUK_ERROR_TYPE(thr, DUK_STR_CONSTRUCT_ONLY);
14889 		DUK_WO_NORETURN(return;);
14890 	}
14891 }
14892 
duk_is_strict_call(duk_hthread * thr)14893 DUK_EXTERNAL duk_bool_t duk_is_strict_call(duk_hthread *thr) {
14894 	duk_activation *act;
14895 
14896 	/* For user code this could just return 1 (strict) always
14897 	 * because all Duktape/C functions are considered strict,
14898 	 * and strict is also the default when nothing is running.
14899 	 * However, Duktape may call this function internally when
14900 	 * the current activation is an ECMAScript function, so
14901 	 * this cannot be replaced by a 'return 1' without fixing
14902 	 * the internal call sites.
14903 	 */
14904 
14905 	DUK_ASSERT_API_ENTRY(thr);
14906 
14907 	act = thr->callstack_curr;
14908 	if (act != NULL) {
14909 		return ((act->flags & DUK_ACT_FLAG_STRICT) != 0 ? 1 : 0);
14910 	} else {
14911 		/* Strict by default. */
14912 		return 1;
14913 	}
14914 }
14915 
14916 /*
14917  *  Duktape/C function magic
14918  */
14919 
duk_get_current_magic(duk_hthread * thr)14920 DUK_EXTERNAL duk_int_t duk_get_current_magic(duk_hthread *thr) {
14921 	duk_activation *act;
14922 	duk_hobject *func;
14923 
14924 	DUK_ASSERT_API_ENTRY(thr);
14925 
14926 	act = thr->callstack_curr;
14927 	if (act) {
14928 		func = DUK_ACT_GET_FUNC(act);
14929 		if (!func) {
14930 			duk_tval *tv = &act->tv_func;
14931 			duk_small_uint_t lf_flags;
14932 			lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
14933 			return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
14934 		}
14935 		DUK_ASSERT(func != NULL);
14936 
14937 		if (DUK_HOBJECT_IS_NATFUNC(func)) {
14938 			duk_hnatfunc *nf = (duk_hnatfunc *) func;
14939 			return (duk_int_t) nf->magic;
14940 		}
14941 	}
14942 	return 0;
14943 }
14944 
duk_get_magic(duk_hthread * thr,duk_idx_t idx)14945 DUK_EXTERNAL duk_int_t duk_get_magic(duk_hthread *thr, duk_idx_t idx) {
14946 	duk_tval *tv;
14947 	duk_hobject *h;
14948 
14949 	DUK_ASSERT_API_ENTRY(thr);
14950 
14951 	tv = duk_require_tval(thr, idx);
14952 	if (DUK_TVAL_IS_OBJECT(tv)) {
14953 		h = DUK_TVAL_GET_OBJECT(tv);
14954 		DUK_ASSERT(h != NULL);
14955 		if (!DUK_HOBJECT_HAS_NATFUNC(h)) {
14956 			goto type_error;
14957 		}
14958 		return (duk_int_t) ((duk_hnatfunc *) h)->magic;
14959 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
14960 		duk_small_uint_t lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
14961 		return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
14962 	}
14963 
14964 	/* fall through */
14965  type_error:
14966 	DUK_ERROR_TYPE(thr, DUK_STR_UNEXPECTED_TYPE);
14967 	DUK_WO_NORETURN(return 0;);
14968 }
14969 
duk_set_magic(duk_hthread * thr,duk_idx_t idx,duk_int_t magic)14970 DUK_EXTERNAL void duk_set_magic(duk_hthread *thr, duk_idx_t idx, duk_int_t magic) {
14971 	duk_hnatfunc *nf;
14972 
14973 	DUK_ASSERT_API_ENTRY(thr);
14974 
14975 	nf = duk_require_hnatfunc(thr, idx);
14976 	DUK_ASSERT(nf != NULL);
14977 	nf->magic = (duk_int16_t) magic;
14978 }
14979 
14980 /*
14981  *  Misc helpers
14982  */
14983 
14984 /* Resolve a bound function on value stack top to a non-bound target
14985  * (leave other values as is).
14986  */
duk_resolve_nonbound_function(duk_hthread * thr)14987 DUK_INTERNAL void duk_resolve_nonbound_function(duk_hthread *thr) {
14988 	duk_tval *tv;
14989 
14990 	DUK_HTHREAD_ASSERT_VALID(thr);
14991 
14992 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
14993 	if (DUK_TVAL_IS_OBJECT(tv)) {
14994 		duk_hobject *h;
14995 
14996 		h = DUK_TVAL_GET_OBJECT(tv);
14997 		DUK_ASSERT(h != NULL);
14998 		if (DUK_HOBJECT_HAS_BOUNDFUNC(h)) {
14999 			duk_push_tval(thr, &((duk_hboundfunc *) (void *) h)->target);
15000 			duk_replace(thr, -2);
15001 #if 0
15002 			DUK_TVAL_SET_TVAL(tv, &((duk_hboundfunc *) h)->target);
15003 			DUK_TVAL_INCREF(thr, tv);
15004 			DUK_HOBJECT_DECREF_NORZ(thr, h);
15005 #endif
15006 			/* Rely on Function.prototype.bind() on never creating a bound
15007 			 * function whose target is not proper.  This is now safe
15008 			 * because the target is not even an internal property but a
15009 			 * struct member.
15010 			 */
15011 			DUK_ASSERT(duk_is_lightfunc(thr, -1) || duk_is_callable(thr, -1));
15012 		}
15013 	}
15014 
15015 	/* Lightfuncs cannot be bound but are always callable and
15016 	 * constructable.
15017 	 */
15018 }
15019 /*
15020  *  Encoding and decoding basic formats: hex, base64.
15021  *
15022  *  These are in-place operations which may allow an optimized implementation.
15023  *
15024  *  Base-64: https://tools.ietf.org/html/rfc4648#section-4
15025  */
15026 
15027 /* #include duk_internal.h -> already included */
15028 
15029 /*
15030  *  Misc helpers
15031  */
15032 
15033 /* Shared handling for encode/decode argument.  Fast path handling for
15034  * buffer and string values because they're the most common.  In particular,
15035  * avoid creating a temporary string or buffer when possible.  Return value
15036  * is guaranteed to be non-NULL, even for zero length input.
15037  */
duk__prep_codec_arg(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)15038 DUK_LOCAL const duk_uint8_t *duk__prep_codec_arg(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
15039 	const void *def_ptr = (const void *) out_len;  /* Any non-NULL pointer will do. */
15040 	const void *ptr;
15041 	duk_bool_t isbuffer;
15042 
15043 	DUK_ASSERT(out_len != NULL);
15044 	DUK_ASSERT(def_ptr != NULL);
15045 	DUK_ASSERT(duk_is_valid_index(thr, idx));  /* checked by caller */
15046 
15047 	ptr = (const void *) duk_get_buffer_data_raw(thr, idx, out_len, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/, &isbuffer);
15048 	if (isbuffer) {
15049 		DUK_ASSERT(ptr != NULL || *out_len == 0U);
15050 		if (DUK_UNLIKELY(ptr == NULL)) {
15051 			ptr = def_ptr;
15052 		}
15053 		DUK_ASSERT(ptr != NULL);
15054 	} else {
15055 		/* For strings a non-NULL pointer is always guaranteed because
15056 		 * at least a NUL will be present.
15057 		 */
15058 		ptr = (const void *) duk_to_lstring(thr, idx, out_len);
15059 		DUK_ASSERT(ptr != NULL);
15060 	}
15061 	DUK_ASSERT(ptr != NULL);
15062 	return (const duk_uint8_t *) ptr;
15063 }
15064 
15065 /*
15066  *  Base64
15067  */
15068 
15069 #if defined(DUK_USE_BASE64_SUPPORT)
15070 /* Bytes emitted for number of padding characters in range [0,4]. */
15071 DUK_LOCAL const duk_int8_t duk__base64_decode_nequal_step[5] = {
15072 	3,   /* #### -> 24 bits, emit 3 bytes */
15073 	2,   /* ###= -> 18 bits, emit 2 bytes */
15074 	1,   /* ##== -> 12 bits, emit 1 byte */
15075 	-1,  /* #=== -> 6 bits, error */
15076 	0,   /* ==== -> 0 bits, emit 0 bytes */
15077 };
15078 
15079 #if defined(DUK_USE_BASE64_FASTPATH)
15080 DUK_LOCAL const duk_uint8_t duk__base64_enctab_fast[64] = {
15081 	0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U, 0x48U, 0x49U, 0x4aU, 0x4bU, 0x4cU, 0x4dU, 0x4eU, 0x4fU, 0x50U,  /* A...P */
15082 	0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U, 0x58U, 0x59U, 0x5aU, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U,  /* Q...f */
15083 	0x67U, 0x68U, 0x69U, 0x6aU, 0x6bU, 0x6cU, 0x6dU, 0x6eU, 0x6fU, 0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U,  /* g...v */
15084 	0x77U, 0x78U, 0x79U, 0x7aU, 0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U, 0x38U, 0x39U, 0x2bU, 0x2fU   /* w.../ */
15085 };
15086 #endif  /* DUK_USE_BASE64_FASTPATH */
15087 
15088 #if defined(DUK_USE_BASE64_FASTPATH)
15089 /* Decode table for one byte of input:
15090  *   -1 = allowed whitespace
15091  *   -2 = padding
15092  *   -3 = error
15093  *    0...63 decoded bytes
15094  */
15095 DUK_LOCAL const duk_int8_t duk__base64_dectab_fast[256] = {
15096 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -1, -1, -3, -3, -1, -3, -3,  /* 0x00...0x0f */
15097 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0x10...0x1f */
15098 	-1, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, 62, -3, -3, -3, 63,  /* 0x20...0x2f */
15099 	52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -3, -3, -3, -2, -3, -3,  /* 0x30...0x3f */
15100 	-3,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,  /* 0x40...0x4f */
15101 	15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -3, -3, -3, -3, -3,  /* 0x50...0x5f */
15102 	-3, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,  /* 0x60...0x6f */
15103 	41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -3, -3, -3, -3, -3,  /* 0x70...0x7f */
15104 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0x80...0x8f */
15105 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0x90...0x9f */
15106 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xa0...0xaf */
15107 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xb0...0xbf */
15108 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xc0...0xcf */
15109 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xd0...0xdf */
15110 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xe0...0xef */
15111 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3   /* 0xf0...0xff */
15112 };
15113 #endif  /* DUK_USE_BASE64_FASTPATH */
15114 
15115 #if defined(DUK_USE_BASE64_FASTPATH)
duk__base64_encode_fast_3(const duk_uint8_t * src,duk_uint8_t * dst)15116 DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_3(const duk_uint8_t *src, duk_uint8_t *dst) {
15117 	duk_uint_t t;
15118 
15119 	t = (duk_uint_t) src[0];
15120 	t = (t << 8) + (duk_uint_t) src[1];
15121 	t = (t << 8) + (duk_uint_t) src[2];
15122 
15123 	dst[0] = duk__base64_enctab_fast[t >> 18];
15124 	dst[1] = duk__base64_enctab_fast[(t >> 12) & 0x3fU];
15125 	dst[2] = duk__base64_enctab_fast[(t >> 6) & 0x3fU];
15126 	dst[3] = duk__base64_enctab_fast[t & 0x3fU];
15127 
15128 #if 0
15129 	/* Tested: not faster on x64, most likely due to aliasing between
15130 	 * output and input index computation.
15131 	 */
15132 	/* aaaaaabb bbbbcccc ccdddddd */
15133 	dst[0] = duk__base64_enctab_fast[(src[0] >> 2) & 0x3fU];
15134 	dst[1] = duk__base64_enctab_fast[((src[0] << 4) & 0x30U) | ((src[1] >> 4) & 0x0fU)];
15135 	dst[2] = duk__base64_enctab_fast[((src[1] << 2) & 0x3fU) | ((src[2] >> 6) & 0x03U)];
15136 	dst[3] = duk__base64_enctab_fast[src[2] & 0x3fU];
15137 #endif
15138 }
15139 
duk__base64_encode_fast_2(const duk_uint8_t * src,duk_uint8_t * dst)15140 DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_2(const duk_uint8_t *src, duk_uint8_t *dst) {
15141 	duk_uint_t t;
15142 
15143 	t = (duk_uint_t) src[0];
15144 	t = (t << 8) + (duk_uint_t) src[1];
15145 	dst[0] = duk__base64_enctab_fast[t >> 10];           /* XXXXXX-- -------- */
15146 	dst[1] = duk__base64_enctab_fast[(t >> 4) & 0x3fU];  /* ------XX XXXX---- */
15147 	dst[2] = duk__base64_enctab_fast[(t << 2) & 0x3fU];  /* -------- ----XXXX */
15148 	dst[3] = DUK_ASC_EQUALS;
15149 }
15150 
duk__base64_encode_fast_1(const duk_uint8_t * src,duk_uint8_t * dst)15151 DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_1(const duk_uint8_t *src, duk_uint8_t *dst) {
15152 	duk_uint_t t;
15153 
15154 	t = (duk_uint_t) src[0];
15155 	dst[0] = duk__base64_enctab_fast[t >> 2];            /* XXXXXX-- */
15156 	dst[1] = duk__base64_enctab_fast[(t << 4) & 0x3fU];  /* ------XX */
15157 	dst[2] = DUK_ASC_EQUALS;
15158 	dst[3] = DUK_ASC_EQUALS;
15159 }
15160 
duk__base64_encode_helper(const duk_uint8_t * src,duk_size_t srclen,duk_uint8_t * dst)15161 DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
15162 	duk_size_t n;
15163 	const duk_uint8_t *p;
15164 	duk_uint8_t *q;
15165 
15166 	n = srclen;
15167 	p = src;
15168 	q = dst;
15169 
15170 	if (n >= 16U) {
15171 		/* Fast path, unrolled by 4, allows interleaving.  Process
15172 		 * 12-byte input chunks which encode to 16-char output chunks.
15173 		 * Only enter when at least one block is emitted (avoids div+mul
15174 		 * for short inputs too).
15175 		 */
15176 		const duk_uint8_t *p_end_fast;
15177 
15178 		p_end_fast = p + ((n / 12U) * 12U);
15179 		DUK_ASSERT(p_end_fast >= p + 12);
15180 		do {
15181 			duk__base64_encode_fast_3(p, q);
15182 			duk__base64_encode_fast_3(p + 3, q + 4);
15183 			duk__base64_encode_fast_3(p + 6, q + 8);
15184 			duk__base64_encode_fast_3(p + 9, q + 12);
15185 			p += 12;
15186 			q += 16;
15187 		} while (DUK_LIKELY(p != p_end_fast));
15188 
15189 		DUK_ASSERT(src + srclen >= p);
15190 		n = (duk_size_t) (src + srclen - p);
15191 		DUK_ASSERT(n < 12U);
15192 	}
15193 
15194 	/* Remainder. */
15195 	while (n >= 3U) {
15196 		duk__base64_encode_fast_3(p, q);
15197 		p += 3;
15198 		q += 4;
15199 		n -= 3U;
15200 	}
15201 	DUK_ASSERT(n == 0U || n == 1U || n == 2U);
15202 	if (n == 1U) {
15203 		duk__base64_encode_fast_1(p, q);
15204 #if 0  /* Unnecessary. */
15205 		p += 1;
15206 		q += 4;
15207 		n -= 1U;
15208 #endif
15209 	} else if (n == 2U) {
15210 		duk__base64_encode_fast_2(p, q);
15211 #if 0  /* Unnecessary. */
15212 		p += 2;
15213 		q += 4;
15214 		n -= 2U;
15215 #endif
15216 	} else {
15217 		DUK_ASSERT(n == 0U);  /* nothing to do */
15218 		;
15219 	}
15220 }
15221 #else  /* DUK_USE_BASE64_FASTPATH */
duk__base64_encode_helper(const duk_uint8_t * src,duk_size_t srclen,duk_uint8_t * dst)15222 DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
15223 	duk_small_uint_t i, npad;
15224 	duk_uint_t t, x, y;
15225 	const duk_uint8_t *p;
15226 	const duk_uint8_t *p_end;
15227 	duk_uint8_t *q;
15228 
15229 	p = src;
15230 	p_end = src + srclen;
15231 	q = dst;
15232 	npad = 0U;
15233 
15234 	while (p < p_end) {
15235 		/* Read 3 bytes into 't', padded by zero. */
15236 		t = 0;
15237 		for (i = 0; i < 3; i++) {
15238 			t = t << 8;
15239 			if (p < p_end) {
15240 				t += (duk_uint_t) (*p++);
15241 			} else {
15242 				/* This only happens on the last loop and we're
15243 				 * guaranteed to exit on the next loop.
15244 				 */
15245 				npad++;
15246 			}
15247 		}
15248 		DUK_ASSERT(npad <= 2U);
15249 
15250 		/* Emit 4 encoded characters.  If npad > 0, some of the
15251 		 * chars will be incorrect (zero bits) but we fix up the
15252 		 * padding after the loop.  A straightforward 64-byte
15253 		 * lookup would be faster and cleaner, but this is shorter.
15254 		 */
15255 		for (i = 0; i < 4; i++) {
15256 			x = ((t >> 18) & 0x3fU);
15257 			t = t << 6;
15258 
15259 			if (x <= 51U) {
15260 				if (x <= 25) {
15261 					y = x + DUK_ASC_UC_A;
15262 				} else {
15263 					y = x - 26 + DUK_ASC_LC_A;
15264 				}
15265 			} else {
15266 				if (x <= 61U) {
15267 					y = x - 52 + DUK_ASC_0;
15268 				} else if (x == 62) {
15269 					y = DUK_ASC_PLUS;
15270 				} else {
15271 					DUK_ASSERT(x == 63);
15272 					y = DUK_ASC_SLASH;
15273 				}
15274 			}
15275 
15276 			*q++ = (duk_uint8_t) y;
15277 		}
15278 	}
15279 
15280 	/* Handle padding by rewriting 0-2 bogus characters at the end.
15281 	 *
15282 	 *  Missing bytes    npad     base64 example
15283 	 *    0               0         ####
15284 	 *    1               1         ###=
15285 	 *    2               2         ##==
15286 	 */
15287 	DUK_ASSERT(npad <= 2U);
15288 	while (npad > 0U) {
15289 		*(q - npad) = DUK_ASC_EQUALS;
15290 		npad--;
15291 	}
15292 }
15293 #endif  /* DUK_USE_BASE64_FASTPATH */
15294 
15295 #if defined(DUK_USE_BASE64_FASTPATH)
duk__base64_decode_helper(const duk_uint8_t * src,duk_size_t srclen,duk_uint8_t * dst,duk_uint8_t ** out_dst_final)15296 DUK_LOCAL duk_bool_t duk__base64_decode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst, duk_uint8_t **out_dst_final) {
15297 	duk_int_t x;
15298 	duk_uint_t t;
15299 	duk_small_uint_t n_equal;
15300 	duk_int8_t step;
15301 	const duk_uint8_t *p;
15302 	const duk_uint8_t *p_end;
15303 	const duk_uint8_t *p_end_safe;
15304 	duk_uint8_t *q;
15305 
15306 	DUK_ASSERT(src != NULL);  /* Required by pointer arithmetic below, which fails for NULL. */
15307 
15308 	p = src;
15309 	p_end = src + srclen;
15310 	p_end_safe = p_end - 8;  /* If 'src <= src_end_safe', safe to read 8 bytes. */
15311 	q = dst;
15312 
15313 	/* Alternate between a fast path which processes clean groups with no
15314 	 * padding or whitespace, and a slow path which processes one arbitrary
15315 	 * group and then re-enters the fast path.  This handles e.g. base64
15316 	 * with newlines reasonably well because the majority of a line is in
15317 	 * the fast path.
15318 	 */
15319 	for (;;) {
15320 		/* Fast path, on each loop handle two 4-char input groups.
15321 		 * If both are clean, emit 6 bytes and continue.  If first
15322 		 * is clean, emit 3 bytes and drop out; otherwise emit
15323 		 * nothing and drop out.  This approach could be extended to
15324 		 * more groups per loop, but for inputs with e.g. periodic
15325 		 * newlines (which are common) it might not be an improvement.
15326 		 */
15327 		while (DUK_LIKELY(p <= p_end_safe)) {
15328 			duk_int_t t1, t2;
15329 
15330 			/* The lookup byte is intentionally sign extended to
15331 			 * (at least) 32 bits and then ORed.  This ensures
15332 			 * that is at least 1 byte is negative, the highest
15333 			 * bit of the accumulator will be set at the end and
15334 			 * we don't need to check every byte.
15335 			 *
15336 			 * Read all input bytes first before writing output
15337 			 * bytes to minimize aliasing.
15338 			 */
15339 			DUK_DDD(DUK_DDDPRINT("fast loop: p=%p, p_end_safe=%p, p_end=%p",
15340 			                     (const void *) p, (const void *) p_end_safe, (const void *) p_end));
15341 
15342 			t1 = (duk_int_t) duk__base64_dectab_fast[p[0]];
15343 			t1 = (duk_int_t) ((duk_uint_t) t1 << 6) | (duk_int_t) duk__base64_dectab_fast[p[1]];
15344 			t1 = (duk_int_t) ((duk_uint_t) t1 << 6) | (duk_int_t) duk__base64_dectab_fast[p[2]];
15345 			t1 = (duk_int_t) ((duk_uint_t) t1 << 6) | (duk_int_t) duk__base64_dectab_fast[p[3]];
15346 
15347 			t2 = (duk_int_t) duk__base64_dectab_fast[p[4]];
15348 			t2 = (duk_int_t) ((duk_uint_t) t2 << 6) | (duk_int_t) duk__base64_dectab_fast[p[5]];
15349 			t2 = (duk_int_t) ((duk_uint_t) t2 << 6) | (duk_int_t) duk__base64_dectab_fast[p[6]];
15350 			t2 = (duk_int_t) ((duk_uint_t) t2 << 6) | (duk_int_t) duk__base64_dectab_fast[p[7]];
15351 
15352 			q[0] = (duk_uint8_t) (((duk_uint_t) t1 >> 16) & 0xffU);
15353 			q[1] = (duk_uint8_t) (((duk_uint_t) t1 >> 8) & 0xffU);
15354 			q[2] = (duk_uint8_t) ((duk_uint_t) t1 & 0xffU);
15355 
15356 			q[3] = (duk_uint8_t) (((duk_uint_t) t2 >> 16) & 0xffU);
15357 			q[4] = (duk_uint8_t) (((duk_uint_t) t2 >> 8) & 0xffU);
15358 			q[5] = (duk_uint8_t) ((duk_uint_t) t2 & 0xffU);
15359 
15360 			/* Optimistic check using one branch. */
15361 			if (DUK_LIKELY((t1 | t2) >= 0)) {
15362 				p += 8;
15363 				q += 6;
15364 			} else if (t1 >= 0) {
15365 				DUK_DDD(DUK_DDDPRINT("fast loop first group was clean, second was not, process one slow path group"));
15366 				DUK_ASSERT(t2 < 0);
15367 				p += 4;
15368 				q += 3;
15369 				break;
15370 			} else {
15371 				DUK_DDD(DUK_DDDPRINT("fast loop first group was not clean, second does not matter, process one slow path group"));
15372 				DUK_ASSERT(t1 < 0);
15373 				break;
15374 			}
15375 		}  /* fast path */
15376 
15377 		/* Slow path step 1: try to scan a 4-character encoded group,
15378 		 * end-of-input, or start-of-padding.  We exit with:
15379 		 *   1. n_chars == 4: full group, no padding, no end-of-input.
15380 		 *   2. n_chars < 4: partial group (may also be 0), encountered
15381 		 *      padding or end of input.
15382 		 *
15383 		 * The accumulator is initialized to 1; this allows us to detect
15384 		 * a full group by comparing >= 0x1000000 without an extra
15385 		 * counter variable.
15386 		 */
15387 		t = 1UL;
15388 		for (;;) {
15389 			DUK_DDD(DUK_DDDPRINT("slow loop: p=%p, p_end=%p, t=%lu",
15390 			                     (const void *) p, (const void *) p_end, (unsigned long) t));
15391 
15392 			if (DUK_LIKELY(p < p_end)) {
15393 				x = duk__base64_dectab_fast[*p++];
15394 				if (DUK_LIKELY(x >= 0)) {
15395 					DUK_ASSERT(x >= 0 && x <= 63);
15396 					t = (t << 6) + (duk_uint_t) x;
15397 					if (t >= 0x1000000UL) {
15398 						break;
15399 					}
15400 				} else if (x == -1) {
15401 					continue;  /* allowed ascii whitespace */
15402 				} else if (x == -2) {
15403 					p--;
15404 					break;  /* start of padding */
15405 				} else {
15406 					DUK_ASSERT(x == -3);
15407 					goto decode_error;
15408 				}
15409 			} else {
15410 				break;  /* end of input */
15411 			}
15412 		}  /* slow path step 1 */
15413 
15414 		/* Complete the padding by simulating pad characters,
15415 		 * regardless of actual input padding chars.
15416 		 */
15417 		n_equal = 0;
15418 		while (t < 0x1000000UL) {
15419 			t = (t << 6) + 0U;
15420 			n_equal++;
15421 		}
15422 
15423 		/* Slow path step 2: deal with full/partial group, padding,
15424 		 * etc.  Note that for num chars in [0,3] we intentionally emit
15425 		 * 3 bytes but don't step forward that much, buffer space is
15426 		 * guaranteed in setup.
15427 		 *
15428 		 *  num chars:
15429 		 *   0      ####   no output (= step 0)
15430 		 *   1      #===   reject, 6 bits of data
15431 		 *   2      ##==   12 bits of data, output 1 byte (= step 1)
15432 		 *   3      ###=   18 bits of data, output 2 bytes (= step 2)
15433 		 *   4      ####   24 bits of data, output 3 bytes (= step 3)
15434 		 */
15435 		q[0] = (duk_uint8_t) ((t >> 16) & 0xffU);
15436 		q[1] = (duk_uint8_t) ((t >> 8) & 0xffU);
15437 		q[2] = (duk_uint8_t) (t & 0xffU);
15438 
15439 		DUK_ASSERT(n_equal <= 4);
15440 		step = duk__base64_decode_nequal_step[n_equal];
15441 		if (DUK_UNLIKELY(step < 0)) {
15442 			goto decode_error;
15443 		}
15444 		q += step;
15445 
15446 		/* Slow path step 3: read and ignore padding and whitespace
15447 		 * until (a) next non-padding and non-whitespace character
15448 		 * after which we resume the fast path, or (b) end of input.
15449 		 * This allows us to accept missing, partial, full, and extra
15450 		 * padding cases uniformly.  We also support concatenated
15451 		 * base-64 documents because we resume scanning afterwards.
15452 		 *
15453 		 * Note that to support concatenated documents well, the '='
15454 		 * padding found inside the input must also allow for 'extra'
15455 		 * padding.  For example, 'Zm===' decodes to 'f' and has one
15456 		 * extra padding char.  So, 'Zm===Zm' should decode 'ff', even
15457 		 * though the standard break-up would be 'Zm==' + '=Zm' which
15458 		 * doesn't make sense.
15459 		 *
15460 		 * We also accept prepended padding like '==Zm9', because it
15461 		 * is equivalent to an empty document with extra padding ('==')
15462 		 * followed by a valid document.
15463 		 */
15464 
15465 		for (;;) {
15466 			if (DUK_UNLIKELY(p >= p_end)) {
15467 				goto done;
15468 			}
15469 			x = duk__base64_dectab_fast[*p++];
15470 			if (x == -1 || x == -2) {
15471 				;  /* padding or whitespace, keep eating */
15472 			} else {
15473 				p--;
15474 				break;  /* backtrack and go back to fast path, even for -1 */
15475 			}
15476 		}  /* slow path step 3 */
15477 	}  /* outer fast+slow path loop */
15478 
15479  done:
15480 	DUK_DDD(DUK_DDDPRINT("done; p=%p, p_end=%p",
15481 	                     (const void *) p, (const void *) p_end));
15482 
15483 	DUK_ASSERT(p == p_end);
15484 
15485 	*out_dst_final = q;
15486 	return 1;
15487 
15488  decode_error:
15489 	return 0;
15490 }
15491 #else  /* DUK_USE_BASE64_FASTPATH */
duk__base64_decode_helper(const duk_uint8_t * src,duk_size_t srclen,duk_uint8_t * dst,duk_uint8_t ** out_dst_final)15492 DUK_LOCAL duk_bool_t duk__base64_decode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst, duk_uint8_t **out_dst_final) {
15493 	duk_uint_t t, x;
15494 	duk_int_t y;
15495 	duk_int8_t step;
15496 	const duk_uint8_t *p;
15497 	const duk_uint8_t *p_end;
15498 	duk_uint8_t *q;
15499 	/* 0x09, 0x0a, or 0x0d */
15500 	duk_uint32_t mask_white = (1U << 9) | (1U << 10) | (1U << 13);
15501 
15502 	/* 't' tracks progress of the decoded group:
15503 	 *
15504 	 *  t == 1             no valid chars yet
15505 	 *  t >= 0x40          1x6 = 6 bits shifted in
15506 	 *  t >= 0x1000        2x6 = 12 bits shifted in
15507 	 *  t >= 0x40000       3x6 = 18 bits shifted in
15508 	 *  t >= 0x1000000     4x6 = 24 bits shifted in
15509 	 *
15510 	 * By initializing t=1 there's no need for a separate counter for
15511 	 * the number of characters found so far.
15512 	 */
15513 	p = src;
15514 	p_end = src + srclen;
15515 	q = dst;
15516 	t = 1UL;
15517 
15518 	for (;;) {
15519 		duk_small_uint_t n_equal;
15520 
15521 		DUK_ASSERT(t >= 1U);
15522 		if (p >= p_end) {
15523 			/* End of input: if input exists, treat like
15524 			 * start of padding, finish the block, then
15525 			 * re-enter here to see we're done.
15526 			 */
15527 			if (t == 1U) {
15528 				break;
15529 			} else {
15530 				goto simulate_padding;
15531 			}
15532 		}
15533 
15534 		x = *p++;
15535 
15536 		if (x >= 0x41U) {
15537 			/* Valid: a-z and A-Z. */
15538 			DUK_ASSERT(x >= 0x41U && x <= 0xffU);
15539 			if (x >= 0x61U && x <= 0x7aU) {
15540 				y = (duk_int_t) x - 0x61 + 26;
15541 			} else if (x <= 0x5aU) {
15542 				y = (duk_int_t) x - 0x41;
15543 			} else {
15544 				goto decode_error;
15545 			}
15546 		} else if (x >= 0x30U) {
15547 			/* Valid: 0-9 and =. */
15548 			DUK_ASSERT(x >= 0x30U && x <= 0x40U);
15549 			if (x <= 0x39U) {
15550 				y = (duk_int_t) x - 0x30 + 52;
15551 			} else if (x == 0x3dU) {
15552 				/* Skip padding and whitespace unless we're in the
15553 				 * middle of a block.  Otherwise complete group by
15554 				 * simulating shifting in the correct padding.
15555 				 */
15556 				if (t == 1U) {
15557 					continue;
15558 				}
15559 				goto simulate_padding;
15560 			} else {
15561 				goto decode_error;
15562 			}
15563 		} else if (x >= 0x20U) {
15564 			/* Valid: +, /, and 0x20 whitespace. */
15565 			DUK_ASSERT(x >= 0x20U && x <= 0x2fU);
15566 			if (x == 0x2bU) {
15567 				y = 62;
15568 			} else if (x == 0x2fU) {
15569 				y = 63;
15570 			} else if (x == 0x20U) {
15571 				continue;
15572 			} else {
15573 				goto decode_error;
15574 			}
15575 		} else {
15576 			/* Valid: whitespace. */
15577 			duk_uint32_t m;
15578 			DUK_ASSERT(x < 0x20U);  /* 0x00 to 0x1f */
15579 			m = (1U << x);
15580 			if (mask_white & m) {
15581 				/* Allow basic ASCII whitespace. */
15582 				continue;
15583 			} else {
15584 				goto decode_error;
15585 			}
15586 		}
15587 
15588 		DUK_ASSERT(y >= 0 && y <= 63);
15589 		t = (t << 6) + (duk_uint_t) y;
15590 		if (t < 0x1000000UL) {
15591 			continue;
15592 		}
15593 		/* fall through; no padding will be added */
15594 
15595 	 simulate_padding:
15596 		n_equal = 0;
15597 		while (t < 0x1000000UL) {
15598 			t = (t << 6) + 0U;
15599 			n_equal++;
15600 		}
15601 
15602 		/* Output 3 bytes from 't' and advance as needed. */
15603 		q[0] = (duk_uint8_t) ((t >> 16) & 0xffU);
15604 		q[1] = (duk_uint8_t) ((t >> 8) & 0xffU);
15605 		q[2] = (duk_uint8_t) (t & 0xffU);
15606 
15607 		DUK_ASSERT(n_equal <= 4U);
15608 		step = duk__base64_decode_nequal_step[n_equal];
15609 		if (step < 0) {
15610 			goto decode_error;
15611 		}
15612 		q += step;
15613 
15614 		/* Re-enter loop.  The actual padding characters are skipped
15615 		 * by the main loop.  This handles cases like missing, partial,
15616 		 * full, and extra padding, and allows parsing of concatenated
15617 		 * documents (with extra padding) like: Zm===Zm.  Also extra
15618 		 * prepended padding is accepted: ===Zm9v.
15619 		 */
15620 		t = 1U;
15621 	}
15622 	DUK_ASSERT(t == 1UL);
15623 
15624 	*out_dst_final = q;
15625 	return 1;
15626 
15627  decode_error:
15628 	return 0;
15629 }
15630 #endif  /* DUK_USE_BASE64_FASTPATH */
15631 
duk_base64_encode(duk_hthread * thr,duk_idx_t idx)15632 DUK_EXTERNAL const char *duk_base64_encode(duk_hthread *thr, duk_idx_t idx) {
15633 	const duk_uint8_t *src;
15634 	duk_size_t srclen;
15635 	duk_size_t dstlen;
15636 	duk_uint8_t *dst;
15637 	const char *ret;
15638 
15639 	DUK_ASSERT_API_ENTRY(thr);
15640 
15641 	idx = duk_require_normalize_index(thr, idx);
15642 	src = duk__prep_codec_arg(thr, idx, &srclen);
15643 	DUK_ASSERT(src != NULL);
15644 
15645 	/* Compute exact output length.  Computation must not wrap; this
15646 	 * limit works for 32-bit size_t:
15647 	 * >>> srclen = 3221225469
15648 	 * >>> '%x' % ((srclen + 2) / 3 * 4)
15649 	 * 'fffffffc'
15650 	 */
15651 	if (srclen > 3221225469UL) {
15652 		goto type_error;
15653 	}
15654 	dstlen = (srclen + 2U) / 3U * 4U;
15655 	dst = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, dstlen);
15656 
15657 	duk__base64_encode_helper((const duk_uint8_t *) src, srclen, dst);
15658 
15659 	ret = duk_buffer_to_string(thr, -1);  /* Safe, result is ASCII. */
15660 	duk_replace(thr, idx);
15661 	return ret;
15662 
15663  type_error:
15664 	DUK_ERROR_TYPE(thr, DUK_STR_BASE64_ENCODE_FAILED);
15665 	DUK_WO_NORETURN(return NULL;);
15666 }
15667 
duk_base64_decode(duk_hthread * thr,duk_idx_t idx)15668 DUK_EXTERNAL void duk_base64_decode(duk_hthread *thr, duk_idx_t idx) {
15669 	const duk_uint8_t *src;
15670 	duk_size_t srclen;
15671 	duk_size_t dstlen;
15672 	duk_uint8_t *dst;
15673 	duk_uint8_t *dst_final;
15674 
15675 	DUK_ASSERT_API_ENTRY(thr);
15676 
15677 	idx = duk_require_normalize_index(thr, idx);
15678 	src = duk__prep_codec_arg(thr, idx, &srclen);
15679 	DUK_ASSERT(src != NULL);
15680 
15681 	/* Round up and add safety margin.  Avoid addition before division to
15682 	 * avoid possibility of wrapping.  Margin includes +3 for rounding up,
15683 	 * and +3 for one extra group: the decoder may emit and then backtrack
15684 	 * a full group (3 bytes) from zero-sized input for technical reasons.
15685 	 * Similarly, 'xx' may ecause 1+3 = bytes to be emitted and then
15686 	 * backtracked.
15687 	 */
15688 	dstlen = (srclen / 4) * 3 + 6;  /* upper limit, assuming no whitespace etc */
15689 	dst = (duk_uint8_t *) duk_push_dynamic_buffer(thr, dstlen);
15690 	/* Note: for dstlen=0, dst may be NULL */
15691 
15692 	if (!duk__base64_decode_helper((const duk_uint8_t *) src, srclen, dst, &dst_final)) {
15693 		goto type_error;
15694 	}
15695 
15696 	/* XXX: convert to fixed buffer? */
15697 	(void) duk_resize_buffer(thr, -1, (duk_size_t) (dst_final - dst));
15698 	duk_replace(thr, idx);
15699 	return;
15700 
15701  type_error:
15702 	DUK_ERROR_TYPE(thr, DUK_STR_BASE64_DECODE_FAILED);
15703 	DUK_WO_NORETURN(return;);
15704 }
15705 #else  /* DUK_USE_BASE64_SUPPORT */
duk_base64_encode(duk_hthread * thr,duk_idx_t idx)15706 DUK_EXTERNAL const char *duk_base64_encode(duk_hthread *thr, duk_idx_t idx) {
15707 	DUK_UNREF(idx);
15708 	DUK_ERROR_UNSUPPORTED(thr);
15709 	DUK_WO_NORETURN(return NULL;);
15710 }
15711 
duk_base64_decode(duk_hthread * thr,duk_idx_t idx)15712 DUK_EXTERNAL void duk_base64_decode(duk_hthread *thr, duk_idx_t idx) {
15713 	DUK_UNREF(idx);
15714 	DUK_ERROR_UNSUPPORTED(thr);
15715 	DUK_WO_NORETURN(return;);
15716 }
15717 #endif  /* DUK_USE_BASE64_SUPPORT */
15718 
15719 /*
15720  *  Hex
15721  */
15722 
15723 #if defined(DUK_USE_HEX_SUPPORT)
duk_hex_encode(duk_hthread * thr,duk_idx_t idx)15724 DUK_EXTERNAL const char *duk_hex_encode(duk_hthread *thr, duk_idx_t idx) {
15725 	const duk_uint8_t *inp;
15726 	duk_size_t len;
15727 	duk_size_t i;
15728 	duk_uint8_t *buf;
15729 	const char *ret;
15730 #if defined(DUK_USE_HEX_FASTPATH)
15731 	duk_size_t len_safe;
15732 	duk_uint16_t *p16;
15733 #endif
15734 
15735 	DUK_ASSERT_API_ENTRY(thr);
15736 
15737 	idx = duk_require_normalize_index(thr, idx);
15738 	inp = duk__prep_codec_arg(thr, idx, &len);
15739 	DUK_ASSERT(inp != NULL);
15740 
15741 	/* Fixed buffer, no zeroing because we'll fill all the data. */
15742 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len * 2);
15743 	DUK_ASSERT(buf != NULL);
15744 
15745 #if defined(DUK_USE_HEX_FASTPATH)
15746 	DUK_ASSERT((((duk_size_t) buf) & 0x01U) == 0);   /* pointer is aligned, guaranteed for fixed buffer */
15747 	p16 = (duk_uint16_t *) (void *) buf;
15748 	len_safe = len & ~0x03U;
15749 	for (i = 0; i < len_safe; i += 4) {
15750 		p16[0] = duk_hex_enctab[inp[i]];
15751 		p16[1] = duk_hex_enctab[inp[i + 1]];
15752 		p16[2] = duk_hex_enctab[inp[i + 2]];
15753 		p16[3] = duk_hex_enctab[inp[i + 3]];
15754 		p16 += 4;
15755 	}
15756 	for (; i < len; i++) {
15757 		*p16++ = duk_hex_enctab[inp[i]];
15758 	}
15759 #else  /* DUK_USE_HEX_FASTPATH */
15760 	for (i = 0; i < len; i++) {
15761 		duk_small_uint_t t;
15762 		t = (duk_small_uint_t) inp[i];
15763 		buf[i*2 + 0] = duk_lc_digits[t >> 4];
15764 		buf[i*2 + 1] = duk_lc_digits[t & 0x0f];
15765 	}
15766 #endif  /* DUK_USE_HEX_FASTPATH */
15767 
15768 	/* XXX: Using a string return value forces a string intern which is
15769 	 * not always necessary.  As a rough performance measure, hex encode
15770 	 * time for tests/perf/test-hex-encode.js dropped from ~35s to ~15s
15771 	 * without string coercion.  Change to returning a buffer and let the
15772 	 * caller coerce to string if necessary?
15773 	 */
15774 
15775 	ret = duk_buffer_to_string(thr, -1);  /* Safe, result is ASCII. */
15776 	duk_replace(thr, idx);
15777 	return ret;
15778 }
15779 
duk_hex_decode(duk_hthread * thr,duk_idx_t idx)15780 DUK_EXTERNAL void duk_hex_decode(duk_hthread *thr, duk_idx_t idx) {
15781 	const duk_uint8_t *inp;
15782 	duk_size_t len;
15783 	duk_size_t i;
15784 	duk_int_t t;
15785 	duk_uint8_t *buf;
15786 #if defined(DUK_USE_HEX_FASTPATH)
15787 	duk_int_t chk;
15788 	duk_uint8_t *p;
15789 	duk_size_t len_safe;
15790 #endif
15791 
15792 	DUK_ASSERT_API_ENTRY(thr);
15793 
15794 	idx = duk_require_normalize_index(thr, idx);
15795 	inp = duk__prep_codec_arg(thr, idx, &len);
15796 	DUK_ASSERT(inp != NULL);
15797 
15798 	if (len & 0x01) {
15799 		goto type_error;
15800 	}
15801 
15802 	/* Fixed buffer, no zeroing because we'll fill all the data. */
15803 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len / 2);
15804 	DUK_ASSERT(buf != NULL);
15805 
15806 #if defined(DUK_USE_HEX_FASTPATH)
15807 	p = buf;
15808 	len_safe = len & ~0x07U;
15809 	for (i = 0; i < len_safe; i += 8) {
15810 		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i]]) |
15811 		    ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
15812 		chk = t;
15813 		p[0] = (duk_uint8_t) t;
15814 		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 2]]) |
15815 		    ((duk_int_t) duk_hex_dectab[inp[i + 3]]);
15816 		chk |= t;
15817 		p[1] = (duk_uint8_t) t;
15818 		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 4]]) |
15819 		    ((duk_int_t) duk_hex_dectab[inp[i + 5]]);
15820 		chk |= t;
15821 		p[2] = (duk_uint8_t) t;
15822 		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 6]]) |
15823 		    ((duk_int_t) duk_hex_dectab[inp[i + 7]]);
15824 		chk |= t;
15825 		p[3] = (duk_uint8_t) t;
15826 		p += 4;
15827 
15828 		/* Check if any lookup above had a negative result. */
15829 		if (DUK_UNLIKELY(chk < 0)) {
15830 			goto type_error;
15831 		}
15832 	}
15833 	for (; i < len; i += 2) {
15834 		/* First cast to duk_int_t to sign extend, second cast to
15835 		 * duk_uint_t to avoid signed left shift, and final cast to
15836 		 * duk_int_t result type.
15837 		 */
15838 		t = (duk_int_t) ((((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i]]) << 4U) |
15839 		                 ((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i + 1]]));
15840 		if (DUK_UNLIKELY(t < 0)) {
15841 			goto type_error;
15842 		}
15843 		*p++ = (duk_uint8_t) t;
15844 	}
15845 #else  /* DUK_USE_HEX_FASTPATH */
15846 	for (i = 0; i < len; i += 2) {
15847 		/* For invalid characters the value -1 gets extended to
15848 		 * at least 16 bits.  If either nybble is invalid, the
15849 		 * resulting 't' will be < 0.
15850 		 */
15851 		t = (duk_int_t) ((((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i]]) << 4U) |
15852 		                 ((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i + 1]]));
15853 		if (DUK_UNLIKELY(t < 0)) {
15854 			goto type_error;
15855 		}
15856 		buf[i >> 1] = (duk_uint8_t) t;
15857 	}
15858 #endif  /* DUK_USE_HEX_FASTPATH */
15859 
15860 	duk_replace(thr, idx);
15861 	return;
15862 
15863  type_error:
15864 	DUK_ERROR_TYPE(thr, DUK_STR_HEX_DECODE_FAILED);
15865 	DUK_WO_NORETURN(return;);
15866 }
15867 #else  /* DUK_USE_HEX_SUPPORT */
duk_hex_encode(duk_hthread * thr,duk_idx_t idx)15868 DUK_EXTERNAL const char *duk_hex_encode(duk_hthread *thr, duk_idx_t idx) {
15869 	DUK_UNREF(idx);
15870 	DUK_ERROR_UNSUPPORTED(thr);
15871 	DUK_WO_NORETURN(return NULL;);
15872 }
duk_hex_decode(duk_hthread * thr,duk_idx_t idx)15873 DUK_EXTERNAL void duk_hex_decode(duk_hthread *thr, duk_idx_t idx) {
15874 	DUK_UNREF(idx);
15875 	DUK_ERROR_UNSUPPORTED(thr);
15876 	DUK_WO_NORETURN(return;);
15877 }
15878 #endif  /* DUK_USE_HEX_SUPPORT */
15879 
15880 /*
15881  *  JSON
15882  */
15883 
15884 #if defined(DUK_USE_JSON_SUPPORT)
duk_json_encode(duk_hthread * thr,duk_idx_t idx)15885 DUK_EXTERNAL const char *duk_json_encode(duk_hthread *thr, duk_idx_t idx) {
15886 #if defined(DUK_USE_ASSERTIONS)
15887 	duk_idx_t top_at_entry;
15888 #endif
15889 	const char *ret;
15890 
15891 	DUK_ASSERT_API_ENTRY(thr);
15892 #if defined(DUK_USE_ASSERTIONS)
15893 	top_at_entry = duk_get_top(thr);
15894 #endif
15895 
15896 	idx = duk_require_normalize_index(thr, idx);
15897 	duk_bi_json_stringify_helper(thr,
15898 	                             idx /*idx_value*/,
15899 	                             DUK_INVALID_INDEX /*idx_replacer*/,
15900 	                             DUK_INVALID_INDEX /*idx_space*/,
15901 	                             0 /*flags*/);
15902 	DUK_ASSERT(duk_is_string(thr, -1));
15903 	duk_replace(thr, idx);
15904 	ret = duk_get_string(thr, idx);
15905 
15906 	DUK_ASSERT(duk_get_top(thr) == top_at_entry);
15907 
15908 	return ret;
15909 }
15910 
duk_json_decode(duk_hthread * thr,duk_idx_t idx)15911 DUK_EXTERNAL void duk_json_decode(duk_hthread *thr, duk_idx_t idx) {
15912 #if defined(DUK_USE_ASSERTIONS)
15913 	duk_idx_t top_at_entry;
15914 #endif
15915 
15916 	DUK_ASSERT_API_ENTRY(thr);
15917 #if defined(DUK_USE_ASSERTIONS)
15918 	top_at_entry = duk_get_top(thr);
15919 #endif
15920 
15921 	idx = duk_require_normalize_index(thr, idx);
15922 	duk_bi_json_parse_helper(thr,
15923 	                         idx /*idx_value*/,
15924 	                         DUK_INVALID_INDEX /*idx_reviver*/,
15925 	                         0 /*flags*/);
15926 	duk_replace(thr, idx);
15927 
15928 	DUK_ASSERT(duk_get_top(thr) == top_at_entry);
15929 }
15930 #else  /* DUK_USE_JSON_SUPPORT */
duk_json_encode(duk_hthread * thr,duk_idx_t idx)15931 DUK_EXTERNAL const char *duk_json_encode(duk_hthread *thr, duk_idx_t idx) {
15932 	DUK_ASSERT_API_ENTRY(thr);
15933 	DUK_UNREF(idx);
15934 	DUK_ERROR_UNSUPPORTED(thr);
15935 	DUK_WO_NORETURN(return NULL;);
15936 }
15937 
duk_json_decode(duk_hthread * thr,duk_idx_t idx)15938 DUK_EXTERNAL void duk_json_decode(duk_hthread *thr, duk_idx_t idx) {
15939 	DUK_ASSERT_API_ENTRY(thr);
15940 	DUK_UNREF(idx);
15941 	DUK_ERROR_UNSUPPORTED(thr);
15942 	DUK_WO_NORETURN(return;);
15943 }
15944 #endif  /* DUK_USE_JSON_SUPPORT */
15945 /*
15946  *  Compilation and evaluation
15947  */
15948 
15949 /* #include duk_internal.h -> already included */
15950 
15951 typedef struct duk__compile_raw_args duk__compile_raw_args;
15952 struct duk__compile_raw_args {
15953 	duk_size_t src_length;  /* should be first on 64-bit platforms */
15954 	const duk_uint8_t *src_buffer;
15955 	duk_uint_t flags;
15956 };
15957 
15958 /* Eval is just a wrapper now. */
duk_eval_raw(duk_hthread * thr,const char * src_buffer,duk_size_t src_length,duk_uint_t flags)15959 DUK_EXTERNAL duk_int_t duk_eval_raw(duk_hthread *thr, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {
15960 	duk_int_t rc;
15961 
15962 	DUK_ASSERT_API_ENTRY(thr);
15963 
15964 	/* Note: strictness is *not* inherited from the current Duktape/C.
15965 	 * This would be confusing because the current strictness state
15966 	 * depends on whether we're running inside a Duktape/C activation
15967 	 * (= strict mode) or outside of any activation (= non-strict mode).
15968 	 * See tests/api/test-eval-strictness.c for more discussion.
15969 	 */
15970 
15971 	/* [ ... source? filename? ] (depends on flags) */
15972 
15973 	rc = duk_compile_raw(thr, src_buffer, src_length, flags | DUK_COMPILE_EVAL);  /* may be safe, or non-safe depending on flags */
15974 
15975 	/* [ ... closure/error ] */
15976 
15977 	if (rc != DUK_EXEC_SUCCESS) {
15978 		rc = DUK_EXEC_ERROR;
15979 		goto got_rc;
15980 	}
15981 
15982 	duk_push_global_object(thr);  /* explicit 'this' binding, see GH-164 */
15983 
15984 	if (flags & DUK_COMPILE_SAFE) {
15985 		rc = duk_pcall_method(thr, 0);
15986 	} else {
15987 		duk_call_method(thr, 0);
15988 		rc = DUK_EXEC_SUCCESS;
15989 	}
15990 
15991 	/* [ ... result/error ] */
15992 
15993  got_rc:
15994 	if (flags & DUK_COMPILE_NORESULT) {
15995 		duk_pop(thr);
15996 	}
15997 
15998 	return rc;
15999 }
16000 
16001 /* Helper which can be called both directly and with duk_safe_call(). */
duk__do_compile(duk_hthread * thr,void * udata)16002 DUK_LOCAL duk_ret_t duk__do_compile(duk_hthread *thr, void *udata) {
16003 	duk__compile_raw_args *comp_args;
16004 	duk_uint_t flags;
16005 	duk_hcompfunc *h_templ;
16006 
16007 	DUK_CTX_ASSERT_VALID(thr);
16008 	DUK_ASSERT(udata != NULL);
16009 
16010 	/* Note: strictness is not inherited from the current Duktape/C
16011 	 * context.  Otherwise it would not be possible to compile
16012 	 * non-strict code inside a Duktape/C activation (which is
16013 	 * always strict now).  See tests/api/test-eval-strictness.c
16014 	 * for discussion.
16015 	 */
16016 
16017 	/* [ ... source? filename? ] (depends on flags) */
16018 
16019 	comp_args = (duk__compile_raw_args *) udata;
16020 	flags = comp_args->flags;
16021 
16022 	if (flags & DUK_COMPILE_NOFILENAME) {
16023 		/* Automatic filename: 'eval' or 'input'. */
16024 		duk_push_hstring_stridx(thr, (flags & DUK_COMPILE_EVAL) ? DUK_STRIDX_EVAL : DUK_STRIDX_INPUT);
16025 	}
16026 
16027 	/* [ ... source? filename ] */
16028 
16029 	if (!comp_args->src_buffer) {
16030 		duk_hstring *h_sourcecode;
16031 
16032 		h_sourcecode = duk_get_hstring(thr, -2);
16033 		if ((flags & DUK_COMPILE_NOSOURCE) ||  /* args incorrect */
16034 		    (h_sourcecode == NULL)) {          /* e.g. duk_push_string_file_raw() pushed undefined */
16035 			DUK_ERROR_TYPE(thr, DUK_STR_NO_SOURCECODE);
16036 			DUK_WO_NORETURN(return 0;);
16037 		}
16038 		DUK_ASSERT(h_sourcecode != NULL);
16039 		comp_args->src_buffer = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode);
16040 		comp_args->src_length = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode);
16041 	}
16042 	DUK_ASSERT(comp_args->src_buffer != NULL);
16043 
16044 	if (flags & DUK_COMPILE_FUNCTION) {
16045 		flags |= DUK_COMPILE_EVAL | DUK_COMPILE_FUNCEXPR;
16046 	}
16047 
16048 	/* [ ... source? filename ] */
16049 
16050 	duk_js_compile(thr, comp_args->src_buffer, comp_args->src_length, flags);
16051 
16052 	/* [ ... source? func_template ] */
16053 
16054 	if (flags & DUK_COMPILE_NOSOURCE) {
16055 		;
16056 	} else {
16057 		duk_remove_m2(thr);
16058 	}
16059 
16060 	/* [ ... func_template ] */
16061 
16062 	h_templ = (duk_hcompfunc *) duk_known_hobject(thr, -1);
16063 	duk_js_push_closure(thr,
16064 	                   h_templ,
16065 	                   thr->builtins[DUK_BIDX_GLOBAL_ENV],
16066 	                   thr->builtins[DUK_BIDX_GLOBAL_ENV],
16067 	                   1 /*add_auto_proto*/);
16068 	duk_remove_m2(thr);   /* -> [ ... closure ] */
16069 
16070 	/* [ ... closure ] */
16071 
16072 	return 1;
16073 }
16074 
duk_compile_raw(duk_hthread * thr,const char * src_buffer,duk_size_t src_length,duk_uint_t flags)16075 DUK_EXTERNAL duk_int_t duk_compile_raw(duk_hthread *thr, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {
16076 	duk__compile_raw_args comp_args_alloc;
16077 	duk__compile_raw_args *comp_args = &comp_args_alloc;
16078 
16079 	DUK_ASSERT_API_ENTRY(thr);
16080 
16081 	if ((flags & DUK_COMPILE_STRLEN) && (src_buffer != NULL)) {
16082 		/* String length is computed here to avoid multiple evaluation
16083 		 * of a macro argument in the calling side.
16084 		 */
16085 		src_length = DUK_STRLEN(src_buffer);
16086 	}
16087 
16088 	comp_args->src_buffer = (const duk_uint8_t *) src_buffer;
16089 	comp_args->src_length = src_length;
16090 	comp_args->flags = flags;
16091 
16092 	/* [ ... source? filename? ] (depends on flags) */
16093 
16094 	if (flags & DUK_COMPILE_SAFE) {
16095 		duk_int_t rc;
16096 		duk_int_t nargs;
16097 		duk_int_t nrets = 1;
16098 
16099 		/* Arguments can be: [ source? filename? &comp_args] so that
16100 		 * nargs is 1 to 3.  Call site encodes the correct nargs count
16101 		 * directly into flags.
16102 		 */
16103 		nargs = flags & 0x07;
16104 		DUK_ASSERT(nargs == ((flags & DUK_COMPILE_NOSOURCE) ? 0 : 1) +
16105 		                    ((flags & DUK_COMPILE_NOFILENAME) ? 0 : 1));
16106 		rc = duk_safe_call(thr, duk__do_compile, (void *) comp_args, nargs, nrets);
16107 
16108 		/* [ ... closure ] */
16109 		return rc;
16110 	}
16111 
16112 	(void) duk__do_compile(thr, (void *) comp_args);
16113 
16114 	/* [ ... closure ] */
16115 	return DUK_EXEC_SUCCESS;
16116 }
16117 /*
16118  *  Debugging related API calls
16119  */
16120 
16121 /* #include duk_internal.h -> already included */
16122 
16123 #if defined(DUK_USE_JSON_SUPPORT)
duk_push_context_dump(duk_hthread * thr)16124 DUK_EXTERNAL void duk_push_context_dump(duk_hthread *thr) {
16125 	duk_idx_t idx;
16126 	duk_idx_t top;
16127 
16128 	DUK_ASSERT_API_ENTRY(thr);
16129 
16130 	/* We don't duk_require_stack() here now, but rely on the caller having
16131 	 * enough space.
16132 	 */
16133 
16134 	top = duk_get_top(thr);
16135 	duk_push_bare_array(thr);
16136 	for (idx = 0; idx < top; idx++) {
16137 		duk_dup(thr, idx);
16138 		duk_put_prop_index(thr, -2, (duk_uarridx_t) idx);
16139 	}
16140 
16141 	/* XXX: conversion errors should not propagate outwards.
16142 	 * Perhaps values need to be coerced individually?
16143 	 */
16144 	duk_bi_json_stringify_helper(thr,
16145 	                             duk_get_top_index(thr),  /*idx_value*/
16146 	                             DUK_INVALID_INDEX,  /*idx_replacer*/
16147 	                             DUK_INVALID_INDEX,  /*idx_space*/
16148 	                             DUK_JSON_FLAG_EXT_CUSTOM |
16149 	                             DUK_JSON_FLAG_ASCII_ONLY |
16150 	                             DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/);
16151 
16152 	duk_push_sprintf(thr, "ctx: top=%ld, stack=%s", (long) top, (const char *) duk_safe_to_string(thr, -1));
16153 	duk_replace(thr, -3);  /* [ ... arr jsonx(arr) res ] -> [ ... res jsonx(arr) ] */
16154 	duk_pop(thr);
16155 	DUK_ASSERT(duk_is_string(thr, -1));
16156 }
16157 #else  /* DUK_USE_JSON_SUPPORT */
duk_push_context_dump(duk_hthread * thr)16158 DUK_EXTERNAL void duk_push_context_dump(duk_hthread *thr) {
16159 	DUK_ASSERT_API_ENTRY(thr);
16160 	DUK_ERROR_UNSUPPORTED(thr);
16161 	DUK_WO_NORETURN(return;);
16162 }
16163 #endif  /* DUK_USE_JSON_SUPPORT */
16164 
16165 #if defined(DUK_USE_DEBUGGER_SUPPORT)
16166 
duk_debugger_attach(duk_hthread * thr,duk_debug_read_function read_cb,duk_debug_write_function write_cb,duk_debug_peek_function peek_cb,duk_debug_read_flush_function read_flush_cb,duk_debug_write_flush_function write_flush_cb,duk_debug_request_function request_cb,duk_debug_detached_function detached_cb,void * udata)16167 DUK_EXTERNAL void duk_debugger_attach(duk_hthread *thr,
16168                                       duk_debug_read_function read_cb,
16169                                       duk_debug_write_function write_cb,
16170                                       duk_debug_peek_function peek_cb,
16171                                       duk_debug_read_flush_function read_flush_cb,
16172                                       duk_debug_write_flush_function write_flush_cb,
16173                                       duk_debug_request_function request_cb,
16174                                       duk_debug_detached_function detached_cb,
16175                                       void *udata) {
16176 	duk_heap *heap;
16177 	const char *str;
16178 	duk_size_t len;
16179 
16180 	/* XXX: should there be an error or an automatic detach if
16181 	 * already attached?
16182 	 */
16183 
16184 	DUK_D(DUK_DPRINT("application called duk_debugger_attach()"));
16185 
16186 	DUK_ASSERT_API_ENTRY(thr);
16187 	DUK_ASSERT(read_cb != NULL);
16188 	DUK_ASSERT(write_cb != NULL);
16189 	/* Other callbacks are optional. */
16190 
16191 	heap = thr->heap;
16192 	heap->dbg_read_cb = read_cb;
16193 	heap->dbg_write_cb = write_cb;
16194 	heap->dbg_peek_cb = peek_cb;
16195 	heap->dbg_read_flush_cb = read_flush_cb;
16196 	heap->dbg_write_flush_cb = write_flush_cb;
16197 	heap->dbg_request_cb = request_cb;
16198 	heap->dbg_detached_cb = detached_cb;
16199 	heap->dbg_udata = udata;
16200 	heap->dbg_have_next_byte = 0;
16201 
16202 	/* Start in paused state. */
16203 	heap->dbg_processing = 0;
16204 	heap->dbg_state_dirty = 0;
16205 	heap->dbg_force_restart = 0;
16206 	heap->dbg_pause_flags = 0;
16207 	heap->dbg_pause_act = NULL;
16208 	heap->dbg_pause_startline = 0;
16209 	heap->dbg_exec_counter = 0;
16210 	heap->dbg_last_counter = 0;
16211 	heap->dbg_last_time = 0.0;
16212 	duk_debug_set_paused(heap);  /* XXX: overlap with fields above */
16213 
16214 	/* Send version identification and flush right afterwards.  Note that
16215 	 * we must write raw, unframed bytes here.
16216 	 */
16217 	duk_push_sprintf(thr, "%ld %ld %s %s\n",
16218 	                 (long) DUK_DEBUG_PROTOCOL_VERSION,
16219 	                 (long) DUK_VERSION,
16220 	                 (const char *) DUK_GIT_DESCRIBE,
16221 	                 (const char *) DUK_USE_TARGET_INFO);
16222 	str = duk_get_lstring(thr, -1, &len);
16223 	DUK_ASSERT(str != NULL);
16224 	duk_debug_write_bytes(thr, (const duk_uint8_t *) str, len);
16225 	duk_debug_write_flush(thr);
16226 	duk_pop(thr);
16227 }
16228 
duk_debugger_detach(duk_hthread * thr)16229 DUK_EXTERNAL void duk_debugger_detach(duk_hthread *thr) {
16230 	DUK_D(DUK_DPRINT("application called duk_debugger_detach()"));
16231 
16232 	DUK_ASSERT_API_ENTRY(thr);
16233 	DUK_ASSERT(thr->heap != NULL);
16234 
16235 	/* Can be called multiple times with no harm. */
16236 	duk_debug_do_detach(thr->heap);
16237 }
16238 
duk_debugger_cooperate(duk_hthread * thr)16239 DUK_EXTERNAL void duk_debugger_cooperate(duk_hthread *thr) {
16240 	duk_bool_t processed_messages;
16241 
16242 	DUK_ASSERT_API_ENTRY(thr);
16243 	DUK_ASSERT(thr->heap != NULL);
16244 
16245 	if (!duk_debug_is_attached(thr->heap)) {
16246 		return;
16247 	}
16248 	if (thr->callstack_curr != NULL || thr->heap->dbg_processing) {
16249 		/* Calling duk_debugger_cooperate() while Duktape is being
16250 		 * called into is not supported.  This is not a 100% check
16251 		 * but prevents any damage in most cases.
16252 		 */
16253 		return;
16254 	}
16255 
16256 	processed_messages = duk_debug_process_messages(thr, 1 /*no_block*/);
16257 	DUK_UNREF(processed_messages);
16258 }
16259 
duk_debugger_notify(duk_hthread * thr,duk_idx_t nvalues)16260 DUK_EXTERNAL duk_bool_t duk_debugger_notify(duk_hthread *thr, duk_idx_t nvalues) {
16261 	duk_idx_t top;
16262 	duk_idx_t idx;
16263 	duk_bool_t ret = 0;
16264 
16265 	DUK_ASSERT_API_ENTRY(thr);
16266 	DUK_ASSERT(thr->heap != NULL);
16267 
16268 	DUK_D(DUK_DPRINT("application called duk_debugger_notify() with nvalues=%ld", (long) nvalues));
16269 
16270 	top = duk_get_top(thr);
16271 	if (top < nvalues) {
16272 		DUK_ERROR_RANGE(thr, "not enough stack values for notify");
16273 		DUK_WO_NORETURN(return 0;);
16274 	}
16275 	if (duk_debug_is_attached(thr->heap)) {
16276 		duk_debug_write_notify(thr, DUK_DBG_CMD_APPNOTIFY);
16277 		for (idx = top - nvalues; idx < top; idx++) {
16278 			duk_tval *tv = DUK_GET_TVAL_POSIDX(thr, idx);
16279 			duk_debug_write_tval(thr, tv);
16280 		}
16281 		duk_debug_write_eom(thr);
16282 
16283 		/* Return non-zero (true) if we have a good reason to believe
16284 		 * the notify was delivered; if we're still attached at least
16285 		 * a transport error was not indicated by the transport write
16286 		 * callback.  This is not a 100% guarantee of course.
16287 		 */
16288 		if (duk_debug_is_attached(thr->heap)) {
16289 			ret = 1;
16290 		}
16291 	}
16292 	duk_pop_n(thr, nvalues);
16293 	return ret;
16294 }
16295 
duk_debugger_pause(duk_hthread * thr)16296 DUK_EXTERNAL void duk_debugger_pause(duk_hthread *thr) {
16297 	DUK_ASSERT_API_ENTRY(thr);
16298 	DUK_ASSERT(thr->heap != NULL);
16299 
16300 	DUK_D(DUK_DPRINT("application called duk_debugger_pause()"));
16301 
16302 	/* Treat like a debugger statement: ignore when not attached. */
16303 	if (duk_debug_is_attached(thr->heap)) {
16304 		if (duk_debug_is_paused(thr->heap)) {
16305 			DUK_D(DUK_DPRINT("duk_debugger_pause() called when already paused; ignoring"));
16306 		} else {
16307 			duk_debug_set_paused(thr->heap);
16308 
16309 			/* Pause on the next opcode executed.  This is always safe to do even
16310 			 * inside the debugger message loop: the interrupt counter will be reset
16311 			 * to its proper value when the message loop exits.
16312 			 */
16313 			thr->interrupt_init = 1;
16314 			thr->interrupt_counter = 0;
16315 		}
16316 	}
16317 }
16318 
16319 #else  /* DUK_USE_DEBUGGER_SUPPORT */
16320 
duk_debugger_attach(duk_hthread * thr,duk_debug_read_function read_cb,duk_debug_write_function write_cb,duk_debug_peek_function peek_cb,duk_debug_read_flush_function read_flush_cb,duk_debug_write_flush_function write_flush_cb,duk_debug_request_function request_cb,duk_debug_detached_function detached_cb,void * udata)16321 DUK_EXTERNAL void duk_debugger_attach(duk_hthread *thr,
16322                                       duk_debug_read_function read_cb,
16323                                       duk_debug_write_function write_cb,
16324                                       duk_debug_peek_function peek_cb,
16325                                       duk_debug_read_flush_function read_flush_cb,
16326                                       duk_debug_write_flush_function write_flush_cb,
16327                                       duk_debug_request_function request_cb,
16328                                       duk_debug_detached_function detached_cb,
16329                                       void *udata) {
16330 	DUK_ASSERT_API_ENTRY(thr);
16331 	DUK_UNREF(read_cb);
16332 	DUK_UNREF(write_cb);
16333 	DUK_UNREF(peek_cb);
16334 	DUK_UNREF(read_flush_cb);
16335 	DUK_UNREF(write_flush_cb);
16336 	DUK_UNREF(request_cb);
16337 	DUK_UNREF(detached_cb);
16338 	DUK_UNREF(udata);
16339 	DUK_ERROR_TYPE(thr, "no debugger support");
16340 	DUK_WO_NORETURN(return;);
16341 }
16342 
duk_debugger_detach(duk_hthread * thr)16343 DUK_EXTERNAL void duk_debugger_detach(duk_hthread *thr) {
16344 	DUK_ASSERT_API_ENTRY(thr);
16345 	DUK_ERROR_TYPE(thr, "no debugger support");
16346 	DUK_WO_NORETURN(return;);
16347 }
16348 
duk_debugger_cooperate(duk_hthread * thr)16349 DUK_EXTERNAL void duk_debugger_cooperate(duk_hthread *thr) {
16350 	/* nop */
16351 	DUK_ASSERT_API_ENTRY(thr);
16352 	DUK_UNREF(thr);
16353 }
16354 
duk_debugger_notify(duk_hthread * thr,duk_idx_t nvalues)16355 DUK_EXTERNAL duk_bool_t duk_debugger_notify(duk_hthread *thr, duk_idx_t nvalues) {
16356 	duk_idx_t top;
16357 
16358 	DUK_ASSERT_API_ENTRY(thr);
16359 
16360 	top = duk_get_top(thr);
16361 	if (top < nvalues) {
16362 		DUK_ERROR_RANGE_INVALID_COUNT(thr);
16363 		DUK_WO_NORETURN(return 0;);
16364 	}
16365 
16366 	/* No debugger support, just pop values. */
16367 	duk_pop_n(thr, nvalues);
16368 	return 0;
16369 }
16370 
duk_debugger_pause(duk_hthread * thr)16371 DUK_EXTERNAL void duk_debugger_pause(duk_hthread *thr) {
16372 	/* Treat like debugger statement: nop */
16373 	DUK_ASSERT_API_ENTRY(thr);
16374 	DUK_UNREF(thr);
16375 }
16376 
16377 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
16378 /*
16379  *  Heap creation and destruction
16380  */
16381 
16382 /* #include duk_internal.h -> already included */
16383 
16384 typedef struct duk_internal_thread_state duk_internal_thread_state;
16385 
16386 struct duk_internal_thread_state {
16387 	duk_ljstate lj;
16388 	duk_bool_t creating_error;
16389 	duk_hthread *curr_thread;
16390 	duk_uint8_t thread_state;
16391 	duk_int_t call_recursion_depth;
16392 };
16393 
duk_create_heap(duk_alloc_function alloc_func,duk_realloc_function realloc_func,duk_free_function free_func,void * heap_udata,duk_fatal_function fatal_handler)16394 DUK_EXTERNAL duk_hthread *duk_create_heap(duk_alloc_function alloc_func,
16395                                           duk_realloc_function realloc_func,
16396                                           duk_free_function free_func,
16397                                           void *heap_udata,
16398                                           duk_fatal_function fatal_handler) {
16399 	duk_heap *heap = NULL;
16400 	duk_hthread *thr;
16401 
16402 	/* Assume that either all memory funcs are NULL or non-NULL, mixed
16403 	 * cases will now be unsafe.
16404 	 */
16405 
16406 	/* XXX: just assert non-NULL values here and make caller arguments
16407 	 * do the defaulting to the default implementations (smaller code)?
16408 	 */
16409 
16410 	if (!alloc_func) {
16411 		DUK_ASSERT(realloc_func == NULL);
16412 		DUK_ASSERT(free_func == NULL);
16413 #if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
16414 		alloc_func = duk_default_alloc_function;
16415 		realloc_func = duk_default_realloc_function;
16416 		free_func = duk_default_free_function;
16417 #else
16418 		DUK_D(DUK_DPRINT("no allocation functions given and no default providers"));
16419 		return NULL;
16420 #endif
16421 	} else {
16422 		DUK_ASSERT(realloc_func != NULL);
16423 		DUK_ASSERT(free_func != NULL);
16424 	}
16425 
16426 	if (!fatal_handler) {
16427 		fatal_handler = duk_default_fatal_handler;
16428 	}
16429 
16430 	DUK_ASSERT(alloc_func != NULL);
16431 	DUK_ASSERT(realloc_func != NULL);
16432 	DUK_ASSERT(free_func != NULL);
16433 	DUK_ASSERT(fatal_handler != NULL);
16434 
16435 	heap = duk_heap_alloc(alloc_func, realloc_func, free_func, heap_udata, fatal_handler);
16436 	if (!heap) {
16437 		return NULL;
16438 	}
16439 	thr = heap->heap_thread;
16440 	DUK_ASSERT(thr != NULL);
16441 	DUK_ASSERT(thr->heap != NULL);
16442 	return thr;
16443 }
16444 
duk_destroy_heap(duk_hthread * thr)16445 DUK_EXTERNAL void duk_destroy_heap(duk_hthread *thr) {
16446 	duk_heap *heap;
16447 
16448 	if (!thr) {
16449 		return;
16450 	}
16451 	DUK_ASSERT_API_ENTRY(thr);
16452 	heap = thr->heap;
16453 	DUK_ASSERT(heap != NULL);
16454 
16455 	duk_heap_free(heap);
16456 }
16457 
duk_suspend(duk_hthread * thr,duk_thread_state * state)16458 DUK_EXTERNAL void duk_suspend(duk_hthread *thr, duk_thread_state *state) {
16459 	duk_internal_thread_state *snapshot = (duk_internal_thread_state *) (void *) state;
16460 	duk_heap *heap;
16461 	duk_ljstate *lj;
16462 
16463 	DUK_ASSERT_API_ENTRY(thr);
16464 	DUK_ASSERT(thr->heap != NULL);
16465 	DUK_ASSERT(state != NULL);  /* unvalidated */
16466 
16467 	/* Currently not supported when called from within a finalizer.
16468 	 * If that is done, the finalizer will remain running indefinitely,
16469 	 * preventing other finalizers from executing.  The assert is a bit
16470 	 * wider, checking that it would be OK to run pending finalizers.
16471 	 */
16472 	DUK_ASSERT(thr->heap->pf_prevent_count == 0);
16473 
16474 	/* Currently not supported to duk_suspend() from an errCreate()
16475 	 * call.
16476 	 */
16477 	DUK_ASSERT(thr->heap->creating_error == 0);
16478 
16479 	heap = thr->heap;
16480 	lj = &heap->lj;
16481 
16482 	duk_push_tval(thr, &lj->value1);
16483 	duk_push_tval(thr, &lj->value2);
16484 
16485 	/* XXX: creating_error == 0 is asserted above, so no need to store. */
16486 	duk_memcpy((void *) &snapshot->lj, (const void *) lj, sizeof(duk_ljstate));
16487 	snapshot->creating_error = heap->creating_error;
16488 	snapshot->curr_thread = heap->curr_thread;
16489 	snapshot->thread_state = thr->state;
16490 	snapshot->call_recursion_depth = heap->call_recursion_depth;
16491 
16492 	lj->jmpbuf_ptr = NULL;
16493 	lj->type = DUK_LJ_TYPE_UNKNOWN;
16494 	DUK_TVAL_SET_UNDEFINED(&lj->value1);
16495 	DUK_TVAL_SET_UNDEFINED(&lj->value2);
16496 	heap->creating_error = 0;
16497 	heap->curr_thread = NULL;
16498 	heap->call_recursion_depth = 0;
16499 
16500 	thr->state = DUK_HTHREAD_STATE_INACTIVE;
16501 }
16502 
duk_resume(duk_hthread * thr,const duk_thread_state * state)16503 DUK_EXTERNAL void duk_resume(duk_hthread *thr, const duk_thread_state *state) {
16504 	const duk_internal_thread_state *snapshot = (const duk_internal_thread_state *) (const void *) state;
16505 	duk_heap *heap;
16506 
16507 	DUK_ASSERT_API_ENTRY(thr);
16508 	DUK_ASSERT(thr->heap != NULL);
16509 	DUK_ASSERT(state != NULL);  /* unvalidated */
16510 
16511 	/* Shouldn't be necessary if duk_suspend() is called before
16512 	 * duk_resume(), but assert in case API sequence is incorrect.
16513 	 */
16514 	DUK_ASSERT(thr->heap->pf_prevent_count == 0);
16515 	DUK_ASSERT(thr->heap->creating_error == 0);
16516 
16517 	thr->state = snapshot->thread_state;
16518 
16519 	heap = thr->heap;
16520 
16521 	duk_memcpy((void *) &heap->lj, (const void *) &snapshot->lj, sizeof(duk_ljstate));
16522 	heap->creating_error = snapshot->creating_error;
16523 	heap->curr_thread = snapshot->curr_thread;
16524 	heap->call_recursion_depth = snapshot->call_recursion_depth;
16525 
16526 	duk_pop_2(thr);
16527 }
16528 
16529 /* XXX: better place for this */
duk_set_global_object(duk_hthread * thr)16530 DUK_EXTERNAL void duk_set_global_object(duk_hthread *thr) {
16531 	duk_hobject *h_glob;
16532 	duk_hobject *h_prev_glob;
16533 	duk_hobjenv *h_env;
16534 	duk_hobject *h_prev_env;
16535 
16536 	DUK_ASSERT_API_ENTRY(thr);
16537 
16538 	DUK_D(DUK_DPRINT("replace global object with: %!T", duk_get_tval(thr, -1)));
16539 
16540 	h_glob = duk_require_hobject(thr, -1);
16541 	DUK_ASSERT(h_glob != NULL);
16542 
16543 	/*
16544 	 *  Replace global object.
16545 	 */
16546 
16547 	h_prev_glob = thr->builtins[DUK_BIDX_GLOBAL];
16548 	DUK_UNREF(h_prev_glob);
16549 	thr->builtins[DUK_BIDX_GLOBAL] = h_glob;
16550 	DUK_HOBJECT_INCREF(thr, h_glob);
16551 	DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_glob);  /* side effects, in theory (referenced by global env) */
16552 
16553 	/*
16554 	 *  Replace lexical environment for global scope
16555 	 *
16556 	 *  Create a new object environment for the global lexical scope.
16557 	 *  We can't just reset the _Target property of the current one,
16558 	 *  because the lexical scope is shared by other threads with the
16559 	 *  same (initial) built-ins.
16560 	 */
16561 
16562 	h_env = duk_hobjenv_alloc(thr,
16563 	                          DUK_HOBJECT_FLAG_EXTENSIBLE |
16564 	                          DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
16565 	DUK_ASSERT(h_env != NULL);
16566 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_env) == NULL);
16567 
16568 	DUK_ASSERT(h_env->target == NULL);
16569 	DUK_ASSERT(h_glob != NULL);
16570 	h_env->target = h_glob;
16571 	DUK_HOBJECT_INCREF(thr, h_glob);
16572 	DUK_ASSERT(h_env->has_this == 0);
16573 
16574 	/* [ ... new_glob ] */
16575 
16576 	h_prev_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
16577 	thr->builtins[DUK_BIDX_GLOBAL_ENV] = (duk_hobject *) h_env;
16578 	DUK_HOBJECT_INCREF(thr, (duk_hobject *) h_env);
16579 	DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_env);  /* side effects */
16580 	DUK_UNREF(h_env);  /* without refcounts */
16581 	DUK_UNREF(h_prev_env);
16582 
16583 	/* [ ... new_glob ] */
16584 
16585 	duk_pop(thr);
16586 
16587 	/* [ ... ] */
16588 }
16589 /*
16590  *  Inspection
16591  */
16592 
16593 /* #include duk_internal.h -> already included */
16594 
16595 /* For footprint efficient multiple value setting: arrays are much better than
16596  * varargs, format string with parsing is often better than string pointer arrays.
16597  */
duk__inspect_multiple_uint(duk_hthread * thr,const char * fmt,duk_int_t * vals)16598 DUK_LOCAL void duk__inspect_multiple_uint(duk_hthread *thr, const char *fmt, duk_int_t *vals) {
16599 	duk_int_t val;
16600 	const char *p;
16601 	const char *p_curr;
16602 	duk_size_t len;
16603 
16604 	for (p = fmt;;) {
16605 		len = DUK_STRLEN(p);
16606 		p_curr = p;
16607 		p += len + 1;
16608 		if (len == 0) {
16609 			/* Double NUL (= empty key) terminates. */
16610 			break;
16611 		}
16612 		val = *vals++;
16613 		if (val >= 0) {
16614 			/* Negative values are markers to skip key. */
16615 			duk_push_string(thr, p_curr);
16616 			duk_push_int(thr, val);
16617 			duk_put_prop(thr, -3);
16618 		}
16619 	}
16620 }
16621 
16622 /* Raw helper to extract internal information / statistics about a value.
16623  * The return value is an object with properties that are version specific.
16624  * The properties must not expose anything that would lead to security
16625  * issues (e.g. exposing compiled function 'data' buffer might be an issue).
16626  * Currently only counts and sizes and such are given so there shouldn't
16627  * be security implications.
16628  */
16629 
16630 #define DUK__IDX_TYPE     0
16631 #define DUK__IDX_ITAG     1
16632 #define DUK__IDX_REFC     2
16633 #define DUK__IDX_HBYTES   3
16634 #define DUK__IDX_CLASS    4
16635 #define DUK__IDX_PBYTES   5
16636 #define DUK__IDX_ESIZE    6
16637 #define DUK__IDX_ENEXT    7
16638 #define DUK__IDX_ASIZE    8
16639 #define DUK__IDX_HSIZE    9
16640 #define DUK__IDX_BCBYTES  10
16641 #define DUK__IDX_DBYTES   11
16642 #define DUK__IDX_TSTATE   12
16643 #define DUK__IDX_VARIANT  13
16644 
duk_inspect_value(duk_hthread * thr,duk_idx_t idx)16645 DUK_EXTERNAL void duk_inspect_value(duk_hthread *thr, duk_idx_t idx) {
16646 	duk_tval *tv;
16647 	duk_heaphdr *h;
16648 	/* The temporary values should be in an array rather than individual
16649 	 * variables which (in practice) ensures that the compiler won't map
16650 	 * them to registers and emit a lot of unnecessary shuffling code.
16651 	 */
16652 	duk_int_t vals[14];
16653 
16654 	DUK_ASSERT_API_ENTRY(thr);
16655 
16656 	/* Assume two's complement and set everything to -1. */
16657 	duk_memset((void *) &vals, (int) 0xff, sizeof(vals));
16658 	DUK_ASSERT(vals[DUK__IDX_TYPE] == -1);  /* spot check one */
16659 
16660 	tv = duk_get_tval_or_unused(thr, idx);
16661 	h = (DUK_TVAL_IS_HEAP_ALLOCATED(tv) ? DUK_TVAL_GET_HEAPHDR(tv) : NULL);
16662 
16663 	vals[DUK__IDX_TYPE] = duk_get_type_tval(tv);
16664 	vals[DUK__IDX_ITAG] = (duk_int_t) DUK_TVAL_GET_TAG(tv);
16665 
16666 	duk_push_bare_object(thr);  /* Invalidates 'tv'. */
16667 	tv = NULL;
16668 
16669 	if (h == NULL) {
16670 		goto finish;
16671 	}
16672 	duk_push_pointer(thr, (void *) h);
16673 	duk_put_prop_literal(thr, -2, "hptr");
16674 
16675 #if 0
16676 	/* Covers a lot of information, e.g. buffer and string variants. */
16677 	duk_push_uint(thr, (duk_uint_t) DUK_HEAPHDR_GET_FLAGS(h));
16678 	duk_put_prop_literal(thr, -2, "hflags");
16679 #endif
16680 
16681 #if defined(DUK_USE_REFERENCE_COUNTING)
16682 	vals[DUK__IDX_REFC] = (duk_int_t) DUK_HEAPHDR_GET_REFCOUNT(h);
16683 #endif
16684 	vals[DUK__IDX_VARIANT] = 0;
16685 
16686 	/* Heaphdr size and additional allocation size, followed by
16687 	 * type specific stuff (with varying value count).
16688 	 */
16689 	switch ((duk_small_int_t) DUK_HEAPHDR_GET_TYPE(h)) {
16690 	case DUK_HTYPE_STRING: {
16691 		duk_hstring *h_str = (duk_hstring *) h;
16692 		vals[DUK__IDX_HBYTES] = (duk_int_t) (sizeof(duk_hstring) + DUK_HSTRING_GET_BYTELEN(h_str) + 1);
16693 #if defined(DUK_USE_HSTRING_EXTDATA)
16694 		if (DUK_HSTRING_HAS_EXTDATA(h_str)) {
16695 			vals[DUK__IDX_VARIANT] = 1;
16696 		}
16697 #endif
16698 		break;
16699 	}
16700 	case DUK_HTYPE_OBJECT: {
16701 		duk_hobject *h_obj = (duk_hobject *) h;
16702 
16703 		/* XXX: variants here are maybe pointless; class is enough? */
16704 		if (DUK_HOBJECT_IS_ARRAY(h_obj)) {
16705 			vals[DUK__IDX_HBYTES] = sizeof(duk_harray);
16706 		} else if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
16707 			vals[DUK__IDX_HBYTES] = sizeof(duk_hcompfunc);
16708 		} else if (DUK_HOBJECT_IS_NATFUNC(h_obj)) {
16709 			vals[DUK__IDX_HBYTES] = sizeof(duk_hnatfunc);
16710 		} else if (DUK_HOBJECT_IS_THREAD(h_obj)) {
16711 			vals[DUK__IDX_HBYTES] = sizeof(duk_hthread);
16712 			vals[DUK__IDX_TSTATE] = ((duk_hthread *) h_obj)->state;
16713 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
16714 		} else if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
16715 			vals[DUK__IDX_HBYTES] = sizeof(duk_hbufobj);
16716 			/* XXX: some size information */
16717 #endif
16718 		} else {
16719 			vals[DUK__IDX_HBYTES] = (duk_small_uint_t) sizeof(duk_hobject);
16720 		}
16721 
16722 		vals[DUK__IDX_CLASS] = (duk_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h_obj);
16723 		vals[DUK__IDX_PBYTES] = (duk_int_t) DUK_HOBJECT_P_ALLOC_SIZE(h_obj);
16724 		vals[DUK__IDX_ESIZE] = (duk_int_t) DUK_HOBJECT_GET_ESIZE(h_obj);
16725 		vals[DUK__IDX_ENEXT] = (duk_int_t) DUK_HOBJECT_GET_ENEXT(h_obj);
16726 		vals[DUK__IDX_ASIZE] = (duk_int_t) DUK_HOBJECT_GET_ASIZE(h_obj);
16727 		vals[DUK__IDX_HSIZE] = (duk_int_t) DUK_HOBJECT_GET_HSIZE(h_obj);
16728 
16729 		/* Note: e_next indicates the number of gc-reachable entries
16730 		 * in the entry part, and also indicates the index where the
16731 		 * next new property would be inserted.  It does *not* indicate
16732 		 * the number of non-NULL keys present in the object.  That
16733 		 * value could be counted separately but requires a pass through
16734 		 * the key list.
16735 		 */
16736 
16737 		if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
16738 			duk_hbuffer *h_data = (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(thr->heap, (duk_hcompfunc *) h_obj);
16739 			vals[DUK__IDX_BCBYTES] = (duk_int_t) (h_data ? DUK_HBUFFER_GET_SIZE(h_data) : 0);
16740 		}
16741 		break;
16742 	}
16743 	case DUK_HTYPE_BUFFER: {
16744 		duk_hbuffer *h_buf = (duk_hbuffer *) h;
16745 
16746 		if (DUK_HBUFFER_HAS_DYNAMIC(h_buf)) {
16747 			if (DUK_HBUFFER_HAS_EXTERNAL(h_buf)) {
16748 				vals[DUK__IDX_VARIANT] = 2;  /* buffer variant 2: external */
16749 				vals[DUK__IDX_HBYTES] = (duk_uint_t) (sizeof(duk_hbuffer_external));
16750 			} else {
16751 				/* When alloc_size == 0 the second allocation may not
16752 				 * actually exist.
16753 				 */
16754 				vals[DUK__IDX_VARIANT] = 1;  /* buffer variant 1: dynamic */
16755 				vals[DUK__IDX_HBYTES] = (duk_uint_t) (sizeof(duk_hbuffer_dynamic));
16756 			}
16757 			vals[DUK__IDX_DBYTES] = (duk_int_t) (DUK_HBUFFER_GET_SIZE(h_buf));
16758 		} else {
16759 			DUK_ASSERT(vals[DUK__IDX_VARIANT] == 0);  /* buffer variant 0: fixed */
16760 			vals[DUK__IDX_HBYTES] = (duk_int_t) (sizeof(duk_hbuffer_fixed) + DUK_HBUFFER_GET_SIZE(h_buf));
16761 		}
16762 		break;
16763 	}
16764 	}
16765 
16766  finish:
16767 	duk__inspect_multiple_uint(thr,
16768 	    "type" "\x00" "itag" "\x00" "refc" "\x00" "hbytes" "\x00" "class" "\x00"
16769 	    "pbytes" "\x00" "esize" "\x00" "enext" "\x00" "asize" "\x00" "hsize" "\x00"
16770 	    "bcbytes" "\x00" "dbytes" "\x00" "tstate" "\x00" "variant" "\x00" "\x00",
16771 	    (duk_int_t *) &vals);
16772 }
16773 
duk_inspect_callstack_entry(duk_hthread * thr,duk_int_t level)16774 DUK_EXTERNAL void duk_inspect_callstack_entry(duk_hthread *thr, duk_int_t level) {
16775 	duk_activation *act;
16776 	duk_uint_fast32_t pc;
16777 	duk_uint_fast32_t line;
16778 
16779 	DUK_ASSERT_API_ENTRY(thr);
16780 
16781 	/* -1   = top callstack entry
16782 	 * -2   = caller of level -1
16783 	 * etc
16784 	 */
16785 	act = duk_hthread_get_activation_for_level(thr, level);
16786 	if (act == NULL) {
16787 		duk_push_undefined(thr);
16788 		return;
16789 	}
16790 	duk_push_bare_object(thr);
16791 
16792 	/* Relevant PC is just before current one because PC is
16793 	 * post-incremented.  This should match what error augment
16794 	 * code does.
16795 	 */
16796 	pc = duk_hthread_get_act_prev_pc(thr, act);
16797 
16798 	duk_push_tval(thr, &act->tv_func);
16799 
16800 	duk_push_uint(thr, (duk_uint_t) pc);
16801 	duk_put_prop_stridx_short(thr, -3, DUK_STRIDX_PC);
16802 
16803 #if defined(DUK_USE_PC2LINE)
16804 	line = duk_hobject_pc2line_query(thr, -1, pc);
16805 #else
16806 	line = 0;
16807 #endif
16808 	duk_push_uint(thr, (duk_uint_t) line);
16809 	duk_put_prop_stridx_short(thr, -3, DUK_STRIDX_LINE_NUMBER);
16810 
16811 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_LC_FUNCTION);
16812 	/* Providing access to e.g. act->lex_env would be dangerous: these
16813 	 * internal structures must never be accessible to the application.
16814 	 * Duktape relies on them having consistent data, and this consistency
16815 	 * is only asserted for, not checked for.
16816 	 */
16817 }
16818 
16819 /* automatic undefs */
16820 #undef DUK__IDX_ASIZE
16821 #undef DUK__IDX_BCBYTES
16822 #undef DUK__IDX_CLASS
16823 #undef DUK__IDX_DBYTES
16824 #undef DUK__IDX_ENEXT
16825 #undef DUK__IDX_ESIZE
16826 #undef DUK__IDX_HBYTES
16827 #undef DUK__IDX_HSIZE
16828 #undef DUK__IDX_ITAG
16829 #undef DUK__IDX_PBYTES
16830 #undef DUK__IDX_REFC
16831 #undef DUK__IDX_TSTATE
16832 #undef DUK__IDX_TYPE
16833 #undef DUK__IDX_VARIANT
16834 /*
16835  *  Memory calls.
16836  */
16837 
16838 /* #include duk_internal.h -> already included */
16839 
duk_alloc_raw(duk_hthread * thr,duk_size_t size)16840 DUK_EXTERNAL void *duk_alloc_raw(duk_hthread *thr, duk_size_t size) {
16841 	DUK_ASSERT_API_ENTRY(thr);
16842 
16843 	return DUK_ALLOC_RAW(thr->heap, size);
16844 }
16845 
duk_free_raw(duk_hthread * thr,void * ptr)16846 DUK_EXTERNAL void duk_free_raw(duk_hthread *thr, void *ptr) {
16847 	DUK_ASSERT_API_ENTRY(thr);
16848 
16849 	DUK_FREE_RAW(thr->heap, ptr);
16850 }
16851 
duk_realloc_raw(duk_hthread * thr,void * ptr,duk_size_t size)16852 DUK_EXTERNAL void *duk_realloc_raw(duk_hthread *thr, void *ptr, duk_size_t size) {
16853 	DUK_ASSERT_API_ENTRY(thr);
16854 
16855 	return DUK_REALLOC_RAW(thr->heap, ptr, size);
16856 }
16857 
duk_alloc(duk_hthread * thr,duk_size_t size)16858 DUK_EXTERNAL void *duk_alloc(duk_hthread *thr, duk_size_t size) {
16859 	DUK_ASSERT_API_ENTRY(thr);
16860 
16861 	return DUK_ALLOC(thr->heap, size);
16862 }
16863 
duk_free(duk_hthread * thr,void * ptr)16864 DUK_EXTERNAL void duk_free(duk_hthread *thr, void *ptr) {
16865 	DUK_ASSERT_API_ENTRY(thr);
16866 
16867 	DUK_FREE_CHECKED(thr, ptr);
16868 }
16869 
duk_realloc(duk_hthread * thr,void * ptr,duk_size_t size)16870 DUK_EXTERNAL void *duk_realloc(duk_hthread *thr, void *ptr, duk_size_t size) {
16871 	DUK_ASSERT_API_ENTRY(thr);
16872 
16873 	/*
16874 	 *  Note: since this is an exposed API call, there should be
16875 	 *  no way a mark-and-sweep could have a side effect on the
16876 	 *  memory allocation behind 'ptr'; the pointer should never
16877 	 *  be something that Duktape wants to change.
16878 	 *
16879 	 *  Thus, no need to use DUK_REALLOC_INDIRECT (and we don't
16880 	 *  have the storage location here anyway).
16881 	 */
16882 
16883 	return DUK_REALLOC(thr->heap, ptr, size);
16884 }
16885 
duk_get_memory_functions(duk_hthread * thr,duk_memory_functions * out_funcs)16886 DUK_EXTERNAL void duk_get_memory_functions(duk_hthread *thr, duk_memory_functions *out_funcs) {
16887 	duk_heap *heap;
16888 
16889 	DUK_ASSERT_API_ENTRY(thr);
16890 	DUK_ASSERT(out_funcs != NULL);
16891 	DUK_ASSERT(thr != NULL);
16892 	DUK_ASSERT(thr->heap != NULL);
16893 
16894 	heap = thr->heap;
16895 	out_funcs->alloc_func = heap->alloc_func;
16896 	out_funcs->realloc_func = heap->realloc_func;
16897 	out_funcs->free_func = heap->free_func;
16898 	out_funcs->udata = heap->heap_udata;
16899 }
16900 
duk_gc(duk_hthread * thr,duk_uint_t flags)16901 DUK_EXTERNAL void duk_gc(duk_hthread *thr, duk_uint_t flags) {
16902 	duk_heap *heap;
16903 	duk_small_uint_t ms_flags;
16904 
16905 	DUK_ASSERT_API_ENTRY(thr);
16906 	heap = thr->heap;
16907 	DUK_ASSERT(heap != NULL);
16908 
16909 	DUK_D(DUK_DPRINT("mark-and-sweep requested by application"));
16910 	DUK_ASSERT(DUK_GC_COMPACT == DUK_MS_FLAG_EMERGENCY);  /* Compact flag is 1:1 with emergency flag which forces compaction. */
16911 	ms_flags = (duk_small_uint_t) flags;
16912 	duk_heap_mark_and_sweep(heap, ms_flags);
16913 }
16914 /*
16915  *  Object handling: property access and other support functions.
16916  */
16917 
16918 /* #include duk_internal.h -> already included */
16919 
16920 /*
16921  *  Property handling
16922  *
16923  *  The API exposes only the most common property handling functions.
16924  *  The caller can invoke ECMAScript built-ins for full control (e.g.
16925  *  defineProperty, getOwnPropertyDescriptor).
16926  */
16927 
duk_get_prop(duk_hthread * thr,duk_idx_t obj_idx)16928 DUK_EXTERNAL duk_bool_t duk_get_prop(duk_hthread *thr, duk_idx_t obj_idx) {
16929 	duk_tval *tv_obj;
16930 	duk_tval *tv_key;
16931 	duk_bool_t rc;
16932 
16933 	DUK_ASSERT_API_ENTRY(thr);
16934 
16935 	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
16936 	 * resize is not necessary for a property get right now.
16937 	 */
16938 
16939 	tv_obj = duk_require_tval(thr, obj_idx);
16940 	tv_key = duk_require_tval(thr, -1);
16941 
16942 	rc = duk_hobject_getprop(thr, tv_obj, tv_key);
16943 	DUK_ASSERT(rc == 0 || rc == 1);
16944 	/* a value is left on stack regardless of rc */
16945 
16946 	duk_remove_m2(thr);  /* remove key */
16947 	DUK_ASSERT(duk_is_undefined(thr, -1) || rc == 1);
16948 	return rc;  /* 1 if property found, 0 otherwise */
16949 }
16950 
duk_get_prop_string(duk_hthread * thr,duk_idx_t obj_idx,const char * key)16951 DUK_EXTERNAL duk_bool_t duk_get_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
16952 	DUK_ASSERT_API_ENTRY(thr);
16953 	DUK_ASSERT(key != NULL);
16954 
16955 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16956 	(void) duk_push_string(thr, key);
16957 	return duk_get_prop(thr, obj_idx);
16958 }
16959 
duk_get_prop_lstring(duk_hthread * thr,duk_idx_t obj_idx,const char * key,duk_size_t key_len)16960 DUK_EXTERNAL duk_bool_t duk_get_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
16961 	DUK_ASSERT_API_ENTRY(thr);
16962 	DUK_ASSERT(key != NULL);
16963 
16964 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16965 	(void) duk_push_lstring(thr, key, key_len);
16966 	return duk_get_prop(thr, obj_idx);
16967 }
16968 
16969 #if !defined(DUK_USE_PREFER_SIZE)
duk_get_prop_literal_raw(duk_hthread * thr,duk_idx_t obj_idx,const char * key,duk_size_t key_len)16970 DUK_EXTERNAL duk_bool_t duk_get_prop_literal_raw(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
16971 	DUK_ASSERT_API_ENTRY(thr);
16972 	DUK_ASSERT(key != NULL);
16973 	DUK_ASSERT(key[key_len] == (char) 0);
16974 
16975 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16976 	(void) duk_push_literal_raw(thr, key, key_len);
16977 	return duk_get_prop(thr, obj_idx);
16978 }
16979 #endif
16980 
duk_get_prop_index(duk_hthread * thr,duk_idx_t obj_idx,duk_uarridx_t arr_idx)16981 DUK_EXTERNAL duk_bool_t duk_get_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
16982 	DUK_ASSERT_API_ENTRY(thr);
16983 
16984 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16985 	duk_push_uarridx(thr, arr_idx);
16986 	return duk_get_prop(thr, obj_idx);
16987 }
16988 
duk_get_prop_heapptr(duk_hthread * thr,duk_idx_t obj_idx,void * ptr)16989 DUK_EXTERNAL duk_bool_t duk_get_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {
16990 	DUK_ASSERT_API_ENTRY(thr);
16991 
16992 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16993 	(void) duk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */
16994 	return duk_get_prop(thr, obj_idx);
16995 }
16996 
duk_get_prop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)16997 DUK_INTERNAL duk_bool_t duk_get_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
16998 	DUK_ASSERT_API_ENTRY(thr);
16999 	DUK_ASSERT_STRIDX_VALID(stridx);
17000 
17001 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17002 	(void) duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
17003 	return duk_get_prop(thr, obj_idx);
17004 }
17005 
duk_get_prop_stridx_short_raw(duk_hthread * thr,duk_uint_t packed_args)17006 DUK_INTERNAL duk_bool_t duk_get_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
17007 	return duk_get_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
17008 	                                (duk_small_uint_t) (packed_args & 0xffffUL));
17009 }
17010 
duk_get_prop_stridx_boolean(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx,duk_bool_t * out_has_prop)17011 DUK_INTERNAL duk_bool_t duk_get_prop_stridx_boolean(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_bool_t *out_has_prop) {
17012 	duk_bool_t rc;
17013 
17014 	DUK_ASSERT_API_ENTRY(thr);
17015 	DUK_ASSERT_STRIDX_VALID(stridx);
17016 
17017 	rc = duk_get_prop_stridx(thr, obj_idx, stridx);
17018 	if (out_has_prop) {
17019 		*out_has_prop = rc;
17020 	}
17021 	return duk_to_boolean_top_pop(thr);
17022 }
17023 
17024 /* This get variant is for internal use, it differs from standard
17025  * duk_get_prop() in that:
17026  *   - Object argument must be an object (primitive values not supported).
17027  *   - Key argument must be a string (no coercion).
17028  *   - Only own properties are checked (no inheritance).  Only "entry part"
17029  *     properties are checked (not array index properties).
17030  *   - Property must be a plain data property, not a getter.
17031  *   - Proxy traps are not triggered.
17032  */
duk_xget_owndataprop(duk_hthread * thr,duk_idx_t obj_idx)17033 DUK_INTERNAL duk_bool_t duk_xget_owndataprop(duk_hthread *thr, duk_idx_t obj_idx) {
17034 	duk_hobject *h_obj;
17035 	duk_hstring *h_key;
17036 	duk_tval *tv_val;
17037 
17038 	DUK_ASSERT_API_ENTRY(thr);
17039 
17040 	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
17041 	 * resize is not necessary for a property get right now.
17042 	 */
17043 
17044 	h_obj = duk_get_hobject(thr, obj_idx);
17045 	if (h_obj == NULL) {
17046 		return 0;
17047 	}
17048 	h_key = duk_require_hstring(thr, -1);
17049 
17050 	tv_val = duk_hobject_find_entry_tval_ptr(thr->heap, h_obj, h_key);
17051 	if (tv_val == NULL) {
17052 		return 0;
17053 	}
17054 
17055 	duk_push_tval(thr, tv_val);
17056 	duk_remove_m2(thr);  /* remove key */
17057 
17058 	return 1;
17059 }
17060 
duk_xget_owndataprop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)17061 DUK_INTERNAL duk_bool_t duk_xget_owndataprop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
17062 	DUK_ASSERT_API_ENTRY(thr);
17063 	DUK_ASSERT_STRIDX_VALID(stridx);
17064 
17065 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17066 	(void) duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
17067 	return duk_xget_owndataprop(thr, obj_idx);
17068 }
17069 
duk_xget_owndataprop_stridx_short_raw(duk_hthread * thr,duk_uint_t packed_args)17070 DUK_INTERNAL duk_bool_t duk_xget_owndataprop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
17071 	return duk_xget_owndataprop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
17072 	                                   (duk_small_uint_t) (packed_args & 0xffffUL));
17073 }
17074 
duk__put_prop_shared(duk_hthread * thr,duk_idx_t obj_idx,duk_idx_t idx_key)17075 DUK_LOCAL duk_bool_t duk__put_prop_shared(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t idx_key) {
17076 	duk_tval *tv_obj;
17077 	duk_tval *tv_key;
17078 	duk_tval *tv_val;
17079 	duk_bool_t throw_flag;
17080 	duk_bool_t rc;
17081 
17082 	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
17083 	 * resize is not necessary for a property put right now (putprop protects
17084 	 * against it internally).
17085 	 */
17086 
17087 	/* Key and value indices are either (-2, -1) or (-1, -2).  Given idx_key,
17088 	 * idx_val is always (idx_key ^ 0x01).
17089 	 */
17090 	DUK_ASSERT((idx_key == -2 && (idx_key ^ 1) == -1) ||
17091 	           (idx_key == -1 && (idx_key ^ 1) == -2));
17092 	/* XXX: Direct access; faster validation. */
17093 	tv_obj = duk_require_tval(thr, obj_idx);
17094 	tv_key = duk_require_tval(thr, idx_key);
17095 	tv_val = duk_require_tval(thr, idx_key ^ 1);
17096 	throw_flag = duk_is_strict_call(thr);
17097 
17098 	rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, throw_flag);
17099 	DUK_ASSERT(rc == 0 || rc == 1);
17100 
17101 	duk_pop_2(thr);  /* remove key and value */
17102 	return rc;  /* 1 if property found, 0 otherwise */
17103 }
17104 
duk_put_prop(duk_hthread * thr,duk_idx_t obj_idx)17105 DUK_EXTERNAL duk_bool_t duk_put_prop(duk_hthread *thr, duk_idx_t obj_idx) {
17106 	DUK_ASSERT_API_ENTRY(thr);
17107 	return duk__put_prop_shared(thr, obj_idx, -2);
17108 }
17109 
duk_put_prop_string(duk_hthread * thr,duk_idx_t obj_idx,const char * key)17110 DUK_EXTERNAL duk_bool_t duk_put_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
17111 	DUK_ASSERT_API_ENTRY(thr);
17112 	DUK_ASSERT(key != NULL);
17113 
17114 	/* Careful here and with other duk_put_prop_xxx() helpers: the
17115 	 * target object and the property value may be in the same value
17116 	 * stack slot (unusual, but still conceptually clear).
17117 	 */
17118 	obj_idx = duk_normalize_index(thr, obj_idx);
17119 	(void) duk_push_string(thr, key);
17120 	return duk__put_prop_shared(thr, obj_idx, -1);
17121 }
17122 
duk_put_prop_lstring(duk_hthread * thr,duk_idx_t obj_idx,const char * key,duk_size_t key_len)17123 DUK_EXTERNAL duk_bool_t duk_put_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
17124 	DUK_ASSERT_API_ENTRY(thr);
17125 	DUK_ASSERT(key != NULL);
17126 
17127 	obj_idx = duk_normalize_index(thr, obj_idx);
17128 	(void) duk_push_lstring(thr, key, key_len);
17129 	return duk__put_prop_shared(thr, obj_idx, -1);
17130 }
17131 
17132 #if !defined(DUK_USE_PREFER_SIZE)
duk_put_prop_literal_raw(duk_hthread * thr,duk_idx_t obj_idx,const char * key,duk_size_t key_len)17133 DUK_EXTERNAL duk_bool_t duk_put_prop_literal_raw(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
17134 	DUK_ASSERT_API_ENTRY(thr);
17135 	DUK_ASSERT(key != NULL);
17136 	DUK_ASSERT(key[key_len] == (char) 0);
17137 
17138 	obj_idx = duk_normalize_index(thr, obj_idx);
17139 	(void) duk_push_literal_raw(thr, key, key_len);
17140 	return duk__put_prop_shared(thr, obj_idx, -1);
17141 }
17142 #endif
17143 
duk_put_prop_index(duk_hthread * thr,duk_idx_t obj_idx,duk_uarridx_t arr_idx)17144 DUK_EXTERNAL duk_bool_t duk_put_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
17145 	DUK_ASSERT_API_ENTRY(thr);
17146 
17147 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17148 	duk_push_uarridx(thr, arr_idx);
17149 	return duk__put_prop_shared(thr, obj_idx, -1);
17150 }
17151 
duk_put_prop_heapptr(duk_hthread * thr,duk_idx_t obj_idx,void * ptr)17152 DUK_EXTERNAL duk_bool_t duk_put_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {
17153 	DUK_ASSERT_API_ENTRY(thr);
17154 
17155 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17156 	(void) duk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */
17157 	return duk__put_prop_shared(thr, obj_idx, -1);
17158 }
17159 
17160 
duk_put_prop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)17161 DUK_INTERNAL duk_bool_t duk_put_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
17162 	DUK_ASSERT_API_ENTRY(thr);
17163 	DUK_ASSERT_STRIDX_VALID(stridx);
17164 
17165 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17166 	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
17167 	return duk__put_prop_shared(thr, obj_idx, -1);
17168 }
17169 
duk_put_prop_stridx_short_raw(duk_hthread * thr,duk_uint_t packed_args)17170 DUK_INTERNAL duk_bool_t duk_put_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
17171 	return duk_put_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
17172 	                                (duk_small_uint_t) (packed_args & 0xffffUL));
17173 }
17174 
duk_del_prop(duk_hthread * thr,duk_idx_t obj_idx)17175 DUK_EXTERNAL duk_bool_t duk_del_prop(duk_hthread *thr, duk_idx_t obj_idx) {
17176 	duk_tval *tv_obj;
17177 	duk_tval *tv_key;
17178 	duk_bool_t throw_flag;
17179 	duk_bool_t rc;
17180 
17181 	DUK_ASSERT_API_ENTRY(thr);
17182 
17183 	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
17184 	 * resize is not necessary for a property delete right now.
17185 	 */
17186 
17187 	tv_obj = duk_require_tval(thr, obj_idx);
17188 	tv_key = duk_require_tval(thr, -1);
17189 	throw_flag = duk_is_strict_call(thr);
17190 
17191 	rc = duk_hobject_delprop(thr, tv_obj, tv_key, throw_flag);
17192 	DUK_ASSERT(rc == 0 || rc == 1);
17193 
17194 	duk_pop(thr);  /* remove key */
17195 	return rc;
17196 }
17197 
duk_del_prop_string(duk_hthread * thr,duk_idx_t obj_idx,const char * key)17198 DUK_EXTERNAL duk_bool_t duk_del_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
17199 	DUK_ASSERT_API_ENTRY(thr);
17200 	DUK_ASSERT(key != NULL);
17201 
17202 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17203 	(void) duk_push_string(thr, key);
17204 	return duk_del_prop(thr, obj_idx);
17205 }
17206 
duk_del_prop_lstring(duk_hthread * thr,duk_idx_t obj_idx,const char * key,duk_size_t key_len)17207 DUK_EXTERNAL duk_bool_t duk_del_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
17208 	DUK_ASSERT_API_ENTRY(thr);
17209 	DUK_ASSERT(key != NULL);
17210 
17211 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17212 	(void) duk_push_lstring(thr, key, key_len);
17213 	return duk_del_prop(thr, obj_idx);
17214 }
17215 
17216 #if !defined(DUK_USE_PREFER_SIZE)
duk_del_prop_literal_raw(duk_hthread * thr,duk_idx_t obj_idx,const char * key,duk_size_t key_len)17217 DUK_EXTERNAL duk_bool_t duk_del_prop_literal_raw(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
17218 	DUK_ASSERT_API_ENTRY(thr);
17219 	DUK_ASSERT(key != NULL);
17220 	DUK_ASSERT(key[key_len] == (char) 0);
17221 
17222 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17223 	(void) duk_push_literal_raw(thr, key, key_len);
17224 	return duk_del_prop(thr, obj_idx);
17225 }
17226 #endif
17227 
duk_del_prop_index(duk_hthread * thr,duk_idx_t obj_idx,duk_uarridx_t arr_idx)17228 DUK_EXTERNAL duk_bool_t duk_del_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
17229 	DUK_ASSERT_API_ENTRY(thr);
17230 
17231 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17232 	duk_push_uarridx(thr, arr_idx);
17233 	return duk_del_prop(thr, obj_idx);
17234 }
17235 
duk_del_prop_heapptr(duk_hthread * thr,duk_idx_t obj_idx,void * ptr)17236 DUK_EXTERNAL duk_bool_t duk_del_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {
17237 	DUK_ASSERT_API_ENTRY(thr);
17238 
17239 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17240 	(void) duk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */
17241 	return duk_del_prop(thr, obj_idx);
17242 }
17243 
duk_del_prop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)17244 DUK_INTERNAL duk_bool_t duk_del_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
17245 	DUK_ASSERT_API_ENTRY(thr);
17246 	DUK_ASSERT_STRIDX_VALID(stridx);
17247 
17248 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17249 	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
17250 	return duk_del_prop(thr, obj_idx);
17251 }
17252 
17253 #if 0
17254 DUK_INTERNAL duk_bool_t duk_del_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
17255 	return duk_del_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
17256 	                                (duk_small_uint_t) (packed_args & 0xffffUL));
17257 }
17258 #endif
17259 
duk_has_prop(duk_hthread * thr,duk_idx_t obj_idx)17260 DUK_EXTERNAL duk_bool_t duk_has_prop(duk_hthread *thr, duk_idx_t obj_idx) {
17261 	duk_tval *tv_obj;
17262 	duk_tval *tv_key;
17263 	duk_bool_t rc;
17264 
17265 	DUK_ASSERT_API_ENTRY(thr);
17266 
17267 	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
17268 	 * resize is not necessary for a property existence check right now.
17269 	 */
17270 
17271 	tv_obj = duk_require_tval(thr, obj_idx);
17272 	tv_key = duk_require_tval(thr, -1);
17273 
17274 	rc = duk_hobject_hasprop(thr, tv_obj, tv_key);
17275 	DUK_ASSERT(rc == 0 || rc == 1);
17276 
17277 	duk_pop(thr);  /* remove key */
17278 	return rc;  /* 1 if property found, 0 otherwise */
17279 }
17280 
duk_has_prop_string(duk_hthread * thr,duk_idx_t obj_idx,const char * key)17281 DUK_EXTERNAL duk_bool_t duk_has_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
17282 	DUK_ASSERT_API_ENTRY(thr);
17283 	DUK_ASSERT(key != NULL);
17284 
17285 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17286 	(void) duk_push_string(thr, key);
17287 	return duk_has_prop(thr, obj_idx);
17288 }
17289 
duk_has_prop_lstring(duk_hthread * thr,duk_idx_t obj_idx,const char * key,duk_size_t key_len)17290 DUK_EXTERNAL duk_bool_t duk_has_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
17291 	DUK_ASSERT_API_ENTRY(thr);
17292 	DUK_ASSERT(key != NULL);
17293 
17294 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17295 	(void) duk_push_lstring(thr, key, key_len);
17296 	return duk_has_prop(thr, obj_idx);
17297 }
17298 
17299 #if !defined(DUK_USE_PREFER_SIZE)
duk_has_prop_literal_raw(duk_hthread * thr,duk_idx_t obj_idx,const char * key,duk_size_t key_len)17300 DUK_EXTERNAL duk_bool_t duk_has_prop_literal_raw(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
17301 	DUK_ASSERT_API_ENTRY(thr);
17302 	DUK_ASSERT(key != NULL);
17303 	DUK_ASSERT(key[key_len] == (char) 0);
17304 
17305 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17306 	(void) duk_push_literal_raw(thr, key, key_len);
17307 	return duk_has_prop(thr, obj_idx);
17308 }
17309 #endif
17310 
duk_has_prop_index(duk_hthread * thr,duk_idx_t obj_idx,duk_uarridx_t arr_idx)17311 DUK_EXTERNAL duk_bool_t duk_has_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
17312 	DUK_ASSERT_API_ENTRY(thr);
17313 
17314 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17315 	duk_push_uarridx(thr, arr_idx);
17316 	return duk_has_prop(thr, obj_idx);
17317 }
17318 
duk_has_prop_heapptr(duk_hthread * thr,duk_idx_t obj_idx,void * ptr)17319 DUK_EXTERNAL duk_bool_t duk_has_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {
17320 	DUK_ASSERT_API_ENTRY(thr);
17321 
17322 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17323 	(void) duk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */
17324 	return duk_has_prop(thr, obj_idx);
17325 }
17326 
duk_has_prop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)17327 DUK_INTERNAL duk_bool_t duk_has_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
17328 	DUK_ASSERT_API_ENTRY(thr);
17329 	DUK_ASSERT_STRIDX_VALID(stridx);
17330 
17331 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17332 	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
17333 	return duk_has_prop(thr, obj_idx);
17334 }
17335 
17336 #if 0
17337 DUK_INTERNAL duk_bool_t duk_has_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
17338 	return duk_has_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
17339 	                                (duk_small_uint_t) (packed_args & 0xffffUL));
17340 }
17341 #endif
17342 
17343 /* Define own property without inheritance lookups and such.  This differs from
17344  * [[DefineOwnProperty]] because special behaviors (like Array 'length') are
17345  * not invoked by this method.  The caller must be careful to invoke any such
17346  * behaviors if necessary.
17347  */
duk_xdef_prop(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t desc_flags)17348 DUK_INTERNAL void duk_xdef_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t desc_flags) {
17349 	duk_hobject *obj;
17350 	duk_hstring *key;
17351 
17352 	DUK_ASSERT_API_ENTRY(thr);
17353 
17354 	obj = duk_require_hobject(thr, obj_idx);
17355 	DUK_ASSERT(obj != NULL);
17356 	key = duk_to_property_key_hstring(thr, -2);
17357 	DUK_ASSERT(key != NULL);
17358 	DUK_ASSERT(duk_require_tval(thr, -1) != NULL);
17359 
17360 	duk_hobject_define_property_internal(thr, obj, key, desc_flags);
17361 
17362 	duk_pop(thr);  /* pop key */
17363 }
17364 
duk_xdef_prop_index(duk_hthread * thr,duk_idx_t obj_idx,duk_uarridx_t arr_idx,duk_small_uint_t desc_flags)17365 DUK_INTERNAL void duk_xdef_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx, duk_small_uint_t desc_flags) {
17366 	duk_hobject *obj;
17367 
17368 	DUK_ASSERT_API_ENTRY(thr);
17369 
17370 	obj = duk_require_hobject(thr, obj_idx);
17371 	DUK_ASSERT(obj != NULL);
17372 
17373 	duk_hobject_define_property_internal_arridx(thr, obj, arr_idx, desc_flags);
17374 	/* value popped by call */
17375 }
17376 
duk_xdef_prop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx,duk_small_uint_t desc_flags)17377 DUK_INTERNAL void duk_xdef_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_small_uint_t desc_flags) {
17378 	duk_hobject *obj;
17379 	duk_hstring *key;
17380 
17381 	DUK_ASSERT_API_ENTRY(thr);
17382 	DUK_ASSERT_STRIDX_VALID(stridx);
17383 
17384 	obj = duk_require_hobject(thr, obj_idx);
17385 	DUK_ASSERT(obj != NULL);
17386 	key = DUK_HTHREAD_GET_STRING(thr, stridx);
17387 	DUK_ASSERT(key != NULL);
17388 	DUK_ASSERT(duk_require_tval(thr, -1) != NULL);
17389 
17390 	duk_hobject_define_property_internal(thr, obj, key, desc_flags);
17391 	/* value popped by call */
17392 }
17393 
duk_xdef_prop_stridx_short_raw(duk_hthread * thr,duk_uint_t packed_args)17394 DUK_INTERNAL void duk_xdef_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
17395 	duk_xdef_prop_stridx(thr, (duk_idx_t) (duk_int8_t) (packed_args >> 24),
17396 	                          (duk_small_uint_t) (packed_args >> 8) & 0xffffUL,
17397 	                          (duk_small_uint_t) (packed_args & 0xffL));
17398 }
17399 
17400 #if 0  /*unused*/
17401 DUK_INTERNAL void duk_xdef_prop_stridx_builtin(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_small_int_t builtin_idx, duk_small_uint_t desc_flags) {
17402 	duk_hobject *obj;
17403 	duk_hstring *key;
17404 
17405 	DUK_ASSERT_API_ENTRY(thr);
17406 	DUK_ASSERT_STRIDX_VALID(stridx);
17407 	DUK_ASSERT_BIDX_VALID(builtin_idx);
17408 
17409 	obj = duk_require_hobject(thr, obj_idx);
17410 	DUK_ASSERT(obj != NULL);
17411 	key = DUK_HTHREAD_GET_STRING(thr, stridx);
17412 	DUK_ASSERT(key != NULL);
17413 
17414 	duk_push_hobject(thr, thr->builtins[builtin_idx]);
17415 	duk_hobject_define_property_internal(thr, obj, key, desc_flags);
17416 	/* value popped by call */
17417 }
17418 #endif
17419 
17420 /* This is a rare property helper; it sets the global thrower (E5 Section 13.2.3)
17421  * setter/getter into an object property.  This is needed by the 'arguments'
17422  * object creation code, function instance creation code, and Function.prototype.bind().
17423  */
17424 
duk_xdef_prop_stridx_thrower(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)17425 DUK_INTERNAL void duk_xdef_prop_stridx_thrower(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
17426 	DUK_ASSERT_API_ENTRY(thr);
17427 
17428 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17429 	duk_push_hstring_stridx(thr, stridx);
17430 	duk_push_hobject_bidx(thr, DUK_BIDX_TYPE_ERROR_THROWER);
17431 	duk_dup_top(thr);
17432 	duk_def_prop(thr, obj_idx, DUK_DEFPROP_HAVE_SETTER | DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_FORCE);  /* attributes always 0 */
17433 }
17434 
17435 /* Object.getOwnPropertyDescriptor() equivalent C binding. */
duk_get_prop_desc(duk_hthread * thr,duk_idx_t obj_idx,duk_uint_t flags)17436 DUK_EXTERNAL void duk_get_prop_desc(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t flags) {
17437 	DUK_ASSERT_API_ENTRY(thr);
17438 	DUK_UNREF(flags);  /* no flags defined yet */
17439 
17440 	duk_hobject_object_get_own_property_descriptor(thr, obj_idx);  /* [ ... key ] -> [ ... desc ] */
17441 }
17442 
17443 /* Object.defineProperty() equivalent C binding. */
duk_def_prop(duk_hthread * thr,duk_idx_t obj_idx,duk_uint_t flags)17444 DUK_EXTERNAL void duk_def_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t flags) {
17445 	duk_idx_t idx_base;
17446 	duk_hobject *obj;
17447 	duk_hstring *key;
17448 	duk_idx_t idx_value;
17449 	duk_hobject *get;
17450 	duk_hobject *set;
17451 	duk_uint_t is_data_desc;
17452 	duk_uint_t is_acc_desc;
17453 
17454 	DUK_ASSERT_API_ENTRY(thr);
17455 
17456 	obj = duk_require_hobject(thr, obj_idx);
17457 
17458 	is_data_desc = flags & (DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE);
17459 	is_acc_desc = flags & (DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER);
17460 	if (is_data_desc && is_acc_desc) {
17461 		/* "Have" flags must not be conflicting so that they would
17462 		 * apply to both a plain property and an accessor at the same
17463 		 * time.
17464 		 */
17465 		goto fail_invalid_desc;
17466 	}
17467 
17468 	idx_base = duk_get_top_index(thr);
17469 	if (flags & DUK_DEFPROP_HAVE_SETTER) {
17470 		duk_require_type_mask(thr, idx_base, DUK_TYPE_MASK_UNDEFINED |
17471 		                                     DUK_TYPE_MASK_OBJECT |
17472 		                                     DUK_TYPE_MASK_LIGHTFUNC);
17473 		set = duk_get_hobject_promote_lfunc(thr, idx_base);
17474 		if (set != NULL && !DUK_HOBJECT_IS_CALLABLE(set)) {
17475 			goto fail_not_callable;
17476 		}
17477 		idx_base--;
17478 	} else {
17479 		set = NULL;
17480 	}
17481 	if (flags & DUK_DEFPROP_HAVE_GETTER) {
17482 		duk_require_type_mask(thr, idx_base, DUK_TYPE_MASK_UNDEFINED |
17483 		                                     DUK_TYPE_MASK_OBJECT |
17484 		                                     DUK_TYPE_MASK_LIGHTFUNC);
17485 		get = duk_get_hobject_promote_lfunc(thr, idx_base);
17486 		if (get != NULL && !DUK_HOBJECT_IS_CALLABLE(get)) {
17487 			goto fail_not_callable;
17488 		}
17489 		idx_base--;
17490 	} else {
17491 		get = NULL;
17492 	}
17493 	if (flags & DUK_DEFPROP_HAVE_VALUE) {
17494 		idx_value = idx_base;
17495 		idx_base--;
17496 	} else {
17497 		idx_value = (duk_idx_t) -1;
17498 	}
17499 	key = duk_to_property_key_hstring(thr, idx_base);
17500 	DUK_ASSERT(key != NULL);
17501 
17502 	duk_require_valid_index(thr, idx_base);
17503 
17504 	duk_hobject_define_property_helper(thr,
17505 	                                   flags /*defprop_flags*/,
17506 	                                   obj,
17507 	                                   key,
17508 	                                   idx_value,
17509 	                                   get,
17510 	                                   set,
17511 	                                   1 /*throw_flag*/);
17512 
17513 	/* Clean up stack */
17514 
17515 	duk_set_top(thr, idx_base);
17516 
17517 	/* [ ... obj ... ] */
17518 
17519 	return;
17520 
17521  fail_invalid_desc:
17522 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_DESCRIPTOR);
17523 	DUK_WO_NORETURN(return;);
17524 
17525  fail_not_callable:
17526 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);
17527 	DUK_WO_NORETURN(return;);
17528 }
17529 
17530 /*
17531  *  Object related
17532  */
17533 
duk_compact(duk_hthread * thr,duk_idx_t obj_idx)17534 DUK_EXTERNAL void duk_compact(duk_hthread *thr, duk_idx_t obj_idx) {
17535 	duk_hobject *obj;
17536 
17537 	DUK_ASSERT_API_ENTRY(thr);
17538 
17539 	obj = duk_get_hobject(thr, obj_idx);
17540 	if (obj) {
17541 		/* Note: this may fail, caller should protect the call if necessary */
17542 		duk_hobject_compact_props(thr, obj);
17543 	}
17544 }
17545 
duk_compact_m1(duk_hthread * thr)17546 DUK_INTERNAL void duk_compact_m1(duk_hthread *thr) {
17547 	DUK_ASSERT_API_ENTRY(thr);
17548 
17549 	duk_compact(thr, -1);
17550 }
17551 
17552 /* XXX: the duk_hobject_enum.c stack APIs should be reworked */
17553 
duk_enum(duk_hthread * thr,duk_idx_t obj_idx,duk_uint_t enum_flags)17554 DUK_EXTERNAL void duk_enum(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t enum_flags) {
17555 	DUK_ASSERT_API_ENTRY(thr);
17556 
17557 	duk_dup(thr, obj_idx);
17558 	duk_require_hobject_promote_mask(thr, -1, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
17559 	duk_hobject_enumerator_create(thr, enum_flags);   /* [target] -> [enum] */
17560 }
17561 
duk_next(duk_hthread * thr,duk_idx_t enum_index,duk_bool_t get_value)17562 DUK_EXTERNAL duk_bool_t duk_next(duk_hthread *thr, duk_idx_t enum_index, duk_bool_t get_value) {
17563 	DUK_ASSERT_API_ENTRY(thr);
17564 
17565 	duk_require_hobject(thr, enum_index);
17566 	duk_dup(thr, enum_index);
17567 	return duk_hobject_enumerator_next(thr, get_value);
17568 }
17569 
duk_seal_freeze_raw(duk_hthread * thr,duk_idx_t obj_idx,duk_bool_t is_freeze)17570 DUK_INTERNAL void duk_seal_freeze_raw(duk_hthread *thr, duk_idx_t obj_idx, duk_bool_t is_freeze) {
17571 	duk_tval *tv;
17572 	duk_hobject *h;
17573 
17574 	DUK_ASSERT_API_ENTRY(thr);
17575 
17576 	tv = duk_require_tval(thr, obj_idx);
17577 	DUK_ASSERT(tv != NULL);
17578 
17579 	/* Seal/freeze are quite rare in practice so it'd be nice to get the
17580 	 * correct behavior simply via automatic promotion (at the cost of some
17581 	 * memory churn).  However, the promoted objects don't behave the same,
17582 	 * e.g. promoted lightfuncs are extensible.
17583 	 */
17584 
17585 	switch (DUK_TVAL_GET_TAG(tv)) {
17586 	case DUK_TAG_BUFFER:
17587 		/* Plain buffer: already sealed, but not frozen (and can't be frozen
17588 		 * because index properties can't be made non-writable.
17589 		 */
17590 		if (is_freeze) {
17591 			goto fail_cannot_freeze;
17592 		}
17593 		break;
17594 	case DUK_TAG_LIGHTFUNC:
17595 		/* Lightfunc: already sealed and frozen, success. */
17596 		break;
17597 	case DUK_TAG_OBJECT:
17598 		h = DUK_TVAL_GET_OBJECT(tv);
17599 		DUK_ASSERT(h != NULL);
17600 		if (is_freeze && DUK_HOBJECT_IS_BUFOBJ(h)) {
17601 			/* Buffer objects cannot be frozen because there's no internal
17602 			 * support for making virtual array indices non-writable.
17603 			 */
17604 			DUK_DD(DUK_DDPRINT("cannot freeze a buffer object"));
17605 			goto fail_cannot_freeze;
17606 		}
17607 		duk_hobject_object_seal_freeze_helper(thr, h, is_freeze);
17608 
17609 		/* Sealed and frozen objects cannot gain any more properties,
17610 		 * so this is a good time to compact them.
17611 		 */
17612 		duk_hobject_compact_props(thr, h);
17613 		break;
17614 	default:
17615 		/* ES2015 Sections 19.1.2.5, 19.1.2.17 */
17616 		break;
17617 	}
17618 	return;
17619 
17620  fail_cannot_freeze:
17621 	DUK_ERROR_TYPE_INVALID_ARGS(thr);  /* XXX: proper error message */
17622 	DUK_WO_NORETURN(return;);
17623 }
17624 
duk_seal(duk_hthread * thr,duk_idx_t obj_idx)17625 DUK_EXTERNAL void duk_seal(duk_hthread *thr, duk_idx_t obj_idx) {
17626 	DUK_ASSERT_API_ENTRY(thr);
17627 
17628 	duk_seal_freeze_raw(thr, obj_idx, 0 /*is_freeze*/);
17629 }
17630 
duk_freeze(duk_hthread * thr,duk_idx_t obj_idx)17631 DUK_EXTERNAL void duk_freeze(duk_hthread *thr, duk_idx_t obj_idx) {
17632 	DUK_ASSERT_API_ENTRY(thr);
17633 
17634 	duk_seal_freeze_raw(thr, obj_idx, 1 /*is_freeze*/);
17635 }
17636 
17637 /*
17638  *  Helpers for writing multiple properties
17639  */
17640 
duk_put_function_list(duk_hthread * thr,duk_idx_t obj_idx,const duk_function_list_entry * funcs)17641 DUK_EXTERNAL void duk_put_function_list(duk_hthread *thr, duk_idx_t obj_idx, const duk_function_list_entry *funcs) {
17642 	const duk_function_list_entry *ent = funcs;
17643 
17644 	DUK_ASSERT_API_ENTRY(thr);
17645 
17646 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17647 	if (ent != NULL) {
17648 		while (ent->key != NULL) {
17649 			duk_push_c_function(thr, ent->value, ent->nargs);
17650 			duk_put_prop_string(thr, obj_idx, ent->key);
17651 			ent++;
17652 		}
17653 	}
17654 }
17655 
duk_put_number_list(duk_hthread * thr,duk_idx_t obj_idx,const duk_number_list_entry * numbers)17656 DUK_EXTERNAL void duk_put_number_list(duk_hthread *thr, duk_idx_t obj_idx, const duk_number_list_entry *numbers) {
17657 	const duk_number_list_entry *ent = numbers;
17658 	duk_tval *tv;
17659 
17660 	DUK_ASSERT_API_ENTRY(thr);
17661 
17662 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17663 	if (ent != NULL) {
17664 		while (ent->key != NULL) {
17665 			tv = thr->valstack_top++;
17666 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));  /* value stack init policy */
17667 			DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv, ent->value);  /* no need for decref/incref */
17668 			duk_put_prop_string(thr, obj_idx, ent->key);
17669 			ent++;
17670 		}
17671 	}
17672 }
17673 
17674 /*
17675  *  Shortcut for accessing global object properties
17676  */
17677 
duk_get_global_string(duk_hthread * thr,const char * key)17678 DUK_EXTERNAL duk_bool_t duk_get_global_string(duk_hthread *thr, const char *key) {
17679 	duk_bool_t ret;
17680 
17681 	DUK_ASSERT_API_ENTRY(thr);
17682 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17683 
17684 	/* XXX: direct implementation */
17685 
17686 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17687 	ret = duk_get_prop_string(thr, -1, key);
17688 	duk_remove_m2(thr);
17689 	return ret;
17690 }
17691 
duk_get_global_lstring(duk_hthread * thr,const char * key,duk_size_t key_len)17692 DUK_EXTERNAL duk_bool_t duk_get_global_lstring(duk_hthread *thr, const char *key, duk_size_t key_len) {
17693 	duk_bool_t ret;
17694 
17695 	DUK_ASSERT_API_ENTRY(thr);
17696 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17697 
17698 	/* XXX: direct implementation */
17699 
17700 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17701 	ret = duk_get_prop_lstring(thr, -1, key, key_len);
17702 	duk_remove_m2(thr);
17703 	return ret;
17704 }
17705 
17706 #if !defined(DUK_USE_PREFER_SIZE)
duk_get_global_literal_raw(duk_hthread * thr,const char * key,duk_size_t key_len)17707 DUK_EXTERNAL duk_bool_t duk_get_global_literal_raw(duk_hthread *thr, const char *key, duk_size_t key_len) {
17708 	duk_bool_t ret;
17709 
17710 	DUK_ASSERT_API_ENTRY(thr);
17711 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17712 	DUK_ASSERT(key[key_len] == (char) 0);
17713 
17714 	/* XXX: direct implementation */
17715 
17716 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17717 	ret = duk_get_prop_literal_raw(thr, -1, key, key_len);
17718 	duk_remove_m2(thr);
17719 	return ret;
17720 }
17721 #endif
17722 
duk_get_global_heapptr(duk_hthread * thr,void * ptr)17723 DUK_EXTERNAL duk_bool_t duk_get_global_heapptr(duk_hthread *thr, void *ptr) {
17724 	duk_bool_t ret;
17725 
17726 	DUK_ASSERT_API_ENTRY(thr);
17727 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17728 
17729 	/* XXX: direct implementation */
17730 
17731 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17732 	ret = duk_get_prop_heapptr(thr, -1, ptr);
17733 	duk_remove_m2(thr);
17734 	return ret;
17735 }
17736 
17737 
duk_put_global_string(duk_hthread * thr,const char * key)17738 DUK_EXTERNAL duk_bool_t duk_put_global_string(duk_hthread *thr, const char *key) {
17739 	duk_bool_t ret;
17740 
17741 	DUK_ASSERT_API_ENTRY(thr);
17742 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17743 
17744 	/* XXX: direct implementation */
17745 
17746 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17747 	duk_insert(thr, -2);
17748 	ret = duk_put_prop_string(thr, -2, key);  /* [ ... global val ] -> [ ... global ] */
17749 	duk_pop(thr);
17750 	return ret;
17751 }
17752 
duk_put_global_lstring(duk_hthread * thr,const char * key,duk_size_t key_len)17753 DUK_EXTERNAL duk_bool_t duk_put_global_lstring(duk_hthread *thr, const char *key, duk_size_t key_len) {
17754 	duk_bool_t ret;
17755 
17756 	DUK_ASSERT_API_ENTRY(thr);
17757 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17758 
17759 	/* XXX: direct implementation */
17760 
17761 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17762 	duk_insert(thr, -2);
17763 	ret = duk_put_prop_lstring(thr, -2, key, key_len);  /* [ ... global val ] -> [ ... global ] */
17764 	duk_pop(thr);
17765 	return ret;
17766 }
17767 
17768 #if !defined(DUK_USE_PREFER_SIZE)
duk_put_global_literal_raw(duk_hthread * thr,const char * key,duk_size_t key_len)17769 DUK_EXTERNAL duk_bool_t duk_put_global_literal_raw(duk_hthread *thr, const char *key, duk_size_t key_len) {
17770 	duk_bool_t ret;
17771 
17772 	DUK_ASSERT_API_ENTRY(thr);
17773 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17774 	DUK_ASSERT(key[key_len] == (char) 0);
17775 
17776 	/* XXX: direct implementation */
17777 
17778 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17779 	duk_insert(thr, -2);
17780 	ret = duk_put_prop_literal_raw(thr, -2, key, key_len);  /* [ ... global val ] -> [ ... global ] */
17781 	duk_pop(thr);
17782 	return ret;
17783 }
17784 #endif
17785 
duk_put_global_heapptr(duk_hthread * thr,void * ptr)17786 DUK_EXTERNAL duk_bool_t duk_put_global_heapptr(duk_hthread *thr, void *ptr) {
17787 	duk_bool_t ret;
17788 
17789 	DUK_ASSERT_API_ENTRY(thr);
17790 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17791 
17792 	/* XXX: direct implementation */
17793 
17794 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17795 	duk_insert(thr, -2);
17796 	ret = duk_put_prop_heapptr(thr, -2, ptr);  /* [ ... global val ] -> [ ... global ] */
17797 	duk_pop(thr);
17798 	return ret;
17799 }
17800 
17801 /*
17802  *  ES2015 GetMethod()
17803  */
17804 
duk_get_method_stridx(duk_hthread * thr,duk_idx_t idx,duk_small_uint_t stridx)17805 DUK_INTERNAL duk_bool_t duk_get_method_stridx(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t stridx) {
17806 	(void) duk_get_prop_stridx(thr, idx, stridx);
17807 	if (duk_is_null_or_undefined(thr, -1)) {
17808 		duk_pop_nodecref_unsafe(thr);
17809 		return 0;
17810 	}
17811 	if (!duk_is_callable(thr, -1)) {
17812 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);
17813 		DUK_WO_NORETURN(return 0;);
17814 	}
17815 	return 1;
17816 }
17817 
17818 /*
17819  *  Object prototype
17820  */
17821 
duk_get_prototype(duk_hthread * thr,duk_idx_t idx)17822 DUK_EXTERNAL void duk_get_prototype(duk_hthread *thr, duk_idx_t idx) {
17823 	duk_hobject *obj;
17824 	duk_hobject *proto;
17825 
17826 	DUK_ASSERT_API_ENTRY(thr);
17827 
17828 	obj = duk_require_hobject(thr, idx);
17829 	DUK_ASSERT(obj != NULL);
17830 
17831 	/* XXX: shared helper for duk_push_hobject_or_undefined()? */
17832 	proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, obj);
17833 	if (proto) {
17834 		duk_push_hobject(thr, proto);
17835 	} else {
17836 		duk_push_undefined(thr);
17837 	}
17838 }
17839 
duk_set_prototype(duk_hthread * thr,duk_idx_t idx)17840 DUK_EXTERNAL void duk_set_prototype(duk_hthread *thr, duk_idx_t idx) {
17841 	duk_hobject *obj;
17842 	duk_hobject *proto;
17843 
17844 	DUK_ASSERT_API_ENTRY(thr);
17845 
17846 	obj = duk_require_hobject(thr, idx);
17847 	DUK_ASSERT(obj != NULL);
17848 	duk_require_type_mask(thr, -1, DUK_TYPE_MASK_UNDEFINED |
17849 	                               DUK_TYPE_MASK_OBJECT);
17850 	proto = duk_get_hobject(thr, -1);
17851 	/* proto can also be NULL here (allowed explicitly) */
17852 
17853 #if defined(DUK_USE_ROM_OBJECTS)
17854 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
17855 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);  /* XXX: "read only object"? */
17856 		DUK_WO_NORETURN(return;);
17857 	}
17858 #endif
17859 
17860 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, obj, proto);
17861 
17862 	duk_pop(thr);
17863 }
17864 
duk_clear_prototype(duk_hthread * thr,duk_idx_t idx)17865 DUK_INTERNAL void duk_clear_prototype(duk_hthread *thr, duk_idx_t idx) {
17866 	duk_hobject *obj;
17867 
17868 	DUK_ASSERT_API_ENTRY(thr);
17869 
17870 	obj = duk_require_hobject(thr, idx);
17871 	DUK_ASSERT(obj != NULL);
17872 
17873 #if defined(DUK_USE_ROM_OBJECTS)
17874 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
17875 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);  /* XXX: "read only object"? */
17876 		DUK_WO_NORETURN(return;);
17877 	}
17878 #endif
17879 
17880 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, obj, NULL);
17881 }
17882 
duk_is_bare_object(duk_hthread * thr,duk_idx_t idx)17883 DUK_INTERNAL duk_bool_t duk_is_bare_object(duk_hthread *thr, duk_idx_t idx) {
17884 	duk_hobject *obj;
17885 	duk_hobject *proto;
17886 
17887 	DUK_ASSERT_API_ENTRY(thr);
17888 
17889 	obj = duk_require_hobject(thr, idx);
17890 	DUK_ASSERT(obj != NULL);
17891 
17892 	proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, obj);
17893 	return (proto == NULL);
17894 }
17895 
17896 /*
17897  *  Object finalizer
17898  */
17899 
17900 #if defined(DUK_USE_FINALIZER_SUPPORT)
17901 /* XXX: these could be implemented as macros calling an internal function
17902  * directly.
17903  * XXX: same issue as with Duktape.fin: there's no way to delete the property
17904  * now (just set it to undefined).
17905  */
duk_get_finalizer(duk_hthread * thr,duk_idx_t idx)17906 DUK_EXTERNAL void duk_get_finalizer(duk_hthread *thr, duk_idx_t idx) {
17907 	DUK_ASSERT_API_ENTRY(thr);
17908 
17909 	/* This get intentionally walks the inheritance chain at present,
17910 	 * which matches how the effective finalizer property is also
17911 	 * looked up in GC.
17912 	 */
17913 	duk_get_prop_stridx(thr, idx, DUK_STRIDX_INT_FINALIZER);
17914 }
17915 
duk_set_finalizer(duk_hthread * thr,duk_idx_t idx)17916 DUK_EXTERNAL void duk_set_finalizer(duk_hthread *thr, duk_idx_t idx) {
17917 	duk_hobject *h;
17918 	duk_bool_t callable;
17919 
17920 	DUK_ASSERT_API_ENTRY(thr);
17921 
17922 	h = duk_require_hobject(thr, idx);  /* Get before 'put' so that 'idx' is correct. */
17923 	callable = duk_is_callable(thr, -1);
17924 
17925 	/* At present finalizer is stored as a hidden Symbol, with normal
17926 	 * inheritance and access control.  As a result, finalizer cannot
17927 	 * currently be set on a non-extensible (sealed or frozen) object.
17928 	 * It might be useful to allow it.
17929 	 */
17930 	duk_put_prop_stridx(thr, idx, DUK_STRIDX_INT_FINALIZER);
17931 
17932 	/* In addition to setting the finalizer property, keep a "have
17933 	 * finalizer" flag in duk_hobject in sync so that refzero can do
17934 	 * a very quick finalizer check by walking the prototype chain
17935 	 * and checking the flag alone.  (Note that this means that just
17936 	 * setting _Finalizer on an object won't affect finalizer checks.)
17937 	 *
17938 	 * NOTE: if the argument is a Proxy object, this flag will be set
17939 	 * on the Proxy, not the target.  As a result, the target won't get
17940 	 * a finalizer flag and the Proxy also won't be finalized as there's
17941 	 * an explicit Proxy check in finalization now.
17942 	 */
17943 	if (callable) {
17944 		DUK_HOBJECT_SET_HAVE_FINALIZER(h);
17945 	} else {
17946 		DUK_HOBJECT_CLEAR_HAVE_FINALIZER(h);
17947 	}
17948 }
17949 #else  /* DUK_USE_FINALIZER_SUPPORT */
duk_get_finalizer(duk_hthread * thr,duk_idx_t idx)17950 DUK_EXTERNAL void duk_get_finalizer(duk_hthread *thr, duk_idx_t idx) {
17951 	DUK_ASSERT_API_ENTRY(thr);
17952 	DUK_UNREF(idx);
17953 	DUK_ERROR_UNSUPPORTED(thr);
17954 	DUK_WO_NORETURN(return;);
17955 }
17956 
duk_set_finalizer(duk_hthread * thr,duk_idx_t idx)17957 DUK_EXTERNAL void duk_set_finalizer(duk_hthread *thr, duk_idx_t idx) {
17958 	DUK_ASSERT_API_ENTRY(thr);
17959 	DUK_UNREF(idx);
17960 	DUK_ERROR_UNSUPPORTED(thr);
17961 	DUK_WO_NORETURN(return;);
17962 }
17963 #endif  /* DUK_USE_FINALIZER_SUPPORT */
17964 /*
17965  *  Random numbers
17966  */
17967 
17968 /* #include duk_internal.h -> already included */
17969 
duk_random(duk_hthread * thr)17970 DUK_EXTERNAL duk_double_t duk_random(duk_hthread *thr) {
17971 	return (duk_double_t) DUK_UTIL_GET_RANDOM_DOUBLE(thr);
17972 }
17973 /*
17974  *  API calls related to general value stack manipulation: resizing the value
17975  *  stack, pushing and popping values, type checking and reading values,
17976  *  coercing values, etc.
17977  *
17978  *  Also contains internal functions (such as duk_get_tval()), defined
17979  *  in duk_api_internal.h, with semantics similar to the public API.
17980  */
17981 
17982 /* XXX: repetition of stack pre-checks -> helper or macro or inline */
17983 /* XXX: shared api error strings, and perhaps even throw code for rare cases? */
17984 
17985 /* #include duk_internal.h -> already included */
17986 
17987 /*
17988  *  Forward declarations
17989  */
17990 
17991 DUK_LOCAL_DECL duk_idx_t duk__push_c_function_raw(duk_hthread *thr, duk_c_function func, duk_idx_t nargs, duk_uint_t flags, duk_small_uint_t proto_bidx);
17992 
17993 /*
17994  *  Global state for working around missing variadic macros
17995  */
17996 
17997 #if !defined(DUK_USE_VARIADIC_MACROS)
17998 DUK_EXTERNAL const char *duk_api_global_filename = NULL;
17999 DUK_EXTERNAL duk_int_t duk_api_global_line = 0;
18000 #endif
18001 
18002 /*
18003  *  Misc helpers
18004  */
18005 
18006 DUK_LOCAL const char * const duk__symbol_type_strings[4] = {
18007 	"hidden", "global", "local", "wellknown"
18008 };
18009 
18010 #if !defined(DUK_USE_PACKED_TVAL)
18011 DUK_LOCAL const duk_uint_t duk__type_from_tag[] = {
18012 	DUK_TYPE_NUMBER,
18013 	DUK_TYPE_NUMBER,  /* fastint */
18014 	DUK_TYPE_UNDEFINED,
18015 	DUK_TYPE_NULL,
18016 	DUK_TYPE_BOOLEAN,
18017 	DUK_TYPE_POINTER,
18018 	DUK_TYPE_LIGHTFUNC,
18019 	DUK_TYPE_NONE,
18020 	DUK_TYPE_STRING,
18021 	DUK_TYPE_OBJECT,
18022 	DUK_TYPE_BUFFER,
18023 };
18024 DUK_LOCAL const duk_uint_t duk__type_mask_from_tag[] = {
18025 	DUK_TYPE_MASK_NUMBER,
18026 	DUK_TYPE_MASK_NUMBER,  /* fastint */
18027 	DUK_TYPE_MASK_UNDEFINED,
18028 	DUK_TYPE_MASK_NULL,
18029 	DUK_TYPE_MASK_BOOLEAN,
18030 	DUK_TYPE_MASK_POINTER,
18031 	DUK_TYPE_MASK_LIGHTFUNC,
18032 	DUK_TYPE_MASK_NONE,
18033 	DUK_TYPE_MASK_STRING,
18034 	DUK_TYPE_MASK_OBJECT,
18035 	DUK_TYPE_MASK_BUFFER,
18036 };
18037 #endif  /* !DUK_USE_PACKED_TVAL */
18038 
18039 /* Assert that there's room for one value. */
18040 #define DUK__ASSERT_SPACE() do { \
18041 		DUK_ASSERT(!(thr->valstack_top >= thr->valstack_end)); \
18042 	} while (0)
18043 
18044 /* Check that there's room to push one value. */
18045 #if defined(DUK_USE_VALSTACK_UNSAFE)
18046 /* Faster but value stack overruns are memory unsafe. */
18047 #define DUK__CHECK_SPACE() DUK__ASSERT_SPACE()
18048 #else
18049 #define DUK__CHECK_SPACE() do { \
18050 		if (DUK_UNLIKELY(thr->valstack_top >= thr->valstack_end)) { \
18051 			DUK_ERROR_RANGE_PUSH_BEYOND(thr); \
18052 		} \
18053 	} while (0)
18054 #endif
18055 
duk__get_symbol_type(duk_hstring * h)18056 DUK_LOCAL duk_small_uint_t duk__get_symbol_type(duk_hstring *h) {
18057 	const duk_uint8_t *data;
18058 	duk_size_t len;
18059 
18060 	DUK_ASSERT(h != NULL);
18061 	DUK_ASSERT(DUK_HSTRING_HAS_SYMBOL(h));
18062 	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(h) >= 1);  /* always true, symbol prefix */
18063 
18064 	data = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
18065 	len = DUK_HSTRING_GET_BYTELEN(h);
18066 	DUK_ASSERT(len >= 1);
18067 
18068 	/* XXX: differentiate between 0x82 and 0xff (hidden vs. internal?)? */
18069 
18070 	if (data[0] == 0xffU) {
18071 		return DUK_SYMBOL_TYPE_HIDDEN;
18072 	} else if (data[0] == 0x82U) {
18073 		return DUK_SYMBOL_TYPE_HIDDEN;
18074 	} else if (data[0] == 0x80U) {
18075 		return DUK_SYMBOL_TYPE_GLOBAL;
18076 	} else if (data[len - 1] != 0xffU) {
18077 		return DUK_SYMBOL_TYPE_LOCAL;
18078 	} else {
18079 		return DUK_SYMBOL_TYPE_WELLKNOWN;
18080 	}
18081 }
18082 
duk__get_symbol_type_string(duk_hstring * h)18083 DUK_LOCAL const char *duk__get_symbol_type_string(duk_hstring *h) {
18084 	duk_small_uint_t idx;
18085 	idx = duk__get_symbol_type(h);
18086 	DUK_ASSERT(idx < sizeof(duk__symbol_type_strings));
18087 	return duk__symbol_type_strings[idx];
18088 }
18089 
18090 DUK_LOCAL_DECL duk_heaphdr *duk__get_tagged_heaphdr_raw(duk_hthread *thr, duk_idx_t idx, duk_uint_t tag);
18091 
duk__api_coerce_d2i(duk_hthread * thr,duk_idx_t idx,duk_int_t def_value,duk_bool_t require)18092 DUK_LOCAL duk_int_t duk__api_coerce_d2i(duk_hthread *thr, duk_idx_t idx, duk_int_t def_value, duk_bool_t require) {
18093 	duk_tval *tv;
18094 	duk_small_int_t c;
18095 	duk_double_t d;
18096 
18097 	tv = duk_get_tval_or_unused(thr, idx);
18098 	DUK_ASSERT(tv != NULL);
18099 
18100 	/*
18101 	 *  Special cases like NaN and +/- Infinity are handled explicitly
18102 	 *  because a plain C coercion from double to int handles these cases
18103 	 *  in undesirable ways.  For instance, NaN may coerce to INT_MIN
18104 	 *  (not zero), and INT_MAX + 1 may coerce to INT_MIN (not INT_MAX).
18105 	 *
18106 	 *  This double-to-int coercion differs from ToInteger() because it
18107 	 *  has a finite range (ToInteger() allows e.g. +/- Infinity).  It
18108 	 *  also differs from ToInt32() because the INT_MIN/INT_MAX clamping
18109 	 *  depends on the size of the int type on the platform.  In particular,
18110 	 *  on platforms with a 64-bit int type, the full range is allowed.
18111 	 */
18112 
18113 #if defined(DUK_USE_FASTINT)
18114 	if (DUK_TVAL_IS_FASTINT(tv)) {
18115 		duk_int64_t t = DUK_TVAL_GET_FASTINT(tv);
18116 #if (DUK_INT_MAX <= 0x7fffffffL)
18117 		/* Clamping only necessary for 32-bit ints. */
18118 		if (t < DUK_INT_MIN) {
18119 			t = DUK_INT_MIN;
18120 		} else if (t > DUK_INT_MAX) {
18121 			t = DUK_INT_MAX;
18122 		}
18123 #endif
18124 		return (duk_int_t) t;
18125 	}
18126 #endif
18127 
18128 	if (DUK_TVAL_IS_NUMBER(tv)) {
18129 		d = DUK_TVAL_GET_NUMBER(tv);
18130 		c = (duk_small_int_t) DUK_FPCLASSIFY(d);
18131 		if (c == DUK_FP_NAN) {
18132 			return 0;
18133 		} else if (d < (duk_double_t) DUK_INT_MIN) {
18134 			/* covers -Infinity */
18135 			return DUK_INT_MIN;
18136 		} else if (d > (duk_double_t) DUK_INT_MAX) {
18137 			/* covers +Infinity */
18138 			return DUK_INT_MAX;
18139 		} else {
18140 			/* coerce towards zero */
18141 			return (duk_int_t) d;
18142 		}
18143 	}
18144 
18145 	if (require) {
18146 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "number", DUK_STR_NOT_NUMBER);
18147 		DUK_WO_NORETURN(return 0;);
18148 	}
18149 
18150 	return def_value;
18151 }
18152 
duk__api_coerce_d2ui(duk_hthread * thr,duk_idx_t idx,duk_uint_t def_value,duk_bool_t require)18153 DUK_LOCAL duk_uint_t duk__api_coerce_d2ui(duk_hthread *thr, duk_idx_t idx, duk_uint_t def_value, duk_bool_t require) {
18154 	duk_tval *tv;
18155 	duk_small_int_t c;
18156 	duk_double_t d;
18157 
18158 	/* Same as above but for unsigned int range. */
18159 
18160 	tv = duk_get_tval_or_unused(thr, idx);
18161 	DUK_ASSERT(tv != NULL);
18162 
18163 #if defined(DUK_USE_FASTINT)
18164 	if (DUK_TVAL_IS_FASTINT(tv)) {
18165 		duk_int64_t t = DUK_TVAL_GET_FASTINT(tv);
18166 		if (t < 0) {
18167 			t = 0;
18168 		}
18169 #if (DUK_UINT_MAX <= 0xffffffffUL)
18170 		/* Clamping only necessary for 32-bit ints. */
18171 		else if (t > DUK_UINT_MAX) {
18172 			t = DUK_UINT_MAX;
18173 		}
18174 #endif
18175 		return (duk_uint_t) t;
18176 	}
18177 #endif
18178 
18179 	if (DUK_TVAL_IS_NUMBER(tv)) {
18180 		d = DUK_TVAL_GET_NUMBER(tv);
18181 		c = (duk_small_int_t) DUK_FPCLASSIFY(d);
18182 		if (c == DUK_FP_NAN) {
18183 			return 0;
18184 		} else if (d < 0.0) {
18185 			/* covers -Infinity */
18186 			return (duk_uint_t) 0;
18187 		} else if (d > (duk_double_t) DUK_UINT_MAX) {
18188 			/* covers +Infinity */
18189 			return (duk_uint_t) DUK_UINT_MAX;
18190 		} else {
18191 			/* coerce towards zero */
18192 			return (duk_uint_t) d;
18193 		}
18194 	}
18195 
18196 	if (require) {
18197 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "number", DUK_STR_NOT_NUMBER);
18198 		DUK_WO_NORETURN(return 0;);
18199 	}
18200 
18201 	return def_value;
18202 }
18203 
18204 /*
18205  *  Stack index validation/normalization and getting a stack duk_tval ptr.
18206  *
18207  *  These are called by many API entrypoints so the implementations must be
18208  *  fast and "inlined".
18209  *
18210  *  There's some repetition because of this; keep the functions in sync.
18211  */
18212 
duk_normalize_index(duk_hthread * thr,duk_idx_t idx)18213 DUK_EXTERNAL duk_idx_t duk_normalize_index(duk_hthread *thr, duk_idx_t idx) {
18214 	duk_uidx_t vs_size;
18215 	duk_uidx_t uidx;
18216 
18217 	DUK_ASSERT_API_ENTRY(thr);
18218 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
18219 
18220 	/* Care must be taken to avoid pointer wrapping in the index
18221 	 * validation.  For instance, on a 32-bit platform with 8-byte
18222 	 * duk_tval the index 0x20000000UL would wrap the memory space
18223 	 * once.
18224 	 */
18225 
18226 	/* Assume value stack sizes (in elements) fits into duk_idx_t. */
18227 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
18228 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
18229 	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
18230 
18231 	if (idx < 0) {
18232 		uidx = vs_size + (duk_uidx_t) idx;
18233 	} else {
18234 		/* since index non-negative */
18235 		DUK_ASSERT(idx != DUK_INVALID_INDEX);
18236 		uidx = (duk_uidx_t) idx;
18237 	}
18238 
18239 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
18240 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
18241 
18242 	if (DUK_LIKELY(uidx < vs_size)) {
18243 		return (duk_idx_t) uidx;
18244 	}
18245 	return DUK_INVALID_INDEX;
18246 }
18247 
duk_require_normalize_index(duk_hthread * thr,duk_idx_t idx)18248 DUK_EXTERNAL duk_idx_t duk_require_normalize_index(duk_hthread *thr, duk_idx_t idx) {
18249 	duk_uidx_t vs_size;
18250 	duk_uidx_t uidx;
18251 
18252 	DUK_ASSERT_API_ENTRY(thr);
18253 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
18254 
18255 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
18256 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
18257 	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
18258 
18259 	if (idx < 0) {
18260 		uidx = vs_size + (duk_uidx_t) idx;
18261 	} else {
18262 		DUK_ASSERT(idx != DUK_INVALID_INDEX);
18263 		uidx = (duk_uidx_t) idx;
18264 	}
18265 
18266 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
18267 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
18268 
18269 	if (DUK_LIKELY(uidx < vs_size)) {
18270 		return (duk_idx_t) uidx;
18271 	}
18272 	DUK_ERROR_RANGE_INDEX(thr, idx);
18273 	DUK_WO_NORETURN(return 0;);
18274 }
18275 
duk_get_tval(duk_hthread * thr,duk_idx_t idx)18276 DUK_INTERNAL duk_tval *duk_get_tval(duk_hthread *thr, duk_idx_t idx) {
18277 	duk_uidx_t vs_size;
18278 	duk_uidx_t uidx;
18279 
18280 	DUK_ASSERT_API_ENTRY(thr);
18281 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
18282 
18283 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
18284 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
18285 	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
18286 
18287 	if (idx < 0) {
18288 		uidx = vs_size + (duk_uidx_t) idx;
18289 	} else {
18290 		DUK_ASSERT(idx != DUK_INVALID_INDEX);
18291 		uidx = (duk_uidx_t) idx;
18292 	}
18293 
18294 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
18295 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
18296 
18297 	if (DUK_LIKELY(uidx < vs_size)) {
18298 		return thr->valstack_bottom + uidx;
18299 	}
18300 	return NULL;
18301 }
18302 
18303 /* Variant of duk_get_tval() which is guaranteed to return a valid duk_tval
18304  * pointer.  When duk_get_tval() would return NULL, this variant returns a
18305  * pointer to a duk_tval with tag DUK_TAG_UNUSED.  This allows the call site
18306  * to avoid an unnecessary NULL check which sometimes leads to better code.
18307  * The return duk_tval is read only (at least for the UNUSED value).
18308  */
18309 DUK_LOCAL const duk_tval_unused duk__const_tval_unused = DUK_TVAL_UNUSED_INITIALIZER();
18310 
duk_get_tval_or_unused(duk_hthread * thr,duk_idx_t idx)18311 DUK_INTERNAL duk_tval *duk_get_tval_or_unused(duk_hthread *thr, duk_idx_t idx) {
18312 	duk_tval *tv;
18313 
18314 	DUK_ASSERT_API_ENTRY(thr);
18315 
18316 	tv = duk_get_tval(thr, idx);
18317 	if (tv != NULL) {
18318 		return tv;
18319 	}
18320 	return (duk_tval *) DUK_LOSE_CONST(&duk__const_tval_unused);
18321 }
18322 
duk_require_tval(duk_hthread * thr,duk_idx_t idx)18323 DUK_INTERNAL duk_tval *duk_require_tval(duk_hthread *thr, duk_idx_t idx) {
18324 	duk_uidx_t vs_size;
18325 	duk_uidx_t uidx;
18326 
18327 	DUK_ASSERT_API_ENTRY(thr);
18328 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
18329 
18330 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
18331 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
18332 	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
18333 
18334 	/* Use unsigned arithmetic to optimize comparison. */
18335 	if (idx < 0) {
18336 		uidx = vs_size + (duk_uidx_t) idx;
18337 	} else {
18338 		DUK_ASSERT(idx != DUK_INVALID_INDEX);
18339 		uidx = (duk_uidx_t) idx;
18340 	}
18341 
18342 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
18343 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
18344 
18345 	if (DUK_LIKELY(uidx < vs_size)) {
18346 		return thr->valstack_bottom + uidx;
18347 	}
18348 	DUK_ERROR_RANGE_INDEX(thr, idx);
18349 	DUK_WO_NORETURN(return NULL;);
18350 }
18351 
18352 /* Non-critical. */
duk_is_valid_index(duk_hthread * thr,duk_idx_t idx)18353 DUK_EXTERNAL duk_bool_t duk_is_valid_index(duk_hthread *thr, duk_idx_t idx) {
18354 	DUK_ASSERT_API_ENTRY(thr);
18355 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
18356 
18357 	return (duk_normalize_index(thr, idx) >= 0);
18358 }
18359 
18360 /* Non-critical. */
duk_require_valid_index(duk_hthread * thr,duk_idx_t idx)18361 DUK_EXTERNAL void duk_require_valid_index(duk_hthread *thr, duk_idx_t idx) {
18362 	DUK_ASSERT_API_ENTRY(thr);
18363 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
18364 
18365 	if (DUK_UNLIKELY(duk_normalize_index(thr, idx) < 0)) {
18366 		DUK_ERROR_RANGE_INDEX(thr, idx);
18367 		DUK_WO_NORETURN(return;);
18368 	}
18369 }
18370 
18371 /*
18372  *  Value stack top handling
18373  */
18374 
duk_get_top(duk_hthread * thr)18375 DUK_EXTERNAL duk_idx_t duk_get_top(duk_hthread *thr) {
18376 	DUK_ASSERT_API_ENTRY(thr);
18377 
18378 	return (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
18379 }
18380 
18381 /* Internal helper to get current top but to require a minimum top value
18382  * (TypeError if not met).
18383  */
duk_get_top_require_min(duk_hthread * thr,duk_idx_t min_top)18384 DUK_INTERNAL duk_idx_t duk_get_top_require_min(duk_hthread *thr, duk_idx_t min_top) {
18385 	duk_idx_t ret;
18386 
18387 	DUK_ASSERT_API_ENTRY(thr);
18388 
18389 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
18390 	if (DUK_UNLIKELY(ret < min_top)) {
18391 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
18392 		DUK_WO_NORETURN(return 0;);
18393 	}
18394 	return ret;
18395 }
18396 
18397 /* Set stack top within currently allocated range, but don't reallocate.
18398  * This is performance critical especially for call handling, so whenever
18399  * changing, profile and look at generated code.
18400  */
duk_set_top(duk_hthread * thr,duk_idx_t idx)18401 DUK_EXTERNAL void duk_set_top(duk_hthread *thr, duk_idx_t idx) {
18402 	duk_uidx_t vs_size;
18403 	duk_uidx_t vs_limit;
18404 	duk_uidx_t uidx;
18405 	duk_tval *tv;
18406 
18407 	DUK_ASSERT_API_ENTRY(thr);
18408 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
18409 
18410 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
18411 	DUK_ASSERT(thr->valstack_end >= thr->valstack_bottom);
18412 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
18413 	vs_limit = (duk_uidx_t) (thr->valstack_end - thr->valstack_bottom);
18414 
18415 	if (idx < 0) {
18416 		/* Negative indices are always within allocated stack but
18417 		 * must not go below zero index.
18418 		 */
18419 		uidx = vs_size + (duk_uidx_t) idx;
18420 	} else {
18421 		/* Positive index can be higher than valstack top but must
18422 		 * not go above allocated stack (equality is OK).
18423 		 */
18424 		uidx = (duk_uidx_t) idx;
18425 	}
18426 
18427 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
18428 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
18429 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_limit);
18430 
18431 #if defined(DUK_USE_VALSTACK_UNSAFE)
18432 	DUK_ASSERT(uidx <= vs_limit);
18433 	DUK_UNREF(vs_limit);
18434 #else
18435 	if (DUK_UNLIKELY(uidx > vs_limit)) {
18436 		DUK_ERROR_RANGE_INDEX(thr, idx);
18437 		DUK_WO_NORETURN(return;);
18438 	}
18439 #endif
18440 	DUK_ASSERT(uidx <= vs_limit);
18441 
18442 	/* Handle change in value stack top.  Respect value stack
18443 	 * initialization policy: 'undefined' above top.  Note that
18444 	 * DECREF may cause a side effect that reallocates valstack,
18445 	 * so must relookup after DECREF.
18446 	 */
18447 
18448 	if (uidx >= vs_size) {
18449 		/* Stack size increases or stays the same. */
18450 #if defined(DUK_USE_ASSERTIONS)
18451 		duk_uidx_t count;
18452 
18453 		count = uidx - vs_size;
18454 		while (count != 0) {
18455 			count--;
18456 			tv = thr->valstack_top + count;
18457 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
18458 		}
18459 #endif
18460 		thr->valstack_top = thr->valstack_bottom + uidx;
18461 	} else {
18462 		/* Stack size decreases. */
18463 #if defined(DUK_USE_REFERENCE_COUNTING)
18464 		duk_uidx_t count;
18465 		duk_tval *tv_end;
18466 
18467 		count = vs_size - uidx;
18468 		DUK_ASSERT(count > 0);
18469 		tv = thr->valstack_top;
18470 		tv_end = tv - count;
18471 		DUK_ASSERT(tv > tv_end);  /* Because count > 0. */
18472 		do {
18473 			tv--;
18474 			DUK_ASSERT(tv >= thr->valstack_bottom);
18475 			DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);
18476 		} while (tv != tv_end);
18477 		thr->valstack_top = tv_end;
18478 		DUK_REFZERO_CHECK_FAST(thr);
18479 #else  /* DUK_USE_REFERENCE_COUNTING */
18480 		duk_uidx_t count;
18481 		duk_tval *tv_end;
18482 
18483 		count = vs_size - uidx;
18484 		tv = thr->valstack_top;
18485 		tv_end = tv - count;
18486 		DUK_ASSERT(tv > tv_end);
18487 		do {
18488 			tv--;
18489 			DUK_TVAL_SET_UNDEFINED(tv);
18490 		} while (tv != tv_end);
18491 		thr->valstack_top = tv_end;
18492 #endif  /* DUK_USE_REFERENCE_COUNTING */
18493 	}
18494 }
18495 
18496 /* Internal variant with a non-negative index and no runtime size checks. */
18497 #if defined(DUK_USE_PREFER_SIZE)
duk_set_top_unsafe(duk_hthread * thr,duk_idx_t idx)18498 DUK_INTERNAL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx) {
18499 	DUK_ASSERT_API_ENTRY(thr);
18500 
18501 	duk_set_top(thr, idx);
18502 }
18503 #else  /* DUK_USE_PREFER_SIZE */
duk_set_top_unsafe(duk_hthread * thr,duk_idx_t idx)18504 DUK_INTERNAL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx) {
18505 	duk_uidx_t uidx;
18506 	duk_uidx_t vs_size;
18507 	duk_tval *tv;
18508 
18509 	DUK_ASSERT_API_ENTRY(thr);
18510 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
18511 	DUK_ASSERT(thr->valstack_end >= thr->valstack_bottom);
18512 	DUK_ASSERT(idx >= 0);
18513 	DUK_ASSERT(idx <= (duk_idx_t) (thr->valstack_end - thr->valstack_bottom));
18514 
18515 	/* XXX: byte arithmetic */
18516 	uidx = (duk_uidx_t) idx;
18517 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
18518 
18519 	if (uidx >= vs_size) {
18520 		/* Stack size increases or stays the same. */
18521 #if defined(DUK_USE_ASSERTIONS)
18522 		duk_uidx_t count;
18523 
18524 		count = uidx - vs_size;
18525 		while (count != 0) {
18526 			count--;
18527 			tv = thr->valstack_top + count;
18528 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
18529 		}
18530 #endif
18531 		thr->valstack_top = thr->valstack_bottom + uidx;
18532 	} else {
18533 		/* Stack size decreases. */
18534 #if defined(DUK_USE_REFERENCE_COUNTING)
18535 		duk_uidx_t count;
18536 		duk_tval *tv_end;
18537 
18538 		count = vs_size - uidx;
18539 		DUK_ASSERT(count > 0);
18540 		tv = thr->valstack_top;
18541 		tv_end = tv - count;
18542 		DUK_ASSERT(tv > tv_end);  /* Because count > 0. */
18543 		do {
18544 			tv--;
18545 			DUK_ASSERT(tv >= thr->valstack_bottom);
18546 			DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);
18547 		} while (tv != tv_end);
18548 		thr->valstack_top = tv_end;
18549 		DUK_REFZERO_CHECK_FAST(thr);
18550 #else  /* DUK_USE_REFERENCE_COUNTING */
18551 		duk_uidx_t count;
18552 		duk_tval *tv_end;
18553 
18554 		count = vs_size - uidx;
18555 		tv = thr->valstack_top;
18556 		tv_end = tv - count;
18557 		DUK_ASSERT(tv > tv_end);
18558 		do {
18559 			tv--;
18560 			DUK_TVAL_SET_UNDEFINED(tv);
18561 		} while (tv != tv_end);
18562 		thr->valstack_top = tv_end;
18563 #endif  /* DUK_USE_REFERENCE_COUNTING */
18564 	}
18565 }
18566 #endif  /* DUK_USE_PREFER_SIZE */
18567 
18568 /* Internal helper: set top to 'top', and set [idx_wipe_start,top[ to
18569  * 'undefined' (doing nothing if idx_wipe_start == top).  Indices are
18570  * positive and within value stack reserve.  This is used by call handling.
18571  */
duk_set_top_and_wipe(duk_hthread * thr,duk_idx_t top,duk_idx_t idx_wipe_start)18572 DUK_INTERNAL void duk_set_top_and_wipe(duk_hthread *thr, duk_idx_t top, duk_idx_t idx_wipe_start) {
18573 	DUK_ASSERT_API_ENTRY(thr);
18574 	DUK_ASSERT(top >= 0);
18575 	DUK_ASSERT(idx_wipe_start >= 0);
18576 	DUK_ASSERT(idx_wipe_start <= top);
18577 	DUK_ASSERT(thr->valstack_bottom + top <= thr->valstack_end);
18578 	DUK_ASSERT(thr->valstack_bottom + idx_wipe_start <= thr->valstack_end);
18579 
18580 	duk_set_top_unsafe(thr, idx_wipe_start);
18581 	duk_set_top_unsafe(thr, top);
18582 }
18583 
duk_get_top_index(duk_hthread * thr)18584 DUK_EXTERNAL duk_idx_t duk_get_top_index(duk_hthread *thr) {
18585 	duk_idx_t ret;
18586 
18587 	DUK_ASSERT_API_ENTRY(thr);
18588 
18589 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;
18590 	if (DUK_UNLIKELY(ret < 0)) {
18591 		/* Return invalid index; if caller uses this without checking
18592 		 * in another API call, the index won't map to a valid stack
18593 		 * entry.
18594 		 */
18595 		return DUK_INVALID_INDEX;
18596 	}
18597 	return ret;
18598 }
18599 
18600 /* Internal variant: call assumes there is at least one element on the value
18601  * stack frame; this is only asserted for.
18602  */
duk_get_top_index_unsafe(duk_hthread * thr)18603 DUK_INTERNAL duk_idx_t duk_get_top_index_unsafe(duk_hthread *thr) {
18604 	duk_idx_t ret;
18605 
18606 	DUK_ASSERT_API_ENTRY(thr);
18607 
18608 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;
18609 	return ret;
18610 }
18611 
duk_require_top_index(duk_hthread * thr)18612 DUK_EXTERNAL duk_idx_t duk_require_top_index(duk_hthread *thr) {
18613 	duk_idx_t ret;
18614 
18615 	DUK_ASSERT_API_ENTRY(thr);
18616 
18617 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;
18618 	if (DUK_UNLIKELY(ret < 0)) {
18619 		DUK_ERROR_RANGE_INDEX(thr, -1);
18620 		DUK_WO_NORETURN(return 0;);
18621 	}
18622 	return ret;
18623 }
18624 
18625 /*
18626  *  Value stack resizing.
18627  *
18628  *  This resizing happens above the current "top": the value stack can be
18629  *  grown or shrunk, but the "top" is not affected.  The value stack cannot
18630  *  be resized to a size below the current reserve.
18631  *
18632  *  The low level reallocation primitive must carefully recompute all value
18633  *  stack pointers, and must also work if ALL pointers are NULL.  The resize
18634  *  is quite tricky because the valstack realloc may cause a mark-and-sweep,
18635  *  which may run finalizers.  Running finalizers may resize the valstack
18636  *  recursively (the same value stack we're working on).  So, after realloc
18637  *  returns, we know that the valstack bottom, top, and reserve should still
18638  *  be the same (there should not be live values above the "top"), but its
18639  *  underlying size, alloc_end, and base pointer may have changed.
18640  *
18641  *  'new_size' is known to be <= DUK_USE_VALSTACK_LIMIT, which ensures that
18642  *  size_t and pointer arithmetic won't wrap in duk__resize_valstack().
18643  */
18644 
18645 /* Low level valstack resize primitive, used for both grow and shrink.  All
18646  * adjustments for slack etc have already been done.  Doesn't throw but does
18647  * have allocation side effects.
18648  */
duk__resize_valstack(duk_hthread * thr,duk_size_t new_size)18649 DUK_LOCAL DUK_COLD DUK_NOINLINE duk_bool_t duk__resize_valstack(duk_hthread *thr, duk_size_t new_size) {
18650 	duk_tval *pre_valstack;
18651 	duk_tval *pre_bottom;
18652 	duk_tval *pre_top;
18653 	duk_tval *pre_end;
18654 	duk_tval *pre_alloc_end;
18655 	duk_ptrdiff_t ptr_diff;
18656 	duk_tval *new_valstack;
18657 	duk_size_t new_alloc_size;
18658 	duk_tval *tv_prev_alloc_end;
18659 	duk_tval *p;
18660 
18661 	DUK_HTHREAD_ASSERT_VALID(thr);
18662 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
18663 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
18664 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
18665 	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);
18666 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) <= new_size);  /* can't resize below 'top' */
18667 	DUK_ASSERT(new_size <= DUK_USE_VALSTACK_LIMIT);  /* valstack limit caller has check, prevents wrapping */
18668 	DUK_ASSERT(new_size <= DUK_SIZE_MAX / sizeof(duk_tval));  /* specific assert for wrapping */
18669 
18670 	/* Pre-realloc pointer copies for asserts and debug logs. */
18671 	pre_valstack = thr->valstack;
18672 	pre_bottom = thr->valstack_bottom;
18673 	pre_top = thr->valstack_top;
18674 	pre_end = thr->valstack_end;
18675 	pre_alloc_end = thr->valstack_alloc_end;
18676 
18677 	DUK_UNREF(pre_valstack);
18678 	DUK_UNREF(pre_bottom);
18679 	DUK_UNREF(pre_top);
18680 	DUK_UNREF(pre_end);
18681 	DUK_UNREF(pre_alloc_end);
18682 
18683 	/* If finalizer torture enabled, force base pointer change every time
18684 	 * when it would be allowed.
18685 	 */
18686 #if defined(DUK_USE_FINALIZER_TORTURE)
18687 	if (thr->heap->pf_prevent_count == 0) {
18688 		duk_hthread_valstack_torture_realloc(thr);
18689 	}
18690 #endif
18691 
18692 	/* Allocate a new valstack using DUK_REALLOC_DIRECT() to deal with
18693 	 * a side effect changing the base pointer.
18694 	 */
18695 	new_alloc_size = sizeof(duk_tval) * new_size;
18696 	new_valstack = (duk_tval *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_valstack_ptr, (void *) thr, new_alloc_size);
18697 	if (DUK_UNLIKELY(new_valstack == NULL)) {
18698 		/* Because new_size != 0, if condition doesn't need to be
18699 		 * (new_valstack != NULL || new_size == 0).
18700 		 */
18701 		DUK_ASSERT(new_size != 0);
18702 		DUK_D(DUK_DPRINT("failed to resize valstack to %lu entries (%lu bytes)",
18703 		                 (unsigned long) new_size, (unsigned long) new_alloc_size));
18704 		return 0;
18705 	}
18706 
18707 	/* Debug log any changes in pointer(s) by side effects.  These don't
18708 	 * necessarily imply any incorrect behavior, but should be rare in
18709 	 * practice.
18710 	 */
18711 #if defined(DUK_USE_DEBUG)
18712 	if (thr->valstack != pre_valstack) {
18713 		DUK_D(DUK_DPRINT("valstack base pointer changed during valstack resize: %p -> %p",
18714 		                 (void *) pre_valstack, (void *) thr->valstack));
18715 	}
18716 	if (thr->valstack_bottom != pre_bottom) {
18717 		DUK_D(DUK_DPRINT("valstack bottom pointer changed during valstack resize: %p -> %p",
18718 		                 (void *) pre_bottom, (void *) thr->valstack_bottom));
18719 	}
18720 	if (thr->valstack_top != pre_top) {
18721 		DUK_D(DUK_DPRINT("valstack top pointer changed during valstack resize: %p -> %p",
18722 		                 (void *) pre_top, (void *) thr->valstack_top));
18723 	}
18724 	if (thr->valstack_end != pre_end) {
18725 		DUK_D(DUK_DPRINT("valstack end pointer changed during valstack resize: %p -> %p",
18726 		                 (void *) pre_end, (void *) thr->valstack_end));
18727 	}
18728 	if (thr->valstack_alloc_end != pre_alloc_end) {
18729 		DUK_D(DUK_DPRINT("valstack alloc_end pointer changed during valstack resize: %p -> %p",
18730 		                 (void *) pre_alloc_end, (void *) thr->valstack_alloc_end));
18731 	}
18732 #endif
18733 
18734 	/* Assertions: offsets for bottom, top, and end (reserve) must not
18735 	 * have changed even with side effects because they are always
18736 	 * restored in unwind.  For alloc_end there's no guarantee: it may
18737 	 * have grown or shrunk (but remain above 'end').
18738 	 */
18739 	DUK_ASSERT(thr->valstack_bottom - thr->valstack == pre_bottom - pre_valstack);
18740 	DUK_ASSERT(thr->valstack_top - thr->valstack == pre_top - pre_valstack);
18741 	DUK_ASSERT(thr->valstack_end - thr->valstack == pre_end - pre_valstack);
18742 	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);
18743 
18744 	/* Write new pointers.  Most pointers can be handled as a pointer
18745 	 * difference.
18746 	 */
18747 	ptr_diff = (duk_ptrdiff_t) ((duk_uint8_t *) new_valstack - (duk_uint8_t *) thr->valstack);
18748 	tv_prev_alloc_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_alloc_end + ptr_diff);
18749 	thr->valstack = new_valstack;
18750 	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + ptr_diff);
18751 	thr->valstack_top = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_top + ptr_diff);
18752 	thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_end + ptr_diff);
18753 	thr->valstack_alloc_end = (duk_tval *) (void *) ((duk_uint8_t *) new_valstack + new_alloc_size);
18754 
18755 	/* Assertions: pointer sanity after pointer updates. */
18756 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
18757 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
18758 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
18759 	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);
18760 
18761 	DUK_D(DUK_DPRINT("resized valstack %lu -> %lu elements (%lu -> %lu bytes): "
18762 	                 "base=%p -> %p, bottom=%p -> %p (%ld), top=%p -> %p (%ld), "
18763 	                 "end=%p -> %p (%ld), alloc_end=%p -> %p (%ld);"
18764 	                 " tv_prev_alloc_end=%p (-> %ld inits; <0 means shrink)",
18765 	                 (unsigned long) (pre_alloc_end - pre_valstack),
18766 	                 (unsigned long) new_size,
18767 	                 (unsigned long) ((duk_uint8_t *) pre_alloc_end - (duk_uint8_t *) pre_valstack),
18768 	                 (unsigned long) new_alloc_size,
18769 	                 (void *) pre_valstack, (void *) thr->valstack,
18770 	                 (void *) pre_bottom, (void *) thr->valstack_bottom, (long) (thr->valstack_bottom - thr->valstack),
18771 	                 (void *) pre_top, (void *) thr->valstack_top, (long) (thr->valstack_top - thr->valstack),
18772 	                 (void *) pre_end, (void *) thr->valstack_end, (long) (thr->valstack_end - thr->valstack),
18773 	                 (void *) pre_alloc_end, (void *) thr->valstack_alloc_end, (long) (thr->valstack_alloc_end - thr->valstack),
18774 	                 (void *) tv_prev_alloc_end, (long) (thr->valstack_alloc_end - tv_prev_alloc_end)));
18775 
18776 	/* If allocation grew, init any new slots to 'undefined'. */
18777 	p = tv_prev_alloc_end;
18778 	while (p < thr->valstack_alloc_end) {
18779 		/* Never executed if new size is smaller. */
18780 		DUK_TVAL_SET_UNDEFINED(p);
18781 		p++;
18782 	}
18783 
18784 	/* Assert for value stack initialization policy. */
18785 #if defined(DUK_USE_ASSERTIONS)
18786 	p = thr->valstack_top;
18787 	while (p < thr->valstack_alloc_end) {
18788 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(p));
18789 		p++;
18790 	}
18791 #endif
18792 
18793 	return 1;
18794 }
18795 
duk__valstack_grow(duk_hthread * thr,duk_size_t min_bytes,duk_bool_t throw_on_error)18796 DUK_LOCAL DUK_COLD DUK_NOINLINE duk_bool_t duk__valstack_grow(duk_hthread *thr, duk_size_t min_bytes, duk_bool_t throw_on_error) {
18797 	duk_size_t min_size;
18798 	duk_size_t new_size;
18799 
18800 	DUK_ASSERT(min_bytes / sizeof(duk_tval) * sizeof(duk_tval) == min_bytes);
18801 	min_size = min_bytes / sizeof(duk_tval);  /* from bytes to slots */
18802 
18803 #if defined(DUK_USE_VALSTACK_GROW_SHIFT)
18804 	/* New size is minimum size plus a proportional slack, e.g. shift of
18805 	 * 2 means a 25% slack.
18806 	 */
18807 	new_size = min_size + (min_size >> DUK_USE_VALSTACK_GROW_SHIFT);
18808 #else
18809 	/* New size is tight with no slack.  This is sometimes preferred in
18810 	 * low memory environments.
18811 	 */
18812 	new_size = min_size;
18813 #endif
18814 
18815 	if (DUK_UNLIKELY(new_size > DUK_USE_VALSTACK_LIMIT || new_size < min_size /*wrap*/)) {
18816 		/* Note: may be triggered even if minimal new_size would not reach the limit,
18817 		 * plan limit accordingly.
18818 		 */
18819 		if (throw_on_error) {
18820 			DUK_ERROR_RANGE(thr, DUK_STR_VALSTACK_LIMIT);
18821 			DUK_WO_NORETURN(return 0;);
18822 		}
18823 		return 0;
18824 	}
18825 
18826 	if (duk__resize_valstack(thr, new_size) == 0) {
18827 		if (throw_on_error) {
18828 			DUK_ERROR_ALLOC_FAILED(thr);
18829 			DUK_WO_NORETURN(return 0;);
18830 		}
18831 		return 0;
18832 	}
18833 
18834 	thr->valstack_end = thr->valstack + min_size;
18835 	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);
18836 
18837 	return 1;
18838 }
18839 
18840 /* Hot, inlined value stack grow check.  Because value stack almost never
18841  * grows, the actual resize call is in a NOINLINE helper.
18842  */
duk_valstack_grow_check_throw(duk_hthread * thr,duk_size_t min_bytes)18843 DUK_INTERNAL DUK_INLINE void duk_valstack_grow_check_throw(duk_hthread *thr, duk_size_t min_bytes) {
18844 	duk_tval *tv;
18845 
18846 	tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + min_bytes);
18847 	if (DUK_LIKELY(thr->valstack_end >= tv)) {
18848 		return;
18849 	}
18850 	if (DUK_LIKELY(thr->valstack_alloc_end >= tv)) {
18851 		/* Values in [valstack_top,valstack_alloc_end[ are initialized
18852 		 * to 'undefined' so we can just move the end pointer.
18853 		 */
18854 		thr->valstack_end = tv;
18855 		return;
18856 	}
18857 	(void) duk__valstack_grow(thr, min_bytes, 1 /*throw_on_error*/);
18858 }
18859 
18860 /* Hot, inlined value stack grow check which doesn't throw. */
duk_valstack_grow_check_nothrow(duk_hthread * thr,duk_size_t min_bytes)18861 DUK_INTERNAL DUK_INLINE duk_bool_t duk_valstack_grow_check_nothrow(duk_hthread *thr, duk_size_t min_bytes) {
18862 	duk_tval *tv;
18863 
18864 	tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + min_bytes);
18865 	if (DUK_LIKELY(thr->valstack_end >= tv)) {
18866 		return 1;
18867 	}
18868 	if (DUK_LIKELY(thr->valstack_alloc_end >= tv)) {
18869 		thr->valstack_end = tv;
18870 		return 1;
18871 	}
18872 	return duk__valstack_grow(thr, min_bytes, 0 /*throw_on_error*/);
18873 }
18874 
18875 /* Value stack shrink check, called from mark-and-sweep. */
duk_valstack_shrink_check_nothrow(duk_hthread * thr,duk_bool_t snug)18876 DUK_INTERNAL void duk_valstack_shrink_check_nothrow(duk_hthread *thr, duk_bool_t snug) {
18877 	duk_size_t alloc_bytes;
18878 	duk_size_t reserve_bytes;
18879 	duk_size_t shrink_bytes;
18880 
18881 	alloc_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_alloc_end - (duk_uint8_t *) thr->valstack);
18882 	reserve_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
18883 	DUK_ASSERT(alloc_bytes >= reserve_bytes);
18884 
18885 	/* We're free to shrink the value stack allocation down to
18886 	 * reserve_bytes but not more.  If 'snug' (emergency GC)
18887 	 * shrink whatever we can.  Otherwise only shrink if the new
18888 	 * size would be considerably smaller.
18889 	 */
18890 
18891 #if defined(DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT)
18892 	if (snug) {
18893 		shrink_bytes = reserve_bytes;
18894 	} else {
18895 		duk_size_t proportion, slack;
18896 
18897 		/* Require that value stack shrinks by at least X% of its
18898 		 * current size.  For example, shift of 2 means at least
18899 		 * 25%.  The proportion is computed as bytes and may not
18900 		 * be a multiple of sizeof(duk_tval); that's OK here.
18901 		 */
18902 		proportion = alloc_bytes >> DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT;
18903 		if (alloc_bytes - reserve_bytes < proportion) {
18904 			/* Too little would be freed, do nothing. */
18905 			return;
18906 		}
18907 
18908 		/* Keep a slack after shrinking.  The slack is again a
18909 		 * proportion of the current size (the proportion should
18910 		 * of course be smaller than the check proportion above).
18911 		 */
18912 #if defined(DUK_USE_VALSTACK_SHRINK_SLACK_SHIFT)
18913 		DUK_ASSERT(DUK_USE_VALSTACK_SHRINK_SLACK_SHIFT > DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT);
18914 		slack = alloc_bytes >> DUK_USE_VALSTACK_SHRINK_SLACK_SHIFT;
18915 #else
18916 		slack = 0;
18917 #endif
18918 		shrink_bytes = reserve_bytes +
18919 		               slack / sizeof(duk_tval) * sizeof(duk_tval);  /* multiple of duk_tval */
18920 	}
18921 #else  /* DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT */
18922 	/* Always snug, useful in some low memory environments. */
18923 	DUK_UNREF(snug);
18924 	shrink_bytes = reserve_bytes;
18925 #endif  /* DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT */
18926 
18927 	DUK_D(DUK_DPRINT("valstack shrink check: alloc_bytes=%ld, reserve_bytes=%ld, shrink_bytes=%ld (unvalidated)",
18928 	                 (long) alloc_bytes, (long) reserve_bytes, (long) shrink_bytes));
18929 	DUK_ASSERT(shrink_bytes >= reserve_bytes);
18930 	if (shrink_bytes >= alloc_bytes) {
18931 		/* Skip if shrink target is same as current one (or higher,
18932 		 * though that shouldn't happen in practice).
18933 		 */
18934 		return;
18935 	}
18936 	DUK_ASSERT(shrink_bytes / sizeof(duk_tval) * sizeof(duk_tval) == shrink_bytes);
18937 
18938 	DUK_D(DUK_DPRINT("valstack shrink check: decided to shrink, snug: %ld", (long) snug));
18939 
18940 	duk__resize_valstack(thr, shrink_bytes / sizeof(duk_tval));
18941 }
18942 
duk_check_stack(duk_hthread * thr,duk_idx_t extra)18943 DUK_EXTERNAL duk_bool_t duk_check_stack(duk_hthread *thr, duk_idx_t extra) {
18944 	duk_size_t min_new_bytes;
18945 
18946 	DUK_ASSERT_API_ENTRY(thr);
18947 	DUK_ASSERT(thr != NULL);
18948 
18949 	if (DUK_UNLIKELY(extra < 0 || extra > DUK_USE_VALSTACK_LIMIT)) {
18950 		if (extra < 0) {
18951 			/* Clamping to zero makes the API more robust to calling code
18952 			 * calculation errors.
18953 			 */
18954 			extra = 0;
18955 		} else {
18956 			/* Cause grow check to fail without wrapping arithmetic. */
18957 			extra = DUK_USE_VALSTACK_LIMIT;
18958 		}
18959 	}
18960 
18961 	min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack) +
18962 	                sizeof(duk_tval) * ((duk_size_t) extra + DUK_VALSTACK_INTERNAL_EXTRA);
18963 	return duk_valstack_grow_check_nothrow(thr, min_new_bytes);
18964 }
18965 
duk_require_stack(duk_hthread * thr,duk_idx_t extra)18966 DUK_EXTERNAL void duk_require_stack(duk_hthread *thr, duk_idx_t extra) {
18967 	duk_size_t min_new_bytes;
18968 
18969 	DUK_ASSERT_API_ENTRY(thr);
18970 	DUK_ASSERT(thr != NULL);
18971 
18972 	if (DUK_UNLIKELY(extra < 0 || extra > DUK_USE_VALSTACK_LIMIT)) {
18973 		if (extra < 0) {
18974 			/* Clamping to zero makes the API more robust to calling code
18975 			 * calculation errors.
18976 			 */
18977 			extra = 0;
18978 		} else {
18979 			/* Cause grow check to fail without wrapping arithmetic. */
18980 			extra = DUK_USE_VALSTACK_LIMIT;
18981 		}
18982 	}
18983 
18984 	min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack) +
18985 	                sizeof(duk_tval) * ((duk_size_t) extra + DUK_VALSTACK_INTERNAL_EXTRA);
18986 	duk_valstack_grow_check_throw(thr, min_new_bytes);
18987 }
18988 
duk_check_stack_top(duk_hthread * thr,duk_idx_t top)18989 DUK_EXTERNAL duk_bool_t duk_check_stack_top(duk_hthread *thr, duk_idx_t top) {
18990 	duk_size_t min_new_bytes;
18991 
18992 	DUK_ASSERT_API_ENTRY(thr);
18993 
18994 	if (DUK_UNLIKELY(top < 0 || top > DUK_USE_VALSTACK_LIMIT)) {
18995 		if (top < 0) {
18996 			/* Clamping to zero makes the API more robust to calling code
18997 			 * calculation errors.
18998 			 */
18999 			top = 0;
19000 		} else {
19001 			/* Cause grow check to fail without wrapping arithmetic. */
19002 			top = DUK_USE_VALSTACK_LIMIT;
19003 		}
19004 	}
19005 
19006 	DUK_ASSERT(top >= 0);
19007 	min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) +
19008 	                sizeof(duk_tval) * ((duk_size_t) top + DUK_VALSTACK_INTERNAL_EXTRA);
19009 	return duk_valstack_grow_check_nothrow(thr, min_new_bytes);
19010 }
19011 
duk_require_stack_top(duk_hthread * thr,duk_idx_t top)19012 DUK_EXTERNAL void duk_require_stack_top(duk_hthread *thr, duk_idx_t top) {
19013 	duk_size_t min_new_bytes;
19014 
19015 	DUK_ASSERT_API_ENTRY(thr);
19016 
19017 	if (DUK_UNLIKELY(top < 0 || top > DUK_USE_VALSTACK_LIMIT)) {
19018 		if (top < 0) {
19019 			/* Clamping to zero makes the API more robust to calling code
19020 			 * calculation errors.
19021 			 */
19022 			top = 0;
19023 		} else {
19024 			/* Cause grow check to fail without wrapping arithmetic. */
19025 			top = DUK_USE_VALSTACK_LIMIT;
19026 		}
19027 	}
19028 
19029 	DUK_ASSERT(top >= 0);
19030 	min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) +
19031 	                sizeof(duk_tval) * ((duk_size_t) top + DUK_VALSTACK_INTERNAL_EXTRA);
19032 	duk_valstack_grow_check_throw(thr, min_new_bytes);
19033 }
19034 
19035 /*
19036  *  Basic stack manipulation: swap, dup, insert, replace, etc
19037  */
19038 
duk_swap(duk_hthread * thr,duk_idx_t idx1,duk_idx_t idx2)19039 DUK_EXTERNAL void duk_swap(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
19040 	duk_tval *tv1;
19041 	duk_tval *tv2;
19042 	duk_tval tv_tmp;
19043 
19044 	DUK_ASSERT_API_ENTRY(thr);
19045 
19046 	tv1 = duk_require_tval(thr, idx1);
19047 	DUK_ASSERT(tv1 != NULL);
19048 	tv2 = duk_require_tval(thr, idx2);
19049 	DUK_ASSERT(tv2 != NULL);
19050 
19051 	/* If tv1==tv2 this is a NOP, no check is needed */
19052 	DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
19053 	DUK_TVAL_SET_TVAL(tv1, tv2);
19054 	DUK_TVAL_SET_TVAL(tv2, &tv_tmp);
19055 }
19056 
duk_swap_top(duk_hthread * thr,duk_idx_t idx)19057 DUK_EXTERNAL void duk_swap_top(duk_hthread *thr, duk_idx_t idx) {
19058 	DUK_ASSERT_API_ENTRY(thr);
19059 
19060 	duk_swap(thr, idx, -1);
19061 }
19062 
duk_dup(duk_hthread * thr,duk_idx_t from_idx)19063 DUK_EXTERNAL void duk_dup(duk_hthread *thr, duk_idx_t from_idx) {
19064 	duk_tval *tv_from;
19065 	duk_tval *tv_to;
19066 
19067 	DUK_ASSERT_API_ENTRY(thr);
19068 	DUK__CHECK_SPACE();
19069 
19070 	tv_from = duk_require_tval(thr, from_idx);
19071 	tv_to = thr->valstack_top++;
19072 	DUK_ASSERT(tv_from != NULL);
19073 	DUK_ASSERT(tv_to != NULL);
19074 	DUK_TVAL_SET_TVAL(tv_to, tv_from);
19075 	DUK_TVAL_INCREF(thr, tv_to);  /* no side effects */
19076 }
19077 
duk_dup_top(duk_hthread * thr)19078 DUK_EXTERNAL void duk_dup_top(duk_hthread *thr) {
19079 #if defined(DUK_USE_PREFER_SIZE)
19080 	duk_dup(thr, -1);
19081 #else
19082 	duk_tval *tv_from;
19083 	duk_tval *tv_to;
19084 
19085 	DUK_ASSERT_API_ENTRY(thr);
19086 	DUK__CHECK_SPACE();
19087 
19088 	if (DUK_UNLIKELY(thr->valstack_top - thr->valstack_bottom <= 0)) {
19089 		DUK_ERROR_RANGE_INDEX(thr, -1);
19090 		DUK_WO_NORETURN(return;);
19091 	}
19092 	tv_from = thr->valstack_top - 1;
19093 	tv_to = thr->valstack_top++;
19094 	DUK_ASSERT(tv_from != NULL);
19095 	DUK_ASSERT(tv_to != NULL);
19096 	DUK_TVAL_SET_TVAL(tv_to, tv_from);
19097 	DUK_TVAL_INCREF(thr, tv_to);  /* no side effects */
19098 #endif
19099 }
19100 
duk_dup_0(duk_hthread * thr)19101 DUK_INTERNAL void duk_dup_0(duk_hthread *thr) {
19102 	DUK_ASSERT_API_ENTRY(thr);
19103 	duk_dup(thr, 0);
19104 }
duk_dup_1(duk_hthread * thr)19105 DUK_INTERNAL void duk_dup_1(duk_hthread *thr) {
19106 	DUK_ASSERT_API_ENTRY(thr);
19107 	duk_dup(thr, 1);
19108 }
duk_dup_2(duk_hthread * thr)19109 DUK_INTERNAL void duk_dup_2(duk_hthread *thr) {
19110 	DUK_ASSERT_API_ENTRY(thr);
19111 	duk_dup(thr, 2);
19112 }
duk_dup_m2(duk_hthread * thr)19113 DUK_INTERNAL void duk_dup_m2(duk_hthread *thr) {
19114 	DUK_ASSERT_API_ENTRY(thr);
19115 	duk_dup(thr, -2);
19116 }
duk_dup_m3(duk_hthread * thr)19117 DUK_INTERNAL void duk_dup_m3(duk_hthread *thr) {
19118 	DUK_ASSERT_API_ENTRY(thr);
19119 	duk_dup(thr, -3);
19120 }
duk_dup_m4(duk_hthread * thr)19121 DUK_INTERNAL void duk_dup_m4(duk_hthread *thr) {
19122 	DUK_ASSERT_API_ENTRY(thr);
19123 	duk_dup(thr, -4);
19124 }
19125 
duk_insert(duk_hthread * thr,duk_idx_t to_idx)19126 DUK_EXTERNAL void duk_insert(duk_hthread *thr, duk_idx_t to_idx) {
19127 	duk_tval *p;
19128 	duk_tval *q;
19129 	duk_tval tv_tmp;
19130 	duk_size_t nbytes;
19131 
19132 	DUK_ASSERT_API_ENTRY(thr);
19133 
19134 	p = duk_require_tval(thr, to_idx);
19135 	DUK_ASSERT(p != NULL);
19136 	q = duk_require_tval(thr, -1);
19137 	DUK_ASSERT(q != NULL);
19138 
19139 	DUK_ASSERT(q >= p);
19140 
19141 	/*              nbytes
19142 	 *           <--------->
19143 	 *    [ ... | p | x | x | q ]
19144 	 * => [ ... | q | p | x | x ]
19145 	 */
19146 
19147 	nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));
19148 
19149 	DUK_DDD(DUK_DDDPRINT("duk_insert: to_idx=%ld, p=%p, q=%p, nbytes=%lu",
19150 	                     (long) to_idx, (void *) p, (void *) q, (unsigned long) nbytes));
19151 
19152 	/* No net refcount changes.  No need to special case nbytes == 0
19153 	 * (p == q).
19154 	 */
19155 	DUK_TVAL_SET_TVAL(&tv_tmp, q);
19156 	duk_memmove((void *) (p + 1), (const void *) p, (size_t) nbytes);
19157 	DUK_TVAL_SET_TVAL(p, &tv_tmp);
19158 }
19159 
duk_insert_undefined(duk_hthread * thr,duk_idx_t idx)19160 DUK_INTERNAL void duk_insert_undefined(duk_hthread *thr, duk_idx_t idx) {
19161 	DUK_ASSERT_API_ENTRY(thr);
19162 	DUK_ASSERT(idx >= 0);  /* Doesn't support negative indices. */
19163 
19164 	duk_push_undefined(thr);
19165 	duk_insert(thr, idx);
19166 }
19167 
duk_insert_undefined_n(duk_hthread * thr,duk_idx_t idx,duk_idx_t count)19168 DUK_INTERNAL void duk_insert_undefined_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count) {
19169 	duk_tval *tv, *tv_end;
19170 
19171 	DUK_ASSERT_API_ENTRY(thr);
19172 	DUK_ASSERT(idx >= 0);  /* Doesn't support negative indices or count. */
19173 	DUK_ASSERT(count >= 0);
19174 
19175 	tv = duk_reserve_gap(thr, idx, count);
19176 	tv_end = tv + count;
19177 	while (tv != tv_end) {
19178 		DUK_TVAL_SET_UNDEFINED(tv);
19179 		tv++;
19180 	}
19181 }
19182 
duk_pull(duk_hthread * thr,duk_idx_t from_idx)19183 DUK_EXTERNAL void duk_pull(duk_hthread *thr, duk_idx_t from_idx) {
19184 	duk_tval *p;
19185 	duk_tval *q;
19186 	duk_tval tv_tmp;
19187 	duk_size_t nbytes;
19188 
19189 	DUK_ASSERT_API_ENTRY(thr);
19190 
19191 	/*                         nbytes
19192 	 *                       <--------->
19193 	 *    [ ... | x | x | p | y | y | q ]
19194 	 * => [ ... | x | x | y | y | q | p ]
19195 	 */
19196 
19197 	p = duk_require_tval(thr, from_idx);
19198 	DUK_ASSERT(p != NULL);
19199 	q = duk_require_tval(thr, -1);
19200 	DUK_ASSERT(q != NULL);
19201 
19202 	DUK_ASSERT(q >= p);
19203 
19204 	nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));
19205 
19206 	DUK_DDD(DUK_DDDPRINT("duk_pull: from_idx=%ld, p=%p, q=%p, nbytes=%lu",
19207 	                     (long) from_idx, (void *) p, (void *) q, (unsigned long) nbytes));
19208 
19209 	/* No net refcount changes.  No need to special case nbytes == 0
19210 	 * (p == q).
19211 	 */
19212 	DUK_TVAL_SET_TVAL(&tv_tmp, p);
19213 	duk_memmove((void *) p, (const void *) (p + 1), (size_t) nbytes);
19214 	DUK_TVAL_SET_TVAL(q, &tv_tmp);
19215 }
19216 
duk_replace(duk_hthread * thr,duk_idx_t to_idx)19217 DUK_EXTERNAL void duk_replace(duk_hthread *thr, duk_idx_t to_idx) {
19218 	duk_tval *tv1;
19219 	duk_tval *tv2;
19220 	duk_tval tv_tmp;
19221 
19222 	DUK_ASSERT_API_ENTRY(thr);
19223 
19224 	tv1 = duk_require_tval(thr, -1);
19225 	DUK_ASSERT(tv1 != NULL);
19226 	tv2 = duk_require_tval(thr, to_idx);
19227 	DUK_ASSERT(tv2 != NULL);
19228 
19229 	/* For tv1 == tv2, both pointing to stack top, the end result
19230 	 * is same as duk_pop(thr).
19231 	 */
19232 	DUK_TVAL_SET_TVAL(&tv_tmp, tv2);
19233 	DUK_TVAL_SET_TVAL(tv2, tv1);
19234 	DUK_TVAL_SET_UNDEFINED(tv1);
19235 	thr->valstack_top--;
19236 	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
19237 }
19238 
duk_copy(duk_hthread * thr,duk_idx_t from_idx,duk_idx_t to_idx)19239 DUK_EXTERNAL void duk_copy(duk_hthread *thr, duk_idx_t from_idx, duk_idx_t to_idx) {
19240 	duk_tval *tv1;
19241 	duk_tval *tv2;
19242 
19243 	DUK_ASSERT_API_ENTRY(thr);
19244 
19245 	tv1 = duk_require_tval(thr, from_idx);
19246 	DUK_ASSERT(tv1 != NULL);
19247 	tv2 = duk_require_tval(thr, to_idx);
19248 	DUK_ASSERT(tv2 != NULL);
19249 
19250 	/* For tv1 == tv2, this is a no-op (no explicit check needed). */
19251 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv2, tv1);  /* side effects */
19252 }
19253 
duk_remove(duk_hthread * thr,duk_idx_t idx)19254 DUK_EXTERNAL void duk_remove(duk_hthread *thr, duk_idx_t idx) {
19255 	duk_tval *p;
19256 	duk_tval *q;
19257 #if defined(DUK_USE_REFERENCE_COUNTING)
19258 	duk_tval tv_tmp;
19259 #endif
19260 	duk_size_t nbytes;
19261 
19262 	DUK_ASSERT_API_ENTRY(thr);
19263 
19264 	p = duk_require_tval(thr, idx);
19265 	DUK_ASSERT(p != NULL);
19266 	q = duk_require_tval(thr, -1);
19267 	DUK_ASSERT(q != NULL);
19268 
19269 	DUK_ASSERT(q >= p);
19270 
19271 	/*              nbytes            zero size case
19272 	 *           <--------->
19273 	 *    [ ... | p | x | x | q ]     [ ... | p==q ]
19274 	 * => [ ... | x | x | q ]         [ ... ]
19275 	 */
19276 
19277 #if defined(DUK_USE_REFERENCE_COUNTING)
19278 	/* use a temp: decref only when valstack reachable values are correct */
19279 	DUK_TVAL_SET_TVAL(&tv_tmp, p);
19280 #endif
19281 
19282 	nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));  /* Note: 'q' is top-1 */
19283 	duk_memmove((void *) p, (const void *) (p + 1), (size_t) nbytes);
19284 
19285 	DUK_TVAL_SET_UNDEFINED(q);
19286 	thr->valstack_top--;
19287 
19288 #if defined(DUK_USE_REFERENCE_COUNTING)
19289 	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
19290 #endif
19291 }
19292 
duk_remove_unsafe(duk_hthread * thr,duk_idx_t idx)19293 DUK_INTERNAL void duk_remove_unsafe(duk_hthread *thr, duk_idx_t idx) {
19294 	DUK_ASSERT_API_ENTRY(thr);
19295 
19296 	duk_remove(thr, idx);  /* XXX: no optimization for now */
19297 }
19298 
duk_remove_m2(duk_hthread * thr)19299 DUK_INTERNAL void duk_remove_m2(duk_hthread *thr) {
19300 	DUK_ASSERT_API_ENTRY(thr);
19301 
19302 	duk_remove(thr, -2);
19303 }
19304 
duk_remove_n(duk_hthread * thr,duk_idx_t idx,duk_idx_t count)19305 DUK_INTERNAL void duk_remove_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count) {
19306 #if defined(DUK_USE_PREFER_SIZE)
19307 	/* XXX: maybe too slow even when preferring size? */
19308 	DUK_ASSERT_API_ENTRY(thr);
19309 	DUK_ASSERT(count >= 0);
19310 	DUK_ASSERT(idx >= 0);
19311 
19312 	while (count-- > 0) {
19313 		duk_remove(thr, idx);
19314 	}
19315 #else  /* DUK_USE_PREFER_SIZE */
19316 	duk_tval *tv_src;
19317 	duk_tval *tv_dst;
19318 	duk_tval *tv_newtop;
19319 	duk_tval *tv;
19320 	duk_size_t bytes;
19321 
19322 	DUK_ASSERT_API_ENTRY(thr);
19323 	DUK_ASSERT(count >= 0);
19324 	DUK_ASSERT(idx >= 0);
19325 
19326 	tv_dst = thr->valstack_bottom + idx;
19327 	DUK_ASSERT(tv_dst <= thr->valstack_top);
19328 	tv_src = tv_dst + count;
19329 	DUK_ASSERT(tv_src <= thr->valstack_top);
19330 	bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) tv_src);
19331 
19332 	for (tv = tv_dst; tv < tv_src; tv++) {
19333 		DUK_TVAL_DECREF_NORZ(thr, tv);
19334 	}
19335 
19336 	duk_memmove((void *) tv_dst, (const void *) tv_src, bytes);
19337 
19338 	tv_newtop = thr->valstack_top - count;
19339 	for (tv = tv_newtop; tv < thr->valstack_top; tv++) {
19340 		DUK_TVAL_SET_UNDEFINED(tv);
19341 	}
19342 	thr->valstack_top = tv_newtop;
19343 
19344 	/* When not preferring size, only NORZ macros are used; caller
19345 	 * is expected to DUK_REFZERO_CHECK().
19346 	 */
19347 #endif  /* DUK_USE_PREFER_SIZE */
19348 }
19349 
duk_remove_n_unsafe(duk_hthread * thr,duk_idx_t idx,duk_idx_t count)19350 DUK_INTERNAL void duk_remove_n_unsafe(duk_hthread *thr, duk_idx_t idx, duk_idx_t count) {
19351 	DUK_ASSERT_API_ENTRY(thr);
19352 
19353 	duk_remove_n(thr, idx, count);  /* XXX: no optimization for now */
19354 }
19355 
19356 /*
19357  *  Stack slice primitives
19358  */
19359 
duk_xcopymove_raw(duk_hthread * to_thr,duk_hthread * from_thr,duk_idx_t count,duk_bool_t is_copy)19360 DUK_EXTERNAL void duk_xcopymove_raw(duk_hthread *to_thr, duk_hthread *from_thr, duk_idx_t count, duk_bool_t is_copy) {
19361 	void *src;
19362 	duk_size_t nbytes;
19363 	duk_tval *p;
19364 	duk_tval *q;
19365 
19366 	/* XXX: several pointer comparison issues here */
19367 
19368 	DUK_ASSERT_API_ENTRY(to_thr);
19369 	DUK_CTX_ASSERT_VALID(to_thr);
19370 	DUK_CTX_ASSERT_VALID(from_thr);
19371 	DUK_ASSERT(to_thr->heap == from_thr->heap);
19372 
19373 	if (DUK_UNLIKELY(to_thr == from_thr)) {
19374 		DUK_ERROR_TYPE(to_thr, DUK_STR_INVALID_CONTEXT);
19375 		DUK_WO_NORETURN(return;);
19376 	}
19377 	if (DUK_UNLIKELY((duk_uidx_t) count > (duk_uidx_t) DUK_USE_VALSTACK_LIMIT)) {
19378 		/* Maximum value check ensures 'nbytes' won't wrap below.
19379 		 * Also handles negative count.
19380 		 */
19381 		DUK_ERROR_RANGE_INVALID_COUNT(to_thr);
19382 		DUK_WO_NORETURN(return;);
19383 	}
19384 	DUK_ASSERT(count >= 0);
19385 
19386 	nbytes = sizeof(duk_tval) * (duk_size_t) count;
19387 	if (DUK_UNLIKELY(nbytes == 0)) {
19388 		return;
19389 	}
19390 	DUK_ASSERT(to_thr->valstack_top <= to_thr->valstack_end);
19391 	if (DUK_UNLIKELY((duk_size_t) ((duk_uint8_t *) to_thr->valstack_end - (duk_uint8_t *) to_thr->valstack_top) < nbytes)) {
19392 		DUK_ERROR_RANGE_PUSH_BEYOND(to_thr);
19393 		DUK_WO_NORETURN(return;);
19394 	}
19395 	src = (void *) ((duk_uint8_t *) from_thr->valstack_top - nbytes);
19396 	if (DUK_UNLIKELY(src < (void *) from_thr->valstack_bottom)) {
19397 		DUK_ERROR_RANGE_INVALID_COUNT(to_thr);
19398 		DUK_WO_NORETURN(return;);
19399 	}
19400 
19401 	/* Copy values (no overlap even if to_thr == from_thr; that's not
19402 	 * allowed now anyway).
19403 	 */
19404 	DUK_ASSERT(nbytes > 0);
19405 	duk_memcpy((void *) to_thr->valstack_top, (const void *) src, (size_t) nbytes);
19406 
19407 	p = to_thr->valstack_top;
19408 	to_thr->valstack_top = (duk_tval *) (void *) (((duk_uint8_t *) p) + nbytes);
19409 
19410 	if (is_copy) {
19411 		/* Incref copies, keep originals. */
19412 		q = to_thr->valstack_top;
19413 		while (p < q) {
19414 			DUK_TVAL_INCREF(to_thr, p);  /* no side effects */
19415 			p++;
19416 		}
19417 	} else {
19418 		/* No net refcount change. */
19419 		p = from_thr->valstack_top;
19420 		q = (duk_tval *) (void *) (((duk_uint8_t *) p) - nbytes);
19421 		from_thr->valstack_top = q;
19422 
19423 		while (p > q) {
19424 			p--;
19425 			DUK_TVAL_SET_UNDEFINED(p);
19426 			/* XXX: fast primitive to set a bunch of values to UNDEFINED */
19427 		}
19428 	}
19429 }
19430 
19431 /* Internal helper: reserve a gap of 'count' elements at 'idx_base' and return a
19432  * pointer to the gap.  Values in the gap are garbage and MUST be initialized by
19433  * the caller before any side effects may occur.  The caller must ensure there's
19434  * enough stack reserve for 'count' values.
19435  */
duk_reserve_gap(duk_hthread * thr,duk_idx_t idx_base,duk_idx_t count)19436 DUK_INTERNAL duk_tval *duk_reserve_gap(duk_hthread *thr, duk_idx_t idx_base, duk_idx_t count) {
19437 	duk_tval *tv_src;
19438 	duk_tval *tv_dst;
19439 	duk_size_t gap_bytes;
19440 	duk_size_t copy_bytes;
19441 
19442 	/* Caller is responsible for ensuring there's enough preallocated
19443 	 * value stack.
19444 	 */
19445 	DUK_ASSERT_API_ENTRY(thr);
19446 	DUK_ASSERT(count >= 0);
19447 	DUK_ASSERT((duk_size_t) (thr->valstack_end - thr->valstack_top) >= (duk_size_t) count);
19448 
19449 	tv_src = thr->valstack_bottom + idx_base;
19450 	gap_bytes = (duk_size_t) count * sizeof(duk_tval);
19451 	tv_dst = (duk_tval *) (void *) ((duk_uint8_t *) tv_src + gap_bytes);
19452 	copy_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) tv_src);
19453 	thr->valstack_top = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_top + gap_bytes);
19454 	duk_memmove((void *) tv_dst, (const void *) tv_src, copy_bytes);
19455 
19456 	/* Values in the gap are left as garbage: caller must fill them in
19457 	 * and INCREF them before any side effects.
19458 	 */
19459 	return tv_src;
19460 }
19461 
19462 /*
19463  *  Get/opt/require
19464  */
19465 
duk_require_undefined(duk_hthread * thr,duk_idx_t idx)19466 DUK_EXTERNAL void duk_require_undefined(duk_hthread *thr, duk_idx_t idx) {
19467 	duk_tval *tv;
19468 
19469 	DUK_ASSERT_API_ENTRY(thr);
19470 
19471 	tv = duk_get_tval_or_unused(thr, idx);
19472 	DUK_ASSERT(tv != NULL);
19473 	if (DUK_UNLIKELY(!DUK_TVAL_IS_UNDEFINED(tv))) {
19474 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "undefined", DUK_STR_NOT_UNDEFINED);
19475 		DUK_WO_NORETURN(return;);
19476 	}
19477 }
19478 
duk_require_null(duk_hthread * thr,duk_idx_t idx)19479 DUK_EXTERNAL void duk_require_null(duk_hthread *thr, duk_idx_t idx) {
19480 	duk_tval *tv;
19481 
19482 	DUK_ASSERT_API_ENTRY(thr);
19483 
19484 	tv = duk_get_tval_or_unused(thr, idx);
19485 	DUK_ASSERT(tv != NULL);
19486 	if (DUK_UNLIKELY(!DUK_TVAL_IS_NULL(tv))) {
19487 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "null", DUK_STR_NOT_NULL);
19488 		DUK_WO_NORETURN(return;);
19489 	}
19490 }
19491 
duk__get_boolean_raw(duk_hthread * thr,duk_idx_t idx,duk_bool_t def_value)19492 DUK_LOCAL DUK_ALWAYS_INLINE duk_bool_t duk__get_boolean_raw(duk_hthread *thr, duk_idx_t idx, duk_bool_t def_value) {
19493 	duk_bool_t ret;
19494 	duk_tval *tv;
19495 
19496 	DUK_CTX_ASSERT_VALID(thr);
19497 
19498 	tv = duk_get_tval_or_unused(thr, idx);
19499 	DUK_ASSERT(tv != NULL);
19500 	if (DUK_TVAL_IS_BOOLEAN(tv)) {
19501 		ret = DUK_TVAL_GET_BOOLEAN(tv);
19502 		DUK_ASSERT(ret == 0 || ret == 1);
19503 	} else {
19504 		ret = def_value;
19505 		/* Not guaranteed to be 0 or 1. */
19506 	}
19507 
19508 	return ret;
19509 }
19510 
duk_get_boolean(duk_hthread * thr,duk_idx_t idx)19511 DUK_EXTERNAL duk_bool_t duk_get_boolean(duk_hthread *thr, duk_idx_t idx) {
19512 	DUK_ASSERT_API_ENTRY(thr);
19513 
19514 	return duk__get_boolean_raw(thr, idx, 0);  /* default: false */
19515 }
19516 
duk_get_boolean_default(duk_hthread * thr,duk_idx_t idx,duk_bool_t def_value)19517 DUK_EXTERNAL duk_bool_t duk_get_boolean_default(duk_hthread *thr, duk_idx_t idx, duk_bool_t def_value) {
19518 	DUK_ASSERT_API_ENTRY(thr);
19519 
19520 	return duk__get_boolean_raw(thr, idx, def_value);
19521 }
19522 
duk_require_boolean(duk_hthread * thr,duk_idx_t idx)19523 DUK_EXTERNAL duk_bool_t duk_require_boolean(duk_hthread *thr, duk_idx_t idx) {
19524 	duk_tval *tv;
19525 	duk_bool_t ret;
19526 
19527 	DUK_ASSERT_API_ENTRY(thr);
19528 
19529 	tv = duk_get_tval_or_unused(thr, idx);
19530 	DUK_ASSERT(tv != NULL);
19531 	if (DUK_LIKELY(DUK_TVAL_IS_BOOLEAN(tv))) {
19532 		ret = DUK_TVAL_GET_BOOLEAN(tv);
19533 		DUK_ASSERT(ret == 0 || ret == 1);
19534 		return ret;
19535 	} else {
19536 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "boolean", DUK_STR_NOT_BOOLEAN);
19537 		DUK_WO_NORETURN(return 0;);
19538 	}
19539 }
19540 
duk_opt_boolean(duk_hthread * thr,duk_idx_t idx,duk_bool_t def_value)19541 DUK_EXTERNAL duk_bool_t duk_opt_boolean(duk_hthread *thr, duk_idx_t idx, duk_bool_t def_value) {
19542 	DUK_ASSERT_API_ENTRY(thr);
19543 
19544 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19545 		return def_value;
19546 	}
19547 	return duk_require_boolean(thr, idx);
19548 }
19549 
duk__get_number_raw(duk_hthread * thr,duk_idx_t idx,duk_double_t def_value)19550 DUK_LOCAL DUK_ALWAYS_INLINE duk_double_t duk__get_number_raw(duk_hthread *thr, duk_idx_t idx, duk_double_t def_value) {
19551 	duk_double_union ret;
19552 	duk_tval *tv;
19553 
19554 	DUK_CTX_ASSERT_VALID(thr);
19555 
19556 	tv = duk_get_tval_or_unused(thr, idx);
19557 	DUK_ASSERT(tv != NULL);
19558 #if defined(DUK_USE_FASTINT)
19559 	if (DUK_TVAL_IS_FASTINT(tv)) {
19560 		ret.d = (duk_double_t) DUK_TVAL_GET_FASTINT(tv);  /* XXX: cast trick */
19561 	}
19562 	else
19563 #endif
19564 	if (DUK_TVAL_IS_DOUBLE(tv)) {
19565 		/* When using packed duk_tval, number must be in NaN-normalized form
19566 		 * for it to be a duk_tval, so no need to normalize.  NOP for unpacked
19567 		 * duk_tval.
19568 		 */
19569 		ret.d = DUK_TVAL_GET_DOUBLE(tv);
19570 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&ret));
19571 	} else {
19572 		ret.d = def_value;
19573 		/* Default value (including NaN) may not be normalized. */
19574 	}
19575 
19576 	return ret.d;
19577 }
19578 
duk_get_number(duk_hthread * thr,duk_idx_t idx)19579 DUK_EXTERNAL duk_double_t duk_get_number(duk_hthread *thr, duk_idx_t idx) {
19580 	DUK_ASSERT_API_ENTRY(thr);
19581 	return duk__get_number_raw(thr, idx, DUK_DOUBLE_NAN);  /* default: NaN */
19582 }
19583 
duk_get_number_default(duk_hthread * thr,duk_idx_t idx,duk_double_t def_value)19584 DUK_EXTERNAL duk_double_t duk_get_number_default(duk_hthread *thr, duk_idx_t idx, duk_double_t def_value) {
19585 	DUK_ASSERT_API_ENTRY(thr);
19586 	return duk__get_number_raw(thr, idx, def_value);
19587 }
19588 
duk_require_number(duk_hthread * thr,duk_idx_t idx)19589 DUK_EXTERNAL duk_double_t duk_require_number(duk_hthread *thr, duk_idx_t idx) {
19590 	duk_tval *tv;
19591 	duk_double_union ret;
19592 
19593 	DUK_ASSERT_API_ENTRY(thr);
19594 
19595 	tv = duk_get_tval_or_unused(thr, idx);
19596 	DUK_ASSERT(tv != NULL);
19597 	if (DUK_UNLIKELY(!DUK_TVAL_IS_NUMBER(tv))) {
19598 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "number", DUK_STR_NOT_NUMBER);
19599 		DUK_WO_NORETURN(return 0.0;);
19600 	}
19601 
19602 	ret.d = DUK_TVAL_GET_NUMBER(tv);
19603 
19604 	/* When using packed duk_tval, number must be in NaN-normalized form
19605 	 * for it to be a duk_tval, so no need to normalize.  NOP for unpacked
19606 	 * duk_tval.
19607 	 */
19608 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&ret));
19609 	return ret.d;
19610 }
19611 
duk_opt_number(duk_hthread * thr,duk_idx_t idx,duk_double_t def_value)19612 DUK_EXTERNAL duk_double_t duk_opt_number(duk_hthread *thr, duk_idx_t idx, duk_double_t def_value) {
19613 	DUK_ASSERT_API_ENTRY(thr);
19614 
19615 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19616 		/* User provided default is not NaN normalized. */
19617 		return def_value;
19618 	}
19619 	return duk_require_number(thr, idx);
19620 }
19621 
duk_get_int(duk_hthread * thr,duk_idx_t idx)19622 DUK_EXTERNAL duk_int_t duk_get_int(duk_hthread *thr, duk_idx_t idx) {
19623 	DUK_ASSERT_API_ENTRY(thr);
19624 
19625 	return (duk_int_t) duk__api_coerce_d2i(thr, idx, 0 /*def_value*/, 0 /*require*/);
19626 }
19627 
duk_get_uint(duk_hthread * thr,duk_idx_t idx)19628 DUK_EXTERNAL duk_uint_t duk_get_uint(duk_hthread *thr, duk_idx_t idx) {
19629 	DUK_ASSERT_API_ENTRY(thr);
19630 
19631 	return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, 0 /*def_value*/, 0 /*require*/);
19632 }
19633 
duk_get_int_default(duk_hthread * thr,duk_idx_t idx,duk_int_t def_value)19634 DUK_EXTERNAL duk_int_t duk_get_int_default(duk_hthread *thr, duk_idx_t idx, duk_int_t def_value) {
19635 	DUK_ASSERT_API_ENTRY(thr);
19636 
19637 	return (duk_int_t) duk__api_coerce_d2i(thr, idx, def_value, 0 /*require*/);
19638 }
19639 
duk_get_uint_default(duk_hthread * thr,duk_idx_t idx,duk_uint_t def_value)19640 DUK_EXTERNAL duk_uint_t duk_get_uint_default(duk_hthread *thr, duk_idx_t idx, duk_uint_t def_value) {
19641 	DUK_ASSERT_API_ENTRY(thr);
19642 
19643 	return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, def_value, 0 /*require*/);
19644 }
19645 
duk_require_int(duk_hthread * thr,duk_idx_t idx)19646 DUK_EXTERNAL duk_int_t duk_require_int(duk_hthread *thr, duk_idx_t idx) {
19647 	DUK_ASSERT_API_ENTRY(thr);
19648 
19649 	return (duk_int_t) duk__api_coerce_d2i(thr, idx, 0 /*def_value*/, 1 /*require*/);
19650 }
19651 
duk_require_uint(duk_hthread * thr,duk_idx_t idx)19652 DUK_EXTERNAL duk_uint_t duk_require_uint(duk_hthread *thr, duk_idx_t idx) {
19653 	DUK_ASSERT_API_ENTRY(thr);
19654 
19655 	return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, 0 /*def_value*/, 1 /*require*/);
19656 }
19657 
duk_opt_int(duk_hthread * thr,duk_idx_t idx,duk_int_t def_value)19658 DUK_EXTERNAL duk_int_t duk_opt_int(duk_hthread *thr, duk_idx_t idx, duk_int_t def_value) {
19659 	DUK_ASSERT_API_ENTRY(thr);
19660 
19661 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19662 		return def_value;
19663 	}
19664 	return duk_require_int(thr, idx);
19665 }
19666 
duk_opt_uint(duk_hthread * thr,duk_idx_t idx,duk_uint_t def_value)19667 DUK_EXTERNAL duk_uint_t duk_opt_uint(duk_hthread *thr, duk_idx_t idx, duk_uint_t def_value) {
19668 	DUK_ASSERT_API_ENTRY(thr);
19669 
19670 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19671 		return def_value;
19672 	}
19673 	return duk_require_uint(thr, idx);
19674 }
19675 
duk_get_lstring(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)19676 DUK_EXTERNAL const char *duk_get_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
19677 	duk_hstring *h;
19678 	const char *ret;
19679 	duk_size_t len;
19680 
19681 	DUK_ASSERT_API_ENTRY(thr);
19682 
19683 	h = duk_get_hstring(thr, idx);
19684 	if (h != NULL) {
19685 		len = DUK_HSTRING_GET_BYTELEN(h);
19686 		ret = (const char *) DUK_HSTRING_GET_DATA(h);
19687 	} else {
19688 		len = 0;
19689 		ret = NULL;
19690 	}
19691 
19692 	if (out_len != NULL) {
19693 		*out_len = len;
19694 	}
19695 	return ret;
19696 }
19697 
duk_require_lstring(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)19698 DUK_EXTERNAL const char *duk_require_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
19699 	duk_hstring *h;
19700 
19701 	DUK_ASSERT_API_ENTRY(thr);
19702 
19703 	h = duk_require_hstring(thr, idx);
19704 	DUK_ASSERT(h != NULL);
19705 	if (out_len) {
19706 		*out_len = DUK_HSTRING_GET_BYTELEN(h);
19707 	}
19708 	return (const char *) DUK_HSTRING_GET_DATA(h);
19709 }
19710 
duk_require_lstring_notsymbol(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)19711 DUK_INTERNAL const char *duk_require_lstring_notsymbol(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
19712 	duk_hstring *h;
19713 
19714 	DUK_ASSERT_API_ENTRY(thr);
19715 
19716 	h = duk_require_hstring_notsymbol(thr, idx);
19717 	DUK_ASSERT(h != NULL);
19718 	if (out_len) {
19719 		*out_len = DUK_HSTRING_GET_BYTELEN(h);
19720 	}
19721 	return (const char *) DUK_HSTRING_GET_DATA(h);
19722 }
19723 
duk_get_string(duk_hthread * thr,duk_idx_t idx)19724 DUK_EXTERNAL const char *duk_get_string(duk_hthread *thr, duk_idx_t idx) {
19725 	duk_hstring *h;
19726 
19727 	DUK_ASSERT_API_ENTRY(thr);
19728 
19729 	h = duk_get_hstring(thr, idx);
19730 	if (h != NULL) {
19731 		return (const char *) DUK_HSTRING_GET_DATA(h);
19732 	} else {
19733 		return NULL;
19734 	}
19735 }
19736 
duk_opt_lstring(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len,const char * def_ptr,duk_size_t def_len)19737 DUK_EXTERNAL const char *duk_opt_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len, const char *def_ptr, duk_size_t def_len) {
19738 	DUK_ASSERT_API_ENTRY(thr);
19739 
19740 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19741 		if (out_len != NULL) {
19742 			*out_len = def_len;
19743 		}
19744 		return def_ptr;
19745 	}
19746 	return duk_require_lstring(thr, idx, out_len);
19747 }
19748 
duk_opt_string(duk_hthread * thr,duk_idx_t idx,const char * def_ptr)19749 DUK_EXTERNAL const char *duk_opt_string(duk_hthread *thr, duk_idx_t idx, const char *def_ptr) {
19750 	DUK_ASSERT_API_ENTRY(thr);
19751 
19752 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19753 		return def_ptr;
19754 	}
19755 	return duk_require_string(thr, idx);
19756 }
19757 
duk_get_lstring_default(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len,const char * def_ptr,duk_size_t def_len)19758 DUK_EXTERNAL const char *duk_get_lstring_default(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len, const char *def_ptr, duk_size_t def_len) {
19759 	duk_hstring *h;
19760 	const char *ret;
19761 	duk_size_t len;
19762 
19763 	DUK_ASSERT_API_ENTRY(thr);
19764 
19765 	h = duk_get_hstring(thr, idx);
19766 	if (h != NULL) {
19767 		len = DUK_HSTRING_GET_BYTELEN(h);
19768 		ret = (const char *) DUK_HSTRING_GET_DATA(h);
19769 	} else {
19770 		len = def_len;
19771 		ret = def_ptr;
19772 	}
19773 
19774 	if (out_len != NULL) {
19775 		*out_len = len;
19776 	}
19777 	return ret;
19778 }
19779 
duk_get_string_default(duk_hthread * thr,duk_idx_t idx,const char * def_value)19780 DUK_EXTERNAL const char *duk_get_string_default(duk_hthread *thr, duk_idx_t idx, const char *def_value) {
19781 	duk_hstring *h;
19782 
19783 	DUK_ASSERT_API_ENTRY(thr);
19784 
19785 	h = duk_get_hstring(thr, idx);
19786 	if (h != NULL) {
19787 		return (const char *) DUK_HSTRING_GET_DATA(h);
19788 	} else {
19789 		return def_value;
19790 	}
19791 }
19792 
duk_get_string_notsymbol(duk_hthread * thr,duk_idx_t idx)19793 DUK_INTERNAL const char *duk_get_string_notsymbol(duk_hthread *thr, duk_idx_t idx) {
19794 	duk_hstring *h;
19795 
19796 	DUK_ASSERT_API_ENTRY(thr);
19797 
19798 	h = duk_get_hstring_notsymbol(thr, idx);
19799 	if (h) {
19800 		return (const char *) DUK_HSTRING_GET_DATA(h);
19801 	} else {
19802 		return NULL;
19803 	}
19804 }
19805 
duk_require_string(duk_hthread * thr,duk_idx_t idx)19806 DUK_EXTERNAL const char *duk_require_string(duk_hthread *thr, duk_idx_t idx) {
19807 	DUK_ASSERT_API_ENTRY(thr);
19808 
19809 	return duk_require_lstring(thr, idx, NULL);
19810 }
19811 
duk_require_string_notsymbol(duk_hthread * thr,duk_idx_t idx)19812 DUK_INTERNAL const char *duk_require_string_notsymbol(duk_hthread *thr, duk_idx_t idx) {
19813 	duk_hstring *h;
19814 
19815 	DUK_ASSERT_API_ENTRY(thr);
19816 
19817 	h = duk_require_hstring_notsymbol(thr, idx);
19818 	DUK_ASSERT(h != NULL);
19819 	return (const char *) DUK_HSTRING_GET_DATA(h);
19820 }
19821 
duk_require_object(duk_hthread * thr,duk_idx_t idx)19822 DUK_EXTERNAL void duk_require_object(duk_hthread *thr, duk_idx_t idx) {
19823 	duk_tval *tv;
19824 
19825 	DUK_ASSERT_API_ENTRY(thr);
19826 
19827 	tv = duk_get_tval_or_unused(thr, idx);
19828 	DUK_ASSERT(tv != NULL);
19829 	if (DUK_UNLIKELY(!DUK_TVAL_IS_OBJECT(tv))) {
19830 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "object", DUK_STR_NOT_OBJECT);
19831 		DUK_WO_NORETURN(return;);
19832 	}
19833 }
19834 
duk__get_pointer_raw(duk_hthread * thr,duk_idx_t idx,void * def_value)19835 DUK_LOCAL void *duk__get_pointer_raw(duk_hthread *thr, duk_idx_t idx, void *def_value) {
19836 	duk_tval *tv;
19837 	void *p;
19838 
19839 	DUK_CTX_ASSERT_VALID(thr);
19840 
19841 	tv = duk_get_tval_or_unused(thr, idx);
19842 	DUK_ASSERT(tv != NULL);
19843 	if (!DUK_TVAL_IS_POINTER(tv)) {
19844 		return def_value;
19845 	}
19846 
19847 	p = DUK_TVAL_GET_POINTER(tv);  /* may be NULL */
19848 	return p;
19849 }
19850 
duk_get_pointer(duk_hthread * thr,duk_idx_t idx)19851 DUK_EXTERNAL void *duk_get_pointer(duk_hthread *thr, duk_idx_t idx) {
19852 	DUK_ASSERT_API_ENTRY(thr);
19853 	return duk__get_pointer_raw(thr, idx, NULL /*def_value*/);
19854 }
19855 
duk_opt_pointer(duk_hthread * thr,duk_idx_t idx,void * def_value)19856 DUK_EXTERNAL void *duk_opt_pointer(duk_hthread *thr, duk_idx_t idx, void *def_value) {
19857 	DUK_ASSERT_API_ENTRY(thr);
19858 
19859 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19860 		return def_value;
19861 	}
19862 	return duk_require_pointer(thr, idx);
19863 }
19864 
duk_get_pointer_default(duk_hthread * thr,duk_idx_t idx,void * def_value)19865 DUK_EXTERNAL void *duk_get_pointer_default(duk_hthread *thr, duk_idx_t idx, void *def_value) {
19866 	DUK_ASSERT_API_ENTRY(thr);
19867 	return duk__get_pointer_raw(thr, idx, def_value);
19868 }
19869 
duk_require_pointer(duk_hthread * thr,duk_idx_t idx)19870 DUK_EXTERNAL void *duk_require_pointer(duk_hthread *thr, duk_idx_t idx) {
19871 	duk_tval *tv;
19872 	void *p;
19873 
19874 	DUK_ASSERT_API_ENTRY(thr);
19875 
19876 	/* Note: here we must be wary of the fact that a pointer may be
19877 	 * valid and be a NULL.
19878 	 */
19879 	tv = duk_get_tval_or_unused(thr, idx);
19880 	DUK_ASSERT(tv != NULL);
19881 	if (DUK_UNLIKELY(!DUK_TVAL_IS_POINTER(tv))) {
19882 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "pointer", DUK_STR_NOT_POINTER);
19883 		DUK_WO_NORETURN(return NULL;);
19884 	}
19885 	p = DUK_TVAL_GET_POINTER(tv);  /* may be NULL */
19886 	return p;
19887 }
19888 
19889 #if 0  /*unused*/
19890 DUK_INTERNAL void *duk_get_voidptr(duk_hthread *thr, duk_idx_t idx) {
19891 	duk_tval *tv;
19892 	duk_heaphdr *h;
19893 
19894 	DUK_ASSERT_API_ENTRY(thr);
19895 
19896 	tv = duk_get_tval_or_unused(thr, idx);
19897 	DUK_ASSERT(tv != NULL);
19898 	if (!DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
19899 		return NULL;
19900 	}
19901 
19902 	h = DUK_TVAL_GET_HEAPHDR(tv);
19903 	DUK_ASSERT(h != NULL);
19904 	return (void *) h;
19905 }
19906 #endif
19907 
duk__get_buffer_helper(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size,void * def_ptr,duk_size_t def_size,duk_bool_t throw_flag)19908 DUK_LOCAL void *duk__get_buffer_helper(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size, duk_bool_t throw_flag) {
19909 	duk_hbuffer *h;
19910 	void *ret;
19911 	duk_size_t len;
19912 	duk_tval *tv;
19913 
19914 	DUK_CTX_ASSERT_VALID(thr);
19915 
19916 	if (out_size != NULL) {
19917 		*out_size = 0;
19918 	}
19919 
19920 	tv = duk_get_tval_or_unused(thr, idx);
19921 	DUK_ASSERT(tv != NULL);
19922 	if (DUK_LIKELY(DUK_TVAL_IS_BUFFER(tv))) {
19923 		h = DUK_TVAL_GET_BUFFER(tv);
19924 		DUK_ASSERT(h != NULL);
19925 
19926 		len = DUK_HBUFFER_GET_SIZE(h);
19927 		ret = DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);
19928 	} else {
19929 		if (throw_flag) {
19930 			DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "buffer", DUK_STR_NOT_BUFFER);
19931 			DUK_WO_NORETURN(return NULL;);
19932 		}
19933 		len = def_size;
19934 		ret = def_ptr;
19935 	}
19936 
19937 	if (out_size != NULL) {
19938 		*out_size = len;
19939 	}
19940 	return ret;
19941 }
19942 
duk_get_buffer(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size)19943 DUK_EXTERNAL void *duk_get_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
19944 	DUK_ASSERT_API_ENTRY(thr);
19945 
19946 	return duk__get_buffer_helper(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/);
19947 }
19948 
duk_opt_buffer(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size,void * def_ptr,duk_size_t def_size)19949 DUK_EXTERNAL void *duk_opt_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size) {
19950 	DUK_ASSERT_API_ENTRY(thr);
19951 
19952 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19953 		if (out_size != NULL) {
19954 			*out_size = def_size;
19955 		}
19956 		return def_ptr;
19957 	}
19958 	return duk_require_buffer(thr, idx, out_size);
19959 }
19960 
duk_get_buffer_default(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size,void * def_ptr,duk_size_t def_len)19961 DUK_EXTERNAL void *duk_get_buffer_default(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_len) {
19962 	DUK_ASSERT_API_ENTRY(thr);
19963 
19964 	return duk__get_buffer_helper(thr, idx, out_size, def_ptr, def_len, 0 /*throw_flag*/);
19965 }
19966 
duk_require_buffer(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size)19967 DUK_EXTERNAL void *duk_require_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
19968 	DUK_ASSERT_API_ENTRY(thr);
19969 
19970 	return duk__get_buffer_helper(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 1 /*throw_flag*/);
19971 }
19972 
19973 /* Get the active buffer data area for a plain buffer or a buffer object.
19974  * Return NULL if the value is not a buffer.  Note that a buffer may
19975  * have a NULL data pointer when its size is zero, the optional 'out_isbuffer'
19976  * argument allows caller to detect this reliably.
19977  */
duk_get_buffer_data_raw(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size,void * def_ptr,duk_size_t def_size,duk_bool_t throw_flag,duk_bool_t * out_isbuffer)19978 DUK_INTERNAL void *duk_get_buffer_data_raw(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size, duk_bool_t throw_flag, duk_bool_t *out_isbuffer) {
19979 	duk_tval *tv;
19980 
19981 	DUK_ASSERT_API_ENTRY(thr);
19982 
19983 	if (out_isbuffer != NULL) {
19984 		*out_isbuffer = 0;
19985 	}
19986 	if (out_size != NULL) {
19987 		*out_size = def_size;
19988 	}
19989 
19990 	tv = duk_get_tval_or_unused(thr, idx);
19991 	DUK_ASSERT(tv != NULL);
19992 
19993 	if (DUK_TVAL_IS_BUFFER(tv)) {
19994 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
19995 		DUK_ASSERT(h != NULL);
19996 		if (out_size != NULL) {
19997 			*out_size = DUK_HBUFFER_GET_SIZE(h);
19998 		}
19999 		if (out_isbuffer != NULL) {
20000 			*out_isbuffer = 1;
20001 		}
20002 		return (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);  /* may be NULL (but only if size is 0) */
20003 	}
20004 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
20005 	else if (DUK_TVAL_IS_OBJECT(tv)) {
20006 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
20007 		DUK_ASSERT(h != NULL);
20008 		if (DUK_HOBJECT_IS_BUFOBJ(h)) {
20009 			/* XXX: this is probably a useful shared helper: for a
20010 			 * duk_hbufobj, get a validated buffer pointer/length.
20011 			 */
20012 			duk_hbufobj *h_bufobj = (duk_hbufobj *) h;
20013 			DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
20014 
20015 			if (h_bufobj->buf != NULL &&
20016 			    DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
20017 				duk_uint8_t *p;
20018 
20019 				p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf);
20020 				if (out_size != NULL) {
20021 					*out_size = (duk_size_t) h_bufobj->length;
20022 				}
20023 				if (out_isbuffer != NULL) {
20024 					*out_isbuffer = 1;
20025 				}
20026 				return (void *) (p + h_bufobj->offset);
20027 			}
20028 			/* if slice not fully valid, treat as error */
20029 		}
20030 	}
20031 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
20032 
20033 	if (throw_flag) {
20034 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "buffer", DUK_STR_NOT_BUFFER);
20035 		DUK_WO_NORETURN(return NULL;);
20036 	}
20037 	return def_ptr;
20038 }
20039 
duk_get_buffer_data(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size)20040 DUK_EXTERNAL void *duk_get_buffer_data(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
20041 	DUK_ASSERT_API_ENTRY(thr);
20042 	return duk_get_buffer_data_raw(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/, NULL);
20043 }
20044 
duk_get_buffer_data_default(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size,void * def_ptr,duk_size_t def_size)20045 DUK_EXTERNAL void *duk_get_buffer_data_default(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size) {
20046 	DUK_ASSERT_API_ENTRY(thr);
20047 	return duk_get_buffer_data_raw(thr, idx, out_size, def_ptr, def_size, 0 /*throw_flag*/, NULL);
20048 }
20049 
duk_opt_buffer_data(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size,void * def_ptr,duk_size_t def_size)20050 DUK_EXTERNAL void *duk_opt_buffer_data(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size) {
20051 	DUK_ASSERT_API_ENTRY(thr);
20052 
20053 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
20054 		if (out_size != NULL) {
20055 			*out_size = def_size;
20056 		}
20057 		return def_ptr;
20058 	}
20059 	return duk_require_buffer_data(thr, idx, out_size);
20060 }
20061 
duk_require_buffer_data(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size)20062 DUK_EXTERNAL void *duk_require_buffer_data(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
20063 	DUK_ASSERT_API_ENTRY(thr);
20064 	return duk_get_buffer_data_raw(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 1 /*throw_flag*/, NULL);
20065 }
20066 
20067 /* Raw helper for getting a value from the stack, checking its tag.
20068  * The tag cannot be a number because numbers don't have an internal
20069  * tag in the packed representation.
20070  */
20071 
duk__get_tagged_heaphdr_raw(duk_hthread * thr,duk_idx_t idx,duk_uint_t tag)20072 DUK_LOCAL duk_heaphdr *duk__get_tagged_heaphdr_raw(duk_hthread *thr, duk_idx_t idx, duk_uint_t tag) {
20073 	duk_tval *tv;
20074 	duk_heaphdr *ret;
20075 
20076 	DUK_CTX_ASSERT_VALID(thr);
20077 
20078 	tv = duk_get_tval_or_unused(thr, idx);
20079 	DUK_ASSERT(tv != NULL);
20080 	if (DUK_TVAL_GET_TAG(tv) != tag) {
20081 		return (duk_heaphdr *) NULL;
20082 	}
20083 
20084 	ret = DUK_TVAL_GET_HEAPHDR(tv);
20085 	DUK_ASSERT(ret != NULL);  /* tagged null pointers should never occur */
20086 	return ret;
20087 
20088 }
20089 
duk_get_hstring(duk_hthread * thr,duk_idx_t idx)20090 DUK_INTERNAL duk_hstring *duk_get_hstring(duk_hthread *thr, duk_idx_t idx) {
20091 	DUK_ASSERT_API_ENTRY(thr);
20092 	return (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);
20093 }
20094 
duk_get_hstring_notsymbol(duk_hthread * thr,duk_idx_t idx)20095 DUK_INTERNAL duk_hstring *duk_get_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx) {
20096 	duk_hstring *h;
20097 
20098 	DUK_ASSERT_API_ENTRY(thr);
20099 
20100 	h = (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);
20101 	if (DUK_UNLIKELY(h && DUK_HSTRING_HAS_SYMBOL(h))) {
20102 		return NULL;
20103 	}
20104 	return h;
20105 }
20106 
duk_require_hstring(duk_hthread * thr,duk_idx_t idx)20107 DUK_INTERNAL duk_hstring *duk_require_hstring(duk_hthread *thr, duk_idx_t idx) {
20108 	duk_hstring *h;
20109 
20110 	DUK_ASSERT_API_ENTRY(thr);
20111 
20112 	h = (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);
20113 	if (DUK_UNLIKELY(h == NULL)) {
20114 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "string", DUK_STR_NOT_STRING);
20115 		DUK_WO_NORETURN(return NULL;);
20116 	}
20117 	return h;
20118 }
20119 
duk_require_hstring_notsymbol(duk_hthread * thr,duk_idx_t idx)20120 DUK_INTERNAL duk_hstring *duk_require_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx) {
20121 	duk_hstring *h;
20122 
20123 	DUK_ASSERT_API_ENTRY(thr);
20124 
20125 	h = (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);
20126 	if (DUK_UNLIKELY(h == NULL || DUK_HSTRING_HAS_SYMBOL(h))) {
20127 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "string", DUK_STR_NOT_STRING);
20128 		DUK_WO_NORETURN(return NULL;);
20129 	}
20130 	return h;
20131 }
20132 
duk_get_hobject(duk_hthread * thr,duk_idx_t idx)20133 DUK_INTERNAL duk_hobject *duk_get_hobject(duk_hthread *thr, duk_idx_t idx) {
20134 	DUK_ASSERT_API_ENTRY(thr);
20135 	return (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
20136 }
20137 
duk_require_hobject(duk_hthread * thr,duk_idx_t idx)20138 DUK_INTERNAL duk_hobject *duk_require_hobject(duk_hthread *thr, duk_idx_t idx) {
20139 	duk_hobject *h;
20140 
20141 	DUK_ASSERT_API_ENTRY(thr);
20142 
20143 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
20144 	if (DUK_UNLIKELY(h == NULL)) {
20145 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "object", DUK_STR_NOT_OBJECT);
20146 		DUK_WO_NORETURN(return NULL;);
20147 	}
20148 	return h;
20149 }
20150 
duk_get_hbuffer(duk_hthread * thr,duk_idx_t idx)20151 DUK_INTERNAL duk_hbuffer *duk_get_hbuffer(duk_hthread *thr, duk_idx_t idx) {
20152 	DUK_ASSERT_API_ENTRY(thr);
20153 	return (duk_hbuffer *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_BUFFER);
20154 }
20155 
duk_require_hbuffer(duk_hthread * thr,duk_idx_t idx)20156 DUK_INTERNAL duk_hbuffer *duk_require_hbuffer(duk_hthread *thr, duk_idx_t idx) {
20157 	duk_hbuffer *h;
20158 
20159 	DUK_ASSERT_API_ENTRY(thr);
20160 
20161 	h = (duk_hbuffer *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_BUFFER);
20162 	if (DUK_UNLIKELY(h == NULL)) {
20163 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "buffer", DUK_STR_NOT_BUFFER);
20164 		DUK_WO_NORETURN(return NULL;);
20165 	}
20166 	return h;
20167 }
20168 
duk_get_hthread(duk_hthread * thr,duk_idx_t idx)20169 DUK_INTERNAL duk_hthread *duk_get_hthread(duk_hthread *thr, duk_idx_t idx) {
20170 	duk_hobject *h;
20171 
20172 	DUK_ASSERT_API_ENTRY(thr);
20173 
20174 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
20175 	if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_IS_THREAD(h))) {
20176 		h = NULL;
20177 	}
20178 	return (duk_hthread *) h;
20179 }
20180 
duk_require_hthread(duk_hthread * thr,duk_idx_t idx)20181 DUK_INTERNAL duk_hthread *duk_require_hthread(duk_hthread *thr, duk_idx_t idx) {
20182 	duk_hobject *h;
20183 
20184 	DUK_ASSERT_API_ENTRY(thr);
20185 
20186 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
20187 	if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_THREAD(h)))) {
20188 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "thread", DUK_STR_NOT_THREAD);
20189 		DUK_WO_NORETURN(return NULL;);
20190 	}
20191 	return (duk_hthread *) h;
20192 }
20193 
duk_get_hcompfunc(duk_hthread * thr,duk_idx_t idx)20194 DUK_INTERNAL duk_hcompfunc *duk_get_hcompfunc(duk_hthread *thr, duk_idx_t idx) {
20195 	duk_hobject *h;
20196 
20197 	DUK_ASSERT_API_ENTRY(thr);
20198 
20199 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
20200 	if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_IS_COMPFUNC(h))) {
20201 		h = NULL;
20202 	}
20203 	return (duk_hcompfunc *) h;
20204 }
20205 
duk_require_hcompfunc(duk_hthread * thr,duk_idx_t idx)20206 DUK_INTERNAL duk_hcompfunc *duk_require_hcompfunc(duk_hthread *thr, duk_idx_t idx) {
20207 	duk_hobject *h;
20208 
20209 	DUK_ASSERT_API_ENTRY(thr);
20210 
20211 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
20212 	if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_COMPFUNC(h)))) {
20213 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "compiledfunction", DUK_STR_NOT_COMPFUNC);
20214 		DUK_WO_NORETURN(return NULL;);
20215 	}
20216 	return (duk_hcompfunc *) h;
20217 }
20218 
duk_get_hnatfunc(duk_hthread * thr,duk_idx_t idx)20219 DUK_INTERNAL duk_hnatfunc *duk_get_hnatfunc(duk_hthread *thr, duk_idx_t idx) {
20220 	duk_hobject *h;
20221 
20222 	DUK_ASSERT_API_ENTRY(thr);
20223 
20224 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
20225 	if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_IS_NATFUNC(h))) {
20226 		h = NULL;
20227 	}
20228 	return (duk_hnatfunc *) h;
20229 }
20230 
duk_require_hnatfunc(duk_hthread * thr,duk_idx_t idx)20231 DUK_INTERNAL duk_hnatfunc *duk_require_hnatfunc(duk_hthread *thr, duk_idx_t idx) {
20232 	duk_hobject *h;
20233 
20234 	DUK_ASSERT_API_ENTRY(thr);
20235 
20236 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
20237 	if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_NATFUNC(h)))) {
20238 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "nativefunction", DUK_STR_NOT_NATFUNC);
20239 		DUK_WO_NORETURN(return NULL;);
20240 	}
20241 	return (duk_hnatfunc *) h;
20242 }
20243 
duk_get_c_function(duk_hthread * thr,duk_idx_t idx)20244 DUK_EXTERNAL duk_c_function duk_get_c_function(duk_hthread *thr, duk_idx_t idx) {
20245 	duk_tval *tv;
20246 	duk_hobject *h;
20247 	duk_hnatfunc *f;
20248 
20249 	DUK_ASSERT_API_ENTRY(thr);
20250 
20251 	tv = duk_get_tval_or_unused(thr, idx);
20252 	DUK_ASSERT(tv != NULL);
20253 	if (DUK_UNLIKELY(!DUK_TVAL_IS_OBJECT(tv))) {
20254 		return NULL;
20255 	}
20256 	h = DUK_TVAL_GET_OBJECT(tv);
20257 	DUK_ASSERT(h != NULL);
20258 
20259 	if (DUK_UNLIKELY(!DUK_HOBJECT_IS_NATFUNC(h))) {
20260 		return NULL;
20261 	}
20262 	DUK_ASSERT(DUK_HOBJECT_HAS_NATFUNC(h));
20263 	f = (duk_hnatfunc *) h;
20264 
20265 	return f->func;
20266 }
20267 
duk_opt_c_function(duk_hthread * thr,duk_idx_t idx,duk_c_function def_value)20268 DUK_EXTERNAL duk_c_function duk_opt_c_function(duk_hthread *thr, duk_idx_t idx, duk_c_function def_value) {
20269 	DUK_ASSERT_API_ENTRY(thr);
20270 
20271 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
20272 		return def_value;
20273 	}
20274 	return duk_require_c_function(thr, idx);
20275 }
20276 
duk_get_c_function_default(duk_hthread * thr,duk_idx_t idx,duk_c_function def_value)20277 DUK_EXTERNAL duk_c_function duk_get_c_function_default(duk_hthread *thr, duk_idx_t idx, duk_c_function def_value) {
20278 	duk_c_function ret;
20279 
20280 	DUK_ASSERT_API_ENTRY(thr);
20281 
20282 	ret = duk_get_c_function(thr, idx);
20283 	if (ret != NULL) {
20284 		return ret;
20285 	}
20286 
20287 	return def_value;
20288 }
20289 
duk_require_c_function(duk_hthread * thr,duk_idx_t idx)20290 DUK_EXTERNAL duk_c_function duk_require_c_function(duk_hthread *thr, duk_idx_t idx) {
20291 	duk_c_function ret;
20292 
20293 	DUK_ASSERT_API_ENTRY(thr);
20294 
20295 	ret = duk_get_c_function(thr, idx);
20296 	if (DUK_UNLIKELY(!ret)) {
20297 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "nativefunction", DUK_STR_NOT_NATFUNC);
20298 		DUK_WO_NORETURN(return ret;);
20299 	}
20300 	return ret;
20301 }
20302 
duk_require_function(duk_hthread * thr,duk_idx_t idx)20303 DUK_EXTERNAL void duk_require_function(duk_hthread *thr, duk_idx_t idx) {
20304 	DUK_ASSERT_API_ENTRY(thr);
20305 	if (DUK_UNLIKELY(!duk_is_function(thr, idx))) {
20306 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "function", DUK_STR_NOT_FUNCTION);
20307 		DUK_WO_NORETURN(return;);
20308 	}
20309 }
20310 
duk_require_constructable(duk_hthread * thr,duk_idx_t idx)20311 DUK_EXTERNAL void duk_require_constructable(duk_hthread *thr, duk_idx_t idx) {
20312 	duk_hobject *h;
20313 
20314 	DUK_ASSERT_API_ENTRY(thr);
20315 
20316 	h = duk_require_hobject_accept_mask(thr, idx, DUK_TYPE_MASK_LIGHTFUNC);
20317 	if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_HAS_CONSTRUCTABLE(h))) {
20318 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "constructable", DUK_STR_NOT_CONSTRUCTABLE);
20319 		DUK_WO_NORETURN(return;);
20320 	}
20321 	/* Lightfuncs (h == NULL) are constructable. */
20322 }
20323 
duk_get_context(duk_hthread * thr,duk_idx_t idx)20324 DUK_EXTERNAL duk_hthread *duk_get_context(duk_hthread *thr, duk_idx_t idx) {
20325 	DUK_ASSERT_API_ENTRY(thr);
20326 
20327 	return duk_get_hthread(thr, idx);
20328 }
20329 
duk_require_context(duk_hthread * thr,duk_idx_t idx)20330 DUK_EXTERNAL duk_hthread *duk_require_context(duk_hthread *thr, duk_idx_t idx) {
20331 	DUK_ASSERT_API_ENTRY(thr);
20332 
20333 	return duk_require_hthread(thr, idx);
20334 }
20335 
duk_opt_context(duk_hthread * thr,duk_idx_t idx,duk_hthread * def_value)20336 DUK_EXTERNAL duk_hthread *duk_opt_context(duk_hthread *thr, duk_idx_t idx, duk_hthread *def_value) {
20337 	DUK_ASSERT_API_ENTRY(thr);
20338 
20339 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
20340 		return def_value;
20341 	}
20342 	return duk_require_context(thr, idx);
20343 }
20344 
duk_get_context_default(duk_hthread * thr,duk_idx_t idx,duk_hthread * def_value)20345 DUK_EXTERNAL duk_hthread *duk_get_context_default(duk_hthread *thr, duk_idx_t idx, duk_hthread *def_value) {
20346 	duk_hthread *ret;
20347 
20348 	DUK_ASSERT_API_ENTRY(thr);
20349 
20350 	ret = duk_get_context(thr, idx);
20351 	if (ret != NULL) {
20352 		return ret;
20353 	}
20354 
20355 	return def_value;
20356 }
20357 
duk_get_heapptr(duk_hthread * thr,duk_idx_t idx)20358 DUK_EXTERNAL void *duk_get_heapptr(duk_hthread *thr, duk_idx_t idx) {
20359 	duk_tval *tv;
20360 	void *ret;
20361 
20362 	DUK_ASSERT_API_ENTRY(thr);
20363 
20364 	tv = duk_get_tval_or_unused(thr, idx);
20365 	DUK_ASSERT(tv != NULL);
20366 	if (DUK_UNLIKELY(!DUK_TVAL_IS_HEAP_ALLOCATED(tv))) {
20367 		return (void *) NULL;
20368 	}
20369 
20370 	ret = (void *) DUK_TVAL_GET_HEAPHDR(tv);
20371 	DUK_ASSERT(ret != NULL);
20372 	return ret;
20373 }
20374 
duk_opt_heapptr(duk_hthread * thr,duk_idx_t idx,void * def_value)20375 DUK_EXTERNAL void *duk_opt_heapptr(duk_hthread *thr, duk_idx_t idx, void *def_value) {
20376 	DUK_ASSERT_API_ENTRY(thr);
20377 
20378 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
20379 		return def_value;
20380 	}
20381 	return duk_require_heapptr(thr, idx);
20382 }
20383 
duk_get_heapptr_default(duk_hthread * thr,duk_idx_t idx,void * def_value)20384 DUK_EXTERNAL void *duk_get_heapptr_default(duk_hthread *thr, duk_idx_t idx, void *def_value) {
20385 	void *ret;
20386 
20387 	DUK_ASSERT_API_ENTRY(thr);
20388 
20389 	ret = duk_get_heapptr(thr, idx);
20390 	if (ret != NULL) {
20391 		return ret;
20392 	}
20393 
20394 	return def_value;
20395 }
20396 
duk_require_heapptr(duk_hthread * thr,duk_idx_t idx)20397 DUK_EXTERNAL void *duk_require_heapptr(duk_hthread *thr, duk_idx_t idx) {
20398 	duk_tval *tv;
20399 	void *ret;
20400 
20401 	DUK_ASSERT_API_ENTRY(thr);
20402 
20403 	tv = duk_get_tval_or_unused(thr, idx);
20404 	DUK_ASSERT(tv != NULL);
20405 	if (DUK_UNLIKELY(!DUK_TVAL_IS_HEAP_ALLOCATED(tv))) {
20406 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "heapobject", DUK_STR_UNEXPECTED_TYPE);
20407 		DUK_WO_NORETURN(return NULL;);
20408 	}
20409 
20410 	ret = (void *) DUK_TVAL_GET_HEAPHDR(tv);
20411 	DUK_ASSERT(ret != NULL);
20412 	return ret;
20413 }
20414 
20415 /* Internal helper for getting/requiring a duk_hobject with possible promotion. */
duk__get_hobject_promote_mask_raw(duk_hthread * thr,duk_idx_t idx,duk_uint_t type_mask)20416 DUK_LOCAL duk_hobject *duk__get_hobject_promote_mask_raw(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {
20417 	duk_uint_t val_mask;
20418 	duk_hobject *res;
20419 
20420 	DUK_CTX_ASSERT_VALID(thr);
20421 
20422 	res = duk_get_hobject(thr, idx);  /* common case, not promoted */
20423 	if (DUK_LIKELY(res != NULL)) {
20424 		DUK_ASSERT(res != NULL);
20425 		return res;
20426 	}
20427 
20428 	val_mask = duk_get_type_mask(thr, idx);
20429 	if (val_mask & type_mask) {
20430 		if (type_mask & DUK_TYPE_MASK_PROMOTE) {
20431 			res = duk_to_hobject(thr, idx);
20432 			DUK_ASSERT(res != NULL);
20433 			return res;
20434 		} else {
20435 			return NULL;  /* accept without promoting */
20436 		}
20437 	}
20438 
20439 	if (type_mask & DUK_TYPE_MASK_THROW) {
20440 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "object", DUK_STR_NOT_OBJECT);
20441 		DUK_WO_NORETURN(return NULL;);
20442 	}
20443 	return NULL;
20444 }
20445 
20446 /* Get a duk_hobject * at 'idx'; if the value is not an object but matches the
20447  * supplied 'type_mask', promote it to an object and return the duk_hobject *.
20448  * This is useful for call sites which want an object but also accept a plain
20449  * buffer and/or a lightfunc which gets automatically promoted to an object.
20450  * Return value is NULL if value is neither an object nor a plain type allowed
20451  * by the mask.
20452  */
duk_get_hobject_promote_mask(duk_hthread * thr,duk_idx_t idx,duk_uint_t type_mask)20453 DUK_INTERNAL duk_hobject *duk_get_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {
20454 	DUK_ASSERT_API_ENTRY(thr);
20455 	return duk__get_hobject_promote_mask_raw(thr, idx, type_mask | DUK_TYPE_MASK_PROMOTE);
20456 }
20457 
20458 /* Like duk_get_hobject_promote_mask() but throw a TypeError instead of
20459  * returning a NULL.
20460  */
duk_require_hobject_promote_mask(duk_hthread * thr,duk_idx_t idx,duk_uint_t type_mask)20461 DUK_INTERNAL duk_hobject *duk_require_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {
20462 	DUK_ASSERT_API_ENTRY(thr);
20463 	return duk__get_hobject_promote_mask_raw(thr, idx, type_mask | DUK_TYPE_MASK_THROW | DUK_TYPE_MASK_PROMOTE);
20464 }
20465 
20466 /* Require a duk_hobject * at 'idx'; if the value is not an object but matches the
20467  * supplied 'type_mask', return a NULL instead.  Otherwise throw a TypeError.
20468  */
duk_require_hobject_accept_mask(duk_hthread * thr,duk_idx_t idx,duk_uint_t type_mask)20469 DUK_INTERNAL duk_hobject *duk_require_hobject_accept_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {
20470 	DUK_ASSERT_API_ENTRY(thr);
20471 	return duk__get_hobject_promote_mask_raw(thr, idx, type_mask | DUK_TYPE_MASK_THROW);
20472 }
20473 
duk_get_hobject_with_class(duk_hthread * thr,duk_idx_t idx,duk_small_uint_t classnum)20474 DUK_INTERNAL duk_hobject *duk_get_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum) {
20475 	duk_hobject *h;
20476 
20477 	DUK_ASSERT_API_ENTRY(thr);
20478 	DUK_ASSERT_DISABLE(classnum >= 0);  /* unsigned */
20479 	DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
20480 
20481 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
20482 	if (DUK_UNLIKELY(h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) != classnum)) {
20483 		h = NULL;
20484 	}
20485 	return h;
20486 }
20487 
duk_require_hobject_with_class(duk_hthread * thr,duk_idx_t idx,duk_small_uint_t classnum)20488 DUK_INTERNAL duk_hobject *duk_require_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum) {
20489 	duk_hobject *h;
20490 
20491 	DUK_ASSERT_API_ENTRY(thr);
20492 	DUK_ASSERT_DISABLE(classnum >= 0);  /* unsigned */
20493 	DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
20494 
20495 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
20496 	if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) == classnum))) {
20497 		duk_hstring *h_class;
20498 		h_class = DUK_HTHREAD_GET_STRING(thr, DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum));
20499 		DUK_UNREF(h_class);
20500 
20501 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, (const char *) DUK_HSTRING_GET_DATA(h_class), DUK_STR_UNEXPECTED_TYPE);
20502 		DUK_WO_NORETURN(return NULL;);
20503 	}
20504 	return h;
20505 }
20506 
duk_get_length(duk_hthread * thr,duk_idx_t idx)20507 DUK_EXTERNAL duk_size_t duk_get_length(duk_hthread *thr, duk_idx_t idx) {
20508 	duk_tval *tv;
20509 
20510 	DUK_ASSERT_API_ENTRY(thr);
20511 
20512 	tv = duk_get_tval_or_unused(thr, idx);
20513 	DUK_ASSERT(tv != NULL);
20514 
20515 	switch (DUK_TVAL_GET_TAG(tv)) {
20516 	case DUK_TAG_UNDEFINED:
20517 	case DUK_TAG_NULL:
20518 	case DUK_TAG_BOOLEAN:
20519 	case DUK_TAG_POINTER:
20520 		return 0;
20521 #if defined(DUK_USE_PREFER_SIZE)
20522 	/* String and buffer have a virtual non-configurable .length property
20523 	 * which is within size_t range so it can be looked up without specific
20524 	 * type checks.  Lightfuncs inherit from %NativeFunctionPrototype%
20525 	 * which provides an inherited .length accessor; it could be overwritten
20526 	 * to produce unexpected types or values, but just number convert and
20527 	 * duk_size_t cast for now.
20528 	 */
20529 	case DUK_TAG_STRING:
20530 	case DUK_TAG_BUFFER:
20531 	case DUK_TAG_LIGHTFUNC: {
20532 		duk_size_t ret;
20533 		duk_get_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);
20534 		ret = (duk_size_t) duk_to_number_m1(thr);
20535 		duk_pop_unsafe(thr);
20536 		return ret;
20537 	}
20538 #else  /* DUK_USE_PREFER_SIZE */
20539 	case DUK_TAG_STRING: {
20540 		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
20541 		DUK_ASSERT(h != NULL);
20542 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
20543 			return 0;
20544 		}
20545 		return (duk_size_t) DUK_HSTRING_GET_CHARLEN(h);
20546 	}
20547 	case DUK_TAG_BUFFER: {
20548 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
20549 		DUK_ASSERT(h != NULL);
20550 		return (duk_size_t) DUK_HBUFFER_GET_SIZE(h);
20551 	}
20552 	case DUK_TAG_LIGHTFUNC: {
20553 		/* We could look up the length from the lightfunc duk_tval,
20554 		 * but since Duktape 2.2 lightfunc .length comes from
20555 		 * %NativeFunctionPrototype% which can be overridden, so
20556 		 * look up the property explicitly.
20557 		 */
20558 		duk_size_t ret;
20559 		duk_get_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);
20560 		ret = (duk_size_t) duk_to_number_m1(thr);
20561 		duk_pop_unsafe(thr);
20562 		return ret;
20563 	}
20564 #endif  /* DUK_USE_PREFER_SIZE */
20565 	case DUK_TAG_OBJECT: {
20566 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
20567 		DUK_ASSERT(h != NULL);
20568 		return (duk_size_t) duk_hobject_get_length(thr, h);
20569 	}
20570 #if defined(DUK_USE_FASTINT)
20571 	case DUK_TAG_FASTINT:
20572 #endif
20573 	default:
20574 		/* number or 'unused' */
20575 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv) || DUK_TVAL_IS_UNUSED(tv));
20576 		return 0;
20577 	}
20578 
20579 	DUK_UNREACHABLE();
20580 }
20581 
20582 /*
20583  *  duk_known_xxx() helpers
20584  *
20585  *  Used internally when we're 100% sure that a certain index is valid and
20586  *  contains an object of a certain type.  For example, if we duk_push_object()
20587  *  we can then safely duk_known_hobject(thr, -1).  These helpers just assert
20588  *  for the index and type, and if the assumptions are not valid, memory unsafe
20589  *  behavior happens.
20590  */
20591 
duk__known_heaphdr(duk_hthread * thr,duk_idx_t idx)20592 DUK_LOCAL duk_heaphdr *duk__known_heaphdr(duk_hthread *thr, duk_idx_t idx) {
20593 	duk_tval *tv;
20594 	duk_heaphdr *h;
20595 
20596 	DUK_CTX_ASSERT_VALID(thr);
20597 	if (idx < 0) {
20598 		tv = thr->valstack_top + idx;
20599 	} else {
20600 		tv = thr->valstack_bottom + idx;
20601 	}
20602 	DUK_ASSERT(tv >= thr->valstack_bottom);
20603 	DUK_ASSERT(tv < thr->valstack_top);
20604 	h = DUK_TVAL_GET_HEAPHDR(tv);
20605 	DUK_ASSERT(h != NULL);
20606 	return h;
20607 }
20608 
duk_known_hstring(duk_hthread * thr,duk_idx_t idx)20609 DUK_INTERNAL duk_hstring *duk_known_hstring(duk_hthread *thr, duk_idx_t idx) {
20610 	DUK_ASSERT_API_ENTRY(thr);
20611 	DUK_ASSERT(duk_get_hstring(thr, idx) != NULL);
20612 	return (duk_hstring *) duk__known_heaphdr(thr, idx);
20613 }
20614 
duk_known_hobject(duk_hthread * thr,duk_idx_t idx)20615 DUK_INTERNAL duk_hobject *duk_known_hobject(duk_hthread *thr, duk_idx_t idx) {
20616 	DUK_ASSERT_API_ENTRY(thr);
20617 	DUK_ASSERT(duk_get_hobject(thr, idx) != NULL);
20618 	return (duk_hobject *) duk__known_heaphdr(thr, idx);
20619 }
20620 
duk_known_hbuffer(duk_hthread * thr,duk_idx_t idx)20621 DUK_INTERNAL duk_hbuffer *duk_known_hbuffer(duk_hthread *thr, duk_idx_t idx) {
20622 	DUK_ASSERT_API_ENTRY(thr);
20623 	DUK_ASSERT(duk_get_hbuffer(thr, idx) != NULL);
20624 	return (duk_hbuffer *) duk__known_heaphdr(thr, idx);
20625 }
20626 
duk_known_hcompfunc(duk_hthread * thr,duk_idx_t idx)20627 DUK_INTERNAL duk_hcompfunc *duk_known_hcompfunc(duk_hthread *thr, duk_idx_t idx) {
20628 	DUK_ASSERT_API_ENTRY(thr);
20629 	DUK_ASSERT(duk_get_hcompfunc(thr, idx) != NULL);
20630 	return (duk_hcompfunc *) duk__known_heaphdr(thr, idx);
20631 }
20632 
duk_known_hnatfunc(duk_hthread * thr,duk_idx_t idx)20633 DUK_INTERNAL duk_hnatfunc *duk_known_hnatfunc(duk_hthread *thr, duk_idx_t idx) {
20634 	DUK_ASSERT_API_ENTRY(thr);
20635 	DUK_ASSERT(duk_get_hnatfunc(thr, idx) != NULL);
20636 	return (duk_hnatfunc *) duk__known_heaphdr(thr, idx);
20637 }
20638 
duk_set_length(duk_hthread * thr,duk_idx_t idx,duk_size_t len)20639 DUK_EXTERNAL void duk_set_length(duk_hthread *thr, duk_idx_t idx, duk_size_t len) {
20640 	DUK_ASSERT_API_ENTRY(thr);
20641 
20642 	idx = duk_normalize_index(thr, idx);
20643 	duk_push_uint(thr, (duk_uint_t) len);
20644 	duk_put_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);
20645 }
20646 
20647 /*
20648  *  Conversions and coercions
20649  *
20650  *  The conversion/coercions are in-place operations on the value stack.
20651  *  Some operations are implemented here directly, while others call a
20652  *  helper in duk_js_ops.c after validating arguments.
20653  */
20654 
20655 /* E5 Section 8.12.8 */
20656 
duk__defaultvalue_coerce_attempt(duk_hthread * thr,duk_idx_t idx,duk_small_uint_t func_stridx)20657 DUK_LOCAL duk_bool_t duk__defaultvalue_coerce_attempt(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t func_stridx) {
20658 	if (duk_get_prop_stridx(thr, idx, func_stridx)) {
20659 		/* [ ... func ] */
20660 		if (duk_is_callable(thr, -1)) {
20661 			duk_dup(thr, idx);         /* -> [ ... func this ] */
20662 			duk_call_method(thr, 0);     /* -> [ ... retval ] */
20663 			if (duk_is_primitive(thr, -1)) {
20664 				duk_replace(thr, idx);
20665 				return 1;
20666 			}
20667 			/* [ ... retval ]; popped below */
20668 		}
20669 	}
20670 	duk_pop_unsafe(thr);  /* [ ... func/retval ] -> [ ... ] */
20671 	return 0;
20672 }
20673 
duk_to_undefined(duk_hthread * thr,duk_idx_t idx)20674 DUK_EXTERNAL void duk_to_undefined(duk_hthread *thr, duk_idx_t idx) {
20675 	duk_tval *tv;
20676 
20677 	DUK_ASSERT_API_ENTRY(thr);
20678 
20679 	tv = duk_require_tval(thr, idx);
20680 	DUK_ASSERT(tv != NULL);
20681 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
20682 }
20683 
duk_to_null(duk_hthread * thr,duk_idx_t idx)20684 DUK_EXTERNAL void duk_to_null(duk_hthread *thr, duk_idx_t idx) {
20685 	duk_tval *tv;
20686 
20687 	DUK_ASSERT_API_ENTRY(thr);
20688 
20689 	tv = duk_require_tval(thr, idx);
20690 	DUK_ASSERT(tv != NULL);
20691 	DUK_TVAL_SET_NULL_UPDREF(thr, tv);  /* side effects */
20692 }
20693 
20694 /* E5 Section 9.1 */
20695 DUK_LOCAL const char * const duk__toprim_hint_strings[3] = {
20696 	"default", "string", "number"
20697 };
duk__to_primitive_helper(duk_hthread * thr,duk_idx_t idx,duk_int_t hint,duk_bool_t check_symbol)20698 DUK_LOCAL void duk__to_primitive_helper(duk_hthread *thr, duk_idx_t idx, duk_int_t hint, duk_bool_t check_symbol) {
20699 	/* Inline initializer for coercers[] is not allowed by old compilers like BCC. */
20700 	duk_small_uint_t coercers[2];
20701 
20702 	DUK_ASSERT_API_ENTRY(thr);
20703 	DUK_ASSERT(hint == DUK_HINT_NONE || hint == DUK_HINT_NUMBER || hint == DUK_HINT_STRING);
20704 
20705 	idx = duk_require_normalize_index(thr, idx);
20706 
20707 	/* If already primitive, return as is. */
20708 	if (!duk_check_type_mask(thr, idx, DUK_TYPE_MASK_OBJECT |
20709 	                                   DUK_TYPE_MASK_LIGHTFUNC |
20710 	                                   DUK_TYPE_MASK_BUFFER)) {
20711 		DUK_ASSERT(!duk_is_buffer(thr, idx));  /* duk_to_string() relies on this behavior */
20712 		return;
20713 	}
20714 
20715 	/* @@toPrimitive lookup.  Also do for plain buffers and lightfuncs
20716 	 * which mimic objects.
20717 	 */
20718 	if (check_symbol && duk_get_method_stridx(thr, idx, DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE)) {
20719 		DUK_ASSERT(hint >= 0 && (duk_size_t) hint < sizeof(duk__toprim_hint_strings) / sizeof(const char *));
20720 		duk_dup(thr, idx);
20721 		duk_push_string(thr, duk__toprim_hint_strings[hint]);
20722 		duk_call_method(thr, 1);  /* [ ... method value hint ] -> [ ... res] */
20723 		if (duk_check_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT |
20724 	                                         DUK_TYPE_MASK_LIGHTFUNC |
20725 		                                 DUK_TYPE_MASK_BUFFER)) {
20726 			goto fail;
20727 		}
20728 		duk_replace(thr, idx);
20729 		return;
20730 	}
20731 
20732 	/* Objects are coerced based on E5 specification.
20733 	 * Lightfuncs are coerced because they behave like
20734 	 * objects even if they're internally a primitive
20735 	 * type.  Same applies to plain buffers, which behave
20736 	 * like ArrayBuffer objects since Duktape 2.x.
20737 	 */
20738 
20739 	/* Hint magic for Date is unnecessary in ES2015 because of
20740 	 * Date.prototype[@@toPrimitive].  However, it is needed if
20741 	 * symbol support is not enabled.
20742 	 */
20743 #if defined(DUK_USE_SYMBOL_BUILTIN)
20744 	if (hint == DUK_HINT_NONE) {
20745 		hint = DUK_HINT_NUMBER;
20746 	}
20747 #else  /* DUK_USE_SYMBOL_BUILTIN */
20748 	if (hint == DUK_HINT_NONE) {
20749 		duk_small_uint_t class_number;
20750 
20751 		class_number = duk_get_class_number(thr, idx);
20752 		if (class_number == DUK_HOBJECT_CLASS_DATE) {
20753 			hint = DUK_HINT_STRING;
20754 		} else {
20755 			hint = DUK_HINT_NUMBER;
20756 		}
20757 	}
20758 #endif  /* DUK_USE_SYMBOL_BUILTIN */
20759 
20760 	coercers[0] = DUK_STRIDX_VALUE_OF;
20761 	coercers[1] = DUK_STRIDX_TO_STRING;
20762 	if (hint == DUK_HINT_STRING) {
20763 		coercers[0] = DUK_STRIDX_TO_STRING;
20764 		coercers[1] = DUK_STRIDX_VALUE_OF;
20765 	}
20766 
20767 	if (duk__defaultvalue_coerce_attempt(thr, idx, coercers[0])) {
20768 		DUK_ASSERT(!duk_is_buffer(thr, idx));  /* duk_to_string() relies on this behavior */
20769 		return;
20770 	}
20771 
20772 	if (duk__defaultvalue_coerce_attempt(thr, idx, coercers[1])) {
20773 		DUK_ASSERT(!duk_is_buffer(thr, idx));  /* duk_to_string() relies on this behavior */
20774 		return;
20775 	}
20776 
20777  fail:
20778 	DUK_ERROR_TYPE(thr, DUK_STR_TOPRIMITIVE_FAILED);
20779 	DUK_WO_NORETURN(return;);
20780 }
20781 
duk_to_primitive(duk_hthread * thr,duk_idx_t idx,duk_int_t hint)20782 DUK_EXTERNAL void duk_to_primitive(duk_hthread *thr, duk_idx_t idx, duk_int_t hint) {
20783 	duk__to_primitive_helper(thr, idx, hint, 1 /*check_symbol*/);
20784 }
20785 
20786 #if defined(DUK_USE_SYMBOL_BUILTIN)
duk_to_primitive_ordinary(duk_hthread * thr,duk_idx_t idx,duk_int_t hint)20787 DUK_INTERNAL void duk_to_primitive_ordinary(duk_hthread *thr, duk_idx_t idx, duk_int_t hint) {
20788 	duk__to_primitive_helper(thr, idx, hint, 0 /*check_symbol*/);
20789 }
20790 #endif
20791 
20792 /* E5 Section 9.2 */
duk_to_boolean(duk_hthread * thr,duk_idx_t idx)20793 DUK_EXTERNAL duk_bool_t duk_to_boolean(duk_hthread *thr, duk_idx_t idx) {
20794 	duk_tval *tv;
20795 	duk_bool_t val;
20796 
20797 	DUK_ASSERT_API_ENTRY(thr);
20798 
20799 	idx = duk_require_normalize_index(thr, idx);
20800 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
20801 	DUK_ASSERT(tv != NULL);
20802 
20803 	val = duk_js_toboolean(tv);
20804 	DUK_ASSERT(val == 0 || val == 1);
20805 
20806 	/* Note: no need to re-lookup tv, conversion is side effect free. */
20807 	DUK_ASSERT(tv != NULL);
20808 	DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv, val);  /* side effects */
20809 	return val;
20810 }
20811 
duk_to_boolean_top_pop(duk_hthread * thr)20812 DUK_INTERNAL duk_bool_t duk_to_boolean_top_pop(duk_hthread *thr) {
20813 	duk_tval *tv;
20814 	duk_bool_t val;
20815 
20816 	DUK_ASSERT_API_ENTRY(thr);
20817 
20818 	tv = duk_require_tval(thr, -1);
20819 	DUK_ASSERT(tv != NULL);
20820 
20821 	val = duk_js_toboolean(tv);
20822 	DUK_ASSERT(val == 0 || val == 1);
20823 
20824 	duk_pop_unsafe(thr);
20825 	return val;
20826 }
20827 
duk_to_number(duk_hthread * thr,duk_idx_t idx)20828 DUK_EXTERNAL duk_double_t duk_to_number(duk_hthread *thr, duk_idx_t idx) {
20829 	duk_tval *tv;
20830 	duk_double_t d;
20831 
20832 	DUK_ASSERT_API_ENTRY(thr);
20833 
20834 	/* XXX: No need to normalize; the whole operation could be inlined here to
20835 	 * avoid 'tv' re-lookup.
20836 	 */
20837 	idx = duk_require_normalize_index(thr, idx);
20838 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
20839 	DUK_ASSERT(tv != NULL);
20840 	d = duk_js_tonumber(thr, tv);  /* XXX: fastint coercion? now result will always be a non-fastint */
20841 
20842 	/* ToNumber() may have side effects so must relookup 'tv'. */
20843 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
20844 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d);  /* side effects */
20845 	return d;
20846 }
20847 
duk_to_number_m1(duk_hthread * thr)20848 DUK_INTERNAL duk_double_t duk_to_number_m1(duk_hthread *thr) {
20849 	DUK_ASSERT_API_ENTRY(thr);
20850 	return duk_to_number(thr, -1);
20851 }
duk_to_number_m2(duk_hthread * thr)20852 DUK_INTERNAL duk_double_t duk_to_number_m2(duk_hthread *thr) {
20853 	DUK_ASSERT_API_ENTRY(thr);
20854 	return duk_to_number(thr, -2);
20855 }
20856 
duk_to_number_tval(duk_hthread * thr,duk_tval * tv)20857 DUK_INTERNAL duk_double_t duk_to_number_tval(duk_hthread *thr, duk_tval *tv) {
20858 #if defined(DUK_USE_PREFER_SIZE)
20859 	duk_double_t res;
20860 
20861 	DUK_ASSERT_API_ENTRY(thr);
20862 
20863 	duk_push_tval(thr, tv);
20864 	res = duk_to_number_m1(thr);
20865 	duk_pop_unsafe(thr);
20866 	return res;
20867 #else
20868 	duk_double_t res;
20869 	duk_tval *tv_dst;
20870 
20871 	DUK_ASSERT_API_ENTRY(thr);
20872 	DUK__ASSERT_SPACE();
20873 
20874 	tv_dst = thr->valstack_top++;
20875 	DUK_TVAL_SET_TVAL(tv_dst, tv);
20876 	DUK_TVAL_INCREF(thr, tv_dst);  /* decref not necessary */
20877 	res = duk_to_number_m1(thr);  /* invalidates tv_dst */
20878 
20879 	tv_dst = --thr->valstack_top;
20880 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_dst));
20881 	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv_dst));  /* plain number */
20882 	DUK_TVAL_SET_UNDEFINED(tv_dst);  /* valstack init policy */
20883 
20884 	return res;
20885 #endif
20886 }
20887 
20888 /* XXX: combine all the integer conversions: they share everything
20889  * but the helper function for coercion.
20890  */
20891 
20892 typedef duk_double_t (*duk__toint_coercer)(duk_hthread *thr, duk_tval *tv);
20893 
duk__to_int_uint_helper(duk_hthread * thr,duk_idx_t idx,duk__toint_coercer coerce_func)20894 DUK_LOCAL duk_double_t duk__to_int_uint_helper(duk_hthread *thr, duk_idx_t idx, duk__toint_coercer coerce_func) {
20895 	duk_tval *tv;
20896 	duk_double_t d;
20897 
20898 	DUK_CTX_ASSERT_VALID(thr);
20899 
20900 	tv = duk_require_tval(thr, idx);
20901 	DUK_ASSERT(tv != NULL);
20902 
20903 #if defined(DUK_USE_FASTINT)
20904 	/* If argument is a fastint, guarantee that it remains one.
20905 	 * There's no downgrade check for other cases.
20906 	 */
20907 	if (DUK_TVAL_IS_FASTINT(tv)) {
20908 		/* XXX: Unnecessary conversion back and forth. */
20909 		return (duk_double_t) DUK_TVAL_GET_FASTINT(tv);
20910 	}
20911 #endif
20912 	d = coerce_func(thr, tv);
20913 
20914 	/* XXX: fastint? */
20915 
20916 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
20917 	tv = duk_require_tval(thr, idx);
20918 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d);  /* side effects */
20919 	return d;
20920 }
20921 
duk_to_int(duk_hthread * thr,duk_idx_t idx)20922 DUK_EXTERNAL duk_int_t duk_to_int(duk_hthread *thr, duk_idx_t idx) {
20923 	/* Value coercion (in stack): ToInteger(), E5 Section 9.4,
20924 	 * API return value coercion: custom.
20925 	 */
20926 	DUK_ASSERT_API_ENTRY(thr);
20927 	(void) duk__to_int_uint_helper(thr, idx, duk_js_tointeger);
20928 	return (duk_int_t) duk__api_coerce_d2i(thr, idx, 0 /*def_value*/, 0 /*require*/);
20929 }
20930 
duk_to_uint(duk_hthread * thr,duk_idx_t idx)20931 DUK_EXTERNAL duk_uint_t duk_to_uint(duk_hthread *thr, duk_idx_t idx) {
20932 	/* Value coercion (in stack): ToInteger(), E5 Section 9.4,
20933 	 * API return value coercion: custom.
20934 	 */
20935 	DUK_ASSERT_API_ENTRY(thr);
20936 	(void) duk__to_int_uint_helper(thr, idx, duk_js_tointeger);
20937 	return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, 0 /*def_value*/, 0 /*require*/);
20938 }
20939 
duk_to_int32(duk_hthread * thr,duk_idx_t idx)20940 DUK_EXTERNAL duk_int32_t duk_to_int32(duk_hthread *thr, duk_idx_t idx) {
20941 	duk_tval *tv;
20942 	duk_int32_t ret;
20943 
20944 	DUK_ASSERT_API_ENTRY(thr);
20945 
20946 	tv = duk_require_tval(thr, idx);
20947 	DUK_ASSERT(tv != NULL);
20948 	ret = duk_js_toint32(thr, tv);
20949 
20950 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
20951 	tv = duk_require_tval(thr, idx);
20952 	DUK_TVAL_SET_I32_UPDREF(thr, tv, ret);  /* side effects */
20953 	return ret;
20954 }
20955 
duk_to_uint32(duk_hthread * thr,duk_idx_t idx)20956 DUK_EXTERNAL duk_uint32_t duk_to_uint32(duk_hthread *thr, duk_idx_t idx) {
20957 	duk_tval *tv;
20958 	duk_uint32_t ret;
20959 
20960 	DUK_ASSERT_API_ENTRY(thr);
20961 
20962 	tv = duk_require_tval(thr, idx);
20963 	DUK_ASSERT(tv != NULL);
20964 	ret = duk_js_touint32(thr, tv);
20965 
20966 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
20967 	tv = duk_require_tval(thr, idx);
20968 	DUK_TVAL_SET_U32_UPDREF(thr, tv, ret);  /* side effects */
20969 	return ret;
20970 }
20971 
duk_to_uint16(duk_hthread * thr,duk_idx_t idx)20972 DUK_EXTERNAL duk_uint16_t duk_to_uint16(duk_hthread *thr, duk_idx_t idx) {
20973 	duk_tval *tv;
20974 	duk_uint16_t ret;
20975 
20976 	DUK_ASSERT_API_ENTRY(thr);
20977 
20978 	tv = duk_require_tval(thr, idx);
20979 	DUK_ASSERT(tv != NULL);
20980 	ret = duk_js_touint16(thr, tv);
20981 
20982 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
20983 	tv = duk_require_tval(thr, idx);
20984 	DUK_TVAL_SET_U32_UPDREF(thr, tv, ret);  /* side effects */
20985 	return ret;
20986 }
20987 
20988 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
20989 /* Special coercion for Uint8ClampedArray. */
duk_to_uint8clamped(duk_hthread * thr,duk_idx_t idx)20990 DUK_INTERNAL duk_uint8_t duk_to_uint8clamped(duk_hthread *thr, duk_idx_t idx) {
20991 	duk_double_t d;
20992 	duk_double_t t;
20993 	duk_uint8_t ret;
20994 
20995 	DUK_ASSERT_API_ENTRY(thr);
20996 
20997 	/* XXX: Simplify this algorithm, should be possible to come up with
20998 	 * a shorter and faster algorithm by inspecting IEEE representation
20999 	 * directly.
21000 	 */
21001 
21002 	d = duk_to_number(thr, idx);
21003 	if (d <= 0.0) {
21004 		return 0;
21005 	} else if (d >= 255) {
21006 		return 255;
21007 	} else if (DUK_ISNAN(d)) {
21008 		/* Avoid NaN-to-integer coercion as it is compiler specific. */
21009 		return 0;
21010 	}
21011 
21012 	t = d - DUK_FLOOR(d);
21013 	if (duk_double_equals(t, 0.5)) {
21014 		/* Exact halfway, round to even. */
21015 		ret = (duk_uint8_t) d;
21016 		ret = (ret + 1) & 0xfe;  /* Example: d=3.5, t=0.5 -> ret = (3 + 1) & 0xfe = 4 & 0xfe = 4
21017 		                          * Example: d=4.5, t=0.5 -> ret = (4 + 1) & 0xfe = 5 & 0xfe = 4
21018 		                          */
21019 	} else {
21020 		/* Not halfway, round to nearest. */
21021 		ret = (duk_uint8_t) (d + 0.5);
21022 	}
21023 	return ret;
21024 }
21025 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
21026 
duk_to_lstring(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)21027 DUK_EXTERNAL const char *duk_to_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
21028 	DUK_ASSERT_API_ENTRY(thr);
21029 
21030 	(void) duk_to_string(thr, idx);
21031 	DUK_ASSERT(duk_is_string(thr, idx));
21032 	return duk_require_lstring(thr, idx, out_len);
21033 }
21034 
duk__safe_to_string_raw(duk_hthread * thr,void * udata)21035 DUK_LOCAL duk_ret_t duk__safe_to_string_raw(duk_hthread *thr, void *udata) {
21036 	DUK_CTX_ASSERT_VALID(thr);
21037 	DUK_UNREF(udata);
21038 
21039 	(void) duk_to_string(thr, -1);
21040 	return 1;
21041 }
21042 
duk_safe_to_lstring(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)21043 DUK_EXTERNAL const char *duk_safe_to_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
21044 	DUK_ASSERT_API_ENTRY(thr);
21045 
21046 	idx = duk_require_normalize_index(thr, idx);
21047 
21048 	/* We intentionally ignore the duk_safe_call() return value and only
21049 	 * check the output type.  This way we don't also need to check that
21050 	 * the returned value is indeed a string in the success case.
21051 	 */
21052 
21053 	duk_dup(thr, idx);
21054 	(void) duk_safe_call(thr, duk__safe_to_string_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
21055 	if (!duk_is_string(thr, -1)) {
21056 		/* Error: try coercing error to string once. */
21057 		(void) duk_safe_call(thr, duk__safe_to_string_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
21058 		if (!duk_is_string(thr, -1)) {
21059 			/* Double error */
21060 			duk_pop_unsafe(thr);
21061 			duk_push_hstring_stridx(thr, DUK_STRIDX_UC_ERROR);
21062 		} else {
21063 			;
21064 		}
21065 	} else {
21066 		/* String; may be a symbol, accepted. */
21067 		;
21068 	}
21069 	DUK_ASSERT(duk_is_string(thr, -1));
21070 
21071 	duk_replace(thr, idx);
21072 	DUK_ASSERT(duk_get_string(thr, idx) != NULL);
21073 	return duk_get_lstring(thr, idx, out_len);
21074 }
21075 
duk_to_stacktrace(duk_hthread * thr,duk_idx_t idx)21076 DUK_EXTERNAL const char *duk_to_stacktrace(duk_hthread *thr, duk_idx_t idx) {
21077 	DUK_ASSERT_API_ENTRY(thr);
21078 	idx = duk_require_normalize_index(thr, idx);
21079 
21080 	/* The expected argument to the call is an Error object.  The stack
21081 	 * trace is extracted without an inheritance-based instanceof check
21082 	 * so that one can also extract the stack trace of a foreign error
21083 	 * created in another Realm.  Accept only a string .stack property.
21084 	 */
21085 	if (duk_is_object(thr, idx)) {
21086 		(void) duk_get_prop_string(thr, idx, "stack");
21087 		if (duk_is_string(thr, -1)) {
21088 			duk_replace(thr, idx);
21089 		} else {
21090 			duk_pop(thr);
21091 		}
21092 	}
21093 
21094 	return duk_to_string(thr, idx);
21095 }
21096 
duk__safe_to_stacktrace_raw(duk_hthread * thr,void * udata)21097 DUK_LOCAL duk_ret_t duk__safe_to_stacktrace_raw(duk_hthread *thr, void *udata) {
21098 	DUK_CTX_ASSERT_VALID(thr);
21099 	DUK_UNREF(udata);
21100 
21101 	(void) duk_to_stacktrace(thr, -1);
21102 
21103 	return 1;
21104 }
21105 
duk_safe_to_stacktrace(duk_hthread * thr,duk_idx_t idx)21106 DUK_EXTERNAL const char *duk_safe_to_stacktrace(duk_hthread *thr, duk_idx_t idx) {
21107 	duk_int_t rc;
21108 
21109 	DUK_ASSERT_API_ENTRY(thr);
21110 	idx = duk_require_normalize_index(thr, idx);
21111 
21112 	duk_dup(thr, idx);
21113 	rc = duk_safe_call(thr, duk__safe_to_stacktrace_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
21114 	if (rc != 0) {
21115 		/* Coercion failed.  Try to coerce the coercion itself error
21116 		 * to a stack trace once.  If that also fails, return a fixed,
21117 		 * preallocated 'Error' string to avoid potential infinite loop.
21118 		 */
21119 		rc = duk_safe_call(thr, duk__safe_to_stacktrace_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
21120 		if (rc != 0) {
21121 			duk_pop_unsafe(thr);
21122 			duk_push_hstring_stridx(thr, DUK_STRIDX_UC_ERROR);
21123 		}
21124 	}
21125 	duk_replace(thr, idx);
21126 
21127 	return duk_get_string(thr, idx);
21128 }
21129 
duk_to_property_key_hstring(duk_hthread * thr,duk_idx_t idx)21130 DUK_INTERNAL duk_hstring *duk_to_property_key_hstring(duk_hthread *thr, duk_idx_t idx) {
21131 	duk_hstring *h;
21132 
21133 	DUK_ASSERT_API_ENTRY(thr);
21134 
21135 	duk_to_primitive(thr, idx, DUK_HINT_STRING);  /* needed for e.g. Symbol objects */
21136 	h = duk_get_hstring(thr, idx);
21137 	if (h == NULL) {
21138 		/* The "is string?" check may seem unnecessary, but as things
21139 		 * are duk_to_hstring() invokes ToString() which fails for
21140 		 * symbols.  But since symbols are already strings for Duktape
21141 		 * C API, we check for that before doing the coercion.
21142 		 */
21143 		h = duk_to_hstring(thr, idx);
21144 	}
21145 	DUK_ASSERT(h != NULL);
21146 	return h;
21147 }
21148 
21149 #if defined(DUK_USE_DEBUGGER_SUPPORT)  /* only needed by debugger for now */
duk_safe_to_hstring(duk_hthread * thr,duk_idx_t idx)21150 DUK_INTERNAL duk_hstring *duk_safe_to_hstring(duk_hthread *thr, duk_idx_t idx) {
21151 	DUK_ASSERT_API_ENTRY(thr);
21152 
21153 	(void) duk_safe_to_string(thr, idx);
21154 	DUK_ASSERT(duk_is_string(thr, idx));
21155 	DUK_ASSERT(duk_get_hstring(thr, idx) != NULL);
21156 	return duk_known_hstring(thr, idx);
21157 }
21158 #endif
21159 
21160 /* Push Object.prototype.toString() output for 'tv'. */
duk_push_class_string_tval(duk_hthread * thr,duk_tval * tv,duk_bool_t avoid_side_effects)21161 DUK_INTERNAL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv, duk_bool_t avoid_side_effects) {
21162 	duk_hobject *h_obj;
21163 	duk_small_uint_t classnum;
21164 	duk_small_uint_t stridx;
21165 	duk_tval tv_tmp;
21166 
21167 	DUK_ASSERT_API_ENTRY(thr);
21168 	DUK_ASSERT(tv != NULL);
21169 
21170 	/* Stabilize 'tv', duk_push_literal() may trigger side effects. */
21171 	DUK_TVAL_SET_TVAL(&tv_tmp, tv);
21172 	tv = &tv_tmp;
21173 
21174 	/* Conceptually for any non-undefined/null value we should do a
21175 	 * ToObject() coercion and look up @@toStringTag (from the object
21176 	 * prototype) to see if a custom result should be used, with the
21177 	 * exception of Arrays which are handled specially first.
21178 	 *
21179 	 * We'd like to avoid the actual conversion, but even for primitive
21180 	 * types the prototype may have @@toStringTag.  What's worse, the
21181 	 * @@toStringTag property may be a getter that must get the object
21182 	 * coerced value (not the prototype) as its 'this' binding.
21183 	 *
21184 	 * For now, do an actual object coercion.  This could be avoided by
21185 	 * doing a side effect free lookup to see if a getter would be invoked.
21186 	 * If not, the value can be read directly and the object coercion could
21187 	 * be avoided.  This may not be worth it in practice, because
21188 	 * Object.prototype.toString() is usually not performance critical.
21189 	 */
21190 
21191 	duk_push_literal(thr, "[object ");  /* -> [ ... "[object" ] */
21192 
21193 	switch (DUK_TVAL_GET_TAG(tv)) {
21194 	case DUK_TAG_UNUSED:  /* Treat like 'undefined', shouldn't happen. */
21195 	case DUK_TAG_UNDEFINED: {
21196 		duk_push_hstring_stridx(thr, DUK_STRIDX_UC_UNDEFINED);
21197 		goto finish;
21198 	}
21199 	case DUK_TAG_NULL: {
21200 		duk_push_hstring_stridx(thr, DUK_STRIDX_UC_NULL);
21201 		goto finish;
21202 	}
21203 	}
21204 
21205 	duk_push_tval(thr, tv);
21206 	tv = NULL;  /* Invalidated by ToObject(). */
21207 	h_obj = duk_to_hobject(thr, -1);
21208 	DUK_ASSERT(h_obj != NULL);
21209 	if (duk_js_isarray_hobject(h_obj)) {
21210 		stridx = DUK_STRIDX_UC_ARRAY;
21211 	} else {
21212 		/* [ ... "[object" obj ] */
21213 
21214 #if defined(DUK_USE_SYMBOL_BUILTIN)
21215 		/* XXX: better handling with avoid_side_effects == 1; lookup tval
21216 		 * without Proxy or getter side effects, and use it in sanitized
21217 		 * form if it's a string.
21218 		 */
21219 		if (!avoid_side_effects) {
21220 			(void) duk_get_prop_stridx(thr, -1, DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG);
21221 			if (duk_is_string_notsymbol(thr, -1)) {
21222 				duk_remove_m2(thr);
21223 				goto finish;
21224 			}
21225 			duk_pop_unsafe(thr);
21226 		}
21227 #else
21228 		DUK_UNREF(avoid_side_effects);
21229 #endif
21230 
21231 		classnum = DUK_HOBJECT_GET_CLASS_NUMBER(h_obj);
21232 		stridx = DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum);
21233 	}
21234 	duk_pop_unsafe(thr);
21235 	duk_push_hstring_stridx(thr, stridx);
21236 
21237  finish:
21238 	/* [ ... "[object" tag ] */
21239 	duk_push_literal(thr, "]");
21240 	duk_concat(thr, 3);  /* [ ... "[object" tag "]" ] -> [ ... res ] */
21241 }
21242 
21243 /* XXX: other variants like uint, u32 etc */
duk_to_int_clamped_raw(duk_hthread * thr,duk_idx_t idx,duk_int_t minval,duk_int_t maxval,duk_bool_t * out_clamped)21244 DUK_INTERNAL duk_int_t duk_to_int_clamped_raw(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval, duk_bool_t *out_clamped) {
21245 	duk_tval *tv;
21246 	duk_tval tv_tmp;
21247 	duk_double_t d, dmin, dmax;
21248 	duk_int_t res;
21249 	duk_bool_t clamped = 0;
21250 
21251 	DUK_ASSERT_API_ENTRY(thr);
21252 
21253 	tv = duk_require_tval(thr, idx);
21254 	DUK_ASSERT(tv != NULL);
21255 	d = duk_js_tointeger(thr, tv);  /* E5 Section 9.4, ToInteger() */
21256 
21257 	dmin = (duk_double_t) minval;
21258 	dmax = (duk_double_t) maxval;
21259 
21260 	if (d < dmin) {
21261 		clamped = 1;
21262 		res = minval;
21263 		d = dmin;
21264 	} else if (d > dmax) {
21265 		clamped = 1;
21266 		res = maxval;
21267 		d = dmax;
21268 	} else {
21269 		res = (duk_int_t) d;
21270 	}
21271 	DUK_UNREF(d);  /* SCANBUILD: with suitable dmin/dmax limits 'd' is unused */
21272 	/* 'd' and 'res' agree here */
21273 
21274 	/* Relookup in case duk_js_tointeger() ends up e.g. coercing an object. */
21275 	tv = duk_get_tval(thr, idx);
21276 	DUK_ASSERT(tv != NULL);  /* not popped by side effect */
21277 	DUK_TVAL_SET_TVAL(&tv_tmp, tv);
21278 #if defined(DUK_USE_FASTINT)
21279 #if (DUK_INT_MAX <= 0x7fffffffL)
21280 	DUK_TVAL_SET_I32(tv, res);
21281 #else
21282 	/* Clamping needed if duk_int_t is 64 bits. */
21283 	if (res >= DUK_FASTINT_MIN && res <= DUK_FASTINT_MAX) {
21284 		DUK_TVAL_SET_FASTINT(tv, res);
21285 	} else {
21286 		DUK_TVAL_SET_NUMBER(tv, d);
21287 	}
21288 #endif
21289 #else
21290 	DUK_TVAL_SET_NUMBER(tv, d);  /* no need to incref */
21291 #endif
21292 	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
21293 
21294 	if (out_clamped) {
21295 		*out_clamped = clamped;
21296 	} else {
21297 		/* coerced value is updated to value stack even when RangeError thrown */
21298 		if (clamped) {
21299 			DUK_ERROR_RANGE(thr, DUK_STR_NUMBER_OUTSIDE_RANGE);
21300 			DUK_WO_NORETURN(return 0;);
21301 		}
21302 	}
21303 
21304 	return res;
21305 }
21306 
duk_to_int_clamped(duk_hthread * thr,duk_idx_t idx,duk_idx_t minval,duk_idx_t maxval)21307 DUK_INTERNAL duk_int_t duk_to_int_clamped(duk_hthread *thr, duk_idx_t idx, duk_idx_t minval, duk_idx_t maxval) {
21308 	duk_bool_t dummy;
21309 
21310 	DUK_ASSERT_API_ENTRY(thr);
21311 
21312 	return duk_to_int_clamped_raw(thr, idx, minval, maxval, &dummy);
21313 }
21314 
duk_to_int_check_range(duk_hthread * thr,duk_idx_t idx,duk_int_t minval,duk_int_t maxval)21315 DUK_INTERNAL duk_int_t duk_to_int_check_range(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval) {
21316 	DUK_ASSERT_API_ENTRY(thr);
21317 	return duk_to_int_clamped_raw(thr, idx, minval, maxval, NULL);  /* out_clamped==NULL -> RangeError if outside range */
21318 }
21319 
duk_to_string(duk_hthread * thr,duk_idx_t idx)21320 DUK_EXTERNAL const char *duk_to_string(duk_hthread *thr, duk_idx_t idx) {
21321 	duk_tval *tv;
21322 
21323 	DUK_ASSERT_API_ENTRY(thr);
21324 
21325 	idx = duk_require_normalize_index(thr, idx);
21326 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
21327 	DUK_ASSERT(tv != NULL);
21328 
21329 	switch (DUK_TVAL_GET_TAG(tv)) {
21330 	case DUK_TAG_UNDEFINED: {
21331 		duk_push_hstring_stridx(thr, DUK_STRIDX_LC_UNDEFINED);
21332 		break;
21333 	}
21334 	case DUK_TAG_NULL: {
21335 		duk_push_hstring_stridx(thr, DUK_STRIDX_LC_NULL);
21336 		break;
21337 	}
21338 	case DUK_TAG_BOOLEAN: {
21339 		if (DUK_TVAL_GET_BOOLEAN(tv)) {
21340 			duk_push_hstring_stridx(thr, DUK_STRIDX_TRUE);
21341 		} else {
21342 			duk_push_hstring_stridx(thr, DUK_STRIDX_FALSE);
21343 		}
21344 		break;
21345 	}
21346 	case DUK_TAG_STRING: {
21347 		/* Nop for actual strings, TypeError for Symbols.
21348 		 * Because various internals rely on ToString() coercion of
21349 		 * internal strings, -allow- (NOP) string coercion for hidden
21350 		 * symbols.
21351 		 */
21352 #if 1
21353 		duk_hstring *h;
21354 		h = DUK_TVAL_GET_STRING(tv);
21355 		DUK_ASSERT(h != NULL);
21356 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
21357 			DUK_ERROR_TYPE(thr, DUK_STR_CANNOT_STRING_COERCE_SYMBOL);
21358 			DUK_WO_NORETURN(goto skip_replace;);
21359 		} else {
21360 			goto skip_replace;
21361 		}
21362 #else
21363 		goto skip_replace;
21364 #endif
21365 		break;
21366 	}
21367 	case DUK_TAG_BUFFER: /* Go through Uint8Array.prototype.toString() for coercion. */
21368 	case DUK_TAG_OBJECT: {
21369 		/* Plain buffers: go through ArrayBuffer.prototype.toString()
21370 		 * for coercion.
21371 		 *
21372 		 * Symbol objects: duk_to_primitive() results in a plain symbol
21373 		 * value, and duk_to_string() then causes a TypeError.
21374 		 */
21375 		duk_to_primitive(thr, idx, DUK_HINT_STRING);
21376 		DUK_ASSERT(!duk_is_buffer(thr, idx));  /* ToPrimitive() must guarantee */
21377 		DUK_ASSERT(!duk_is_object(thr, idx));
21378 		return duk_to_string(thr, idx);  /* Note: recursive call */
21379 	}
21380 	case DUK_TAG_POINTER: {
21381 		void *ptr = DUK_TVAL_GET_POINTER(tv);
21382 		if (ptr != NULL) {
21383 			duk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) ptr);
21384 		} else {
21385 			/* Represent a null pointer as 'null' to be consistent with
21386 			 * the JX format variant.  Native '%p' format for a NULL
21387 			 * pointer may be e.g. '(nil)'.
21388 			 */
21389 			duk_push_hstring_stridx(thr, DUK_STRIDX_LC_NULL);
21390 		}
21391 		break;
21392 	}
21393 	case DUK_TAG_LIGHTFUNC: {
21394 		/* Should match Function.prototype.toString() */
21395 		duk_push_lightfunc_tostring(thr, tv);
21396 		break;
21397 	}
21398 #if defined(DUK_USE_FASTINT)
21399 	case DUK_TAG_FASTINT:
21400 #endif
21401 	default: {
21402 		/* number */
21403 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
21404 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
21405 		duk_push_tval(thr, tv);
21406 		duk_numconv_stringify(thr,
21407 		                      10 /*radix*/,
21408 		                      0 /*precision:shortest*/,
21409 		                      0 /*force_exponential*/);
21410 		break;
21411 	}
21412 	}
21413 
21414 	duk_replace(thr, idx);
21415 
21416  skip_replace:
21417 	DUK_ASSERT(duk_is_string(thr, idx));
21418 	return duk_require_string(thr, idx);
21419 }
21420 
duk_to_hstring(duk_hthread * thr,duk_idx_t idx)21421 DUK_INTERNAL duk_hstring *duk_to_hstring(duk_hthread *thr, duk_idx_t idx) {
21422 	duk_hstring *ret;
21423 
21424 	DUK_ASSERT_API_ENTRY(thr);
21425 
21426 	duk_to_string(thr, idx);
21427 	ret = duk_get_hstring(thr, idx);
21428 	DUK_ASSERT(ret != NULL);
21429 	return ret;
21430 }
21431 
duk_to_hstring_m1(duk_hthread * thr)21432 DUK_INTERNAL duk_hstring *duk_to_hstring_m1(duk_hthread *thr) {
21433 	DUK_ASSERT_API_ENTRY(thr);
21434 	return duk_to_hstring(thr, -1);
21435 }
21436 
duk_to_hstring_acceptsymbol(duk_hthread * thr,duk_idx_t idx)21437 DUK_INTERNAL duk_hstring *duk_to_hstring_acceptsymbol(duk_hthread *thr, duk_idx_t idx) {
21438 	duk_hstring *ret;
21439 
21440 	DUK_ASSERT_API_ENTRY(thr);
21441 
21442 	ret = duk_get_hstring(thr, idx);
21443 	if (DUK_UNLIKELY(ret && DUK_HSTRING_HAS_SYMBOL(ret))) {
21444 		return ret;
21445 	}
21446 	return duk_to_hstring(thr, idx);
21447 }
21448 
21449 /* Convert a plain buffer or any buffer object into a string, using the buffer
21450  * bytes 1:1 in the internal string representation.  For views the active byte
21451  * slice (not element slice interpreted as an initializer) is used.  This is
21452  * necessary in Duktape 2.x because ToString(plainBuffer) no longer creates a
21453  * string with the same bytes as in the buffer but rather (usually)
21454  * '[object ArrayBuffer]'.
21455  */
duk_buffer_to_string(duk_hthread * thr,duk_idx_t idx)21456 DUK_EXTERNAL const char *duk_buffer_to_string(duk_hthread *thr, duk_idx_t idx) {
21457 	void *ptr_src;
21458 	duk_size_t len;
21459 	const char *res;
21460 
21461 	DUK_ASSERT_API_ENTRY(thr);
21462 
21463 	idx = duk_require_normalize_index(thr, idx);
21464 
21465 	ptr_src = duk_require_buffer_data(thr, idx, &len);
21466 	DUK_ASSERT(ptr_src != NULL || len == 0);
21467 
21468 	res = duk_push_lstring(thr, (const char *) ptr_src, len);
21469 	duk_replace(thr, idx);
21470 	return res;
21471 }
21472 
duk_to_buffer_raw(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size,duk_uint_t mode)21473 DUK_EXTERNAL void *duk_to_buffer_raw(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, duk_uint_t mode) {
21474 	duk_hbuffer *h_buf;
21475 	const duk_uint8_t *src_data;
21476 	duk_size_t src_size;
21477 	duk_uint8_t *dst_data;
21478 
21479 	DUK_ASSERT_API_ENTRY(thr);
21480 
21481 	idx = duk_require_normalize_index(thr, idx);
21482 
21483 	h_buf = duk_get_hbuffer(thr, idx);
21484 	if (h_buf != NULL) {
21485 		/* Buffer is kept as is, with the fixed/dynamic nature of the
21486 		 * buffer only changed if requested.  An external buffer
21487 		 * is converted into a non-external dynamic buffer in a
21488 		 * duk_to_dynamic_buffer() call.
21489 		 */
21490 		duk_uint_t tmp;
21491 		duk_uint8_t *tmp_ptr;
21492 
21493 		tmp_ptr = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf);
21494 		src_data = (const duk_uint8_t *) tmp_ptr;
21495 		src_size = DUK_HBUFFER_GET_SIZE(h_buf);
21496 
21497 		tmp = (DUK_HBUFFER_HAS_DYNAMIC(h_buf) ? DUK_BUF_MODE_DYNAMIC : DUK_BUF_MODE_FIXED);
21498 		if ((tmp == mode && !DUK_HBUFFER_HAS_EXTERNAL(h_buf)) ||
21499 		    mode == DUK_BUF_MODE_DONTCARE) {
21500 			/* Note: src_data may be NULL if input is a zero-size
21501 			 * dynamic buffer.
21502 			 */
21503 			dst_data = tmp_ptr;
21504 			goto skip_copy;
21505 		}
21506 	} else {
21507 		/* Non-buffer value is first ToString() coerced, then converted
21508 		 * to a buffer (fixed buffer is used unless a dynamic buffer is
21509 		 * explicitly requested).  Symbols are rejected with a TypeError.
21510 		 * XXX: C API could maybe allow symbol-to-buffer coercion?
21511 		 */
21512 		src_data = (const duk_uint8_t *) duk_to_lstring(thr, idx, &src_size);
21513 	}
21514 
21515 	dst_data = (duk_uint8_t *) duk_push_buffer(thr, src_size, (mode == DUK_BUF_MODE_DYNAMIC) /*dynamic*/);
21516 	/* dst_data may be NULL if size is zero. */
21517 	duk_memcpy_unsafe((void *) dst_data, (const void *) src_data, (size_t) src_size);
21518 
21519 	duk_replace(thr, idx);
21520  skip_copy:
21521 
21522 	if (out_size) {
21523 		*out_size = src_size;
21524 	}
21525 	return dst_data;
21526 }
21527 
duk_to_pointer(duk_hthread * thr,duk_idx_t idx)21528 DUK_EXTERNAL void *duk_to_pointer(duk_hthread *thr, duk_idx_t idx) {
21529 	duk_tval *tv;
21530 	void *res;
21531 
21532 	DUK_ASSERT_API_ENTRY(thr);
21533 
21534 	idx = duk_require_normalize_index(thr, idx);
21535 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
21536 	DUK_ASSERT(tv != NULL);
21537 
21538 	switch (DUK_TVAL_GET_TAG(tv)) {
21539 	case DUK_TAG_UNDEFINED:
21540 	case DUK_TAG_NULL:
21541 	case DUK_TAG_BOOLEAN:
21542 		res = NULL;
21543 		break;
21544 	case DUK_TAG_POINTER:
21545 		res = DUK_TVAL_GET_POINTER(tv);
21546 		break;
21547 	case DUK_TAG_STRING:
21548 	case DUK_TAG_OBJECT:
21549 	case DUK_TAG_BUFFER:
21550 		/* Heap allocated: return heap pointer which is NOT useful
21551 		 * for the caller, except for debugging.
21552 		 */
21553 		res = (void *) DUK_TVAL_GET_HEAPHDR(tv);
21554 		break;
21555 	case DUK_TAG_LIGHTFUNC:
21556 		/* Function pointers do not always cast correctly to void *
21557 		 * (depends on memory and segmentation model for instance),
21558 		 * so they coerce to NULL.
21559 		 */
21560 		res = NULL;
21561 		break;
21562 #if defined(DUK_USE_FASTINT)
21563 	case DUK_TAG_FASTINT:
21564 #endif
21565 	default:
21566 		/* number */
21567 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
21568 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
21569 		res = NULL;
21570 		break;
21571 	}
21572 
21573 	duk_push_pointer(thr, res);
21574 	duk_replace(thr, idx);
21575 	return res;
21576 }
21577 
duk__push_func_from_lightfunc(duk_hthread * thr,duk_c_function func,duk_small_uint_t lf_flags)21578 DUK_LOCAL void duk__push_func_from_lightfunc(duk_hthread *thr, duk_c_function func, duk_small_uint_t lf_flags) {
21579 	duk_idx_t nargs;
21580 	duk_uint_t flags = 0;   /* shared flags for a subset of types */
21581 	duk_small_uint_t lf_len;
21582 	duk_hnatfunc *nf;
21583 
21584 	nargs = (duk_idx_t) DUK_LFUNC_FLAGS_GET_NARGS(lf_flags);
21585 	if (nargs == DUK_LFUNC_NARGS_VARARGS) {
21586 		nargs = (duk_idx_t) DUK_VARARGS;
21587 	}
21588 
21589 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21590 	        DUK_HOBJECT_FLAG_CONSTRUCTABLE |
21591 	        DUK_HOBJECT_FLAG_CALLABLE |
21592 	        DUK_HOBJECT_FLAG_FASTREFS |
21593 	        DUK_HOBJECT_FLAG_NATFUNC |
21594 	        DUK_HOBJECT_FLAG_NEWENV |
21595 	        DUK_HOBJECT_FLAG_STRICT |
21596 	        DUK_HOBJECT_FLAG_NOTAIL |
21597 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
21598 	(void) duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE);
21599 
21600 	lf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
21601 	if ((duk_idx_t) lf_len != nargs) {
21602 		/* Explicit length is only needed if it differs from 'nargs'. */
21603 		duk_push_int(thr, (duk_int_t) lf_len);
21604 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE);
21605 	}
21606 
21607 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
21608 	duk_push_lightfunc_name_raw(thr, func, lf_flags);
21609 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
21610 #endif
21611 
21612 	nf = duk_known_hnatfunc(thr, -1);
21613 	nf->magic = (duk_int16_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
21614 }
21615 
duk_to_object(duk_hthread * thr,duk_idx_t idx)21616 DUK_EXTERNAL void duk_to_object(duk_hthread *thr, duk_idx_t idx) {
21617 	duk_tval *tv;
21618 	duk_uint_t flags = 0;   /* shared flags for a subset of types */
21619 	duk_small_int_t proto = 0;
21620 
21621 	DUK_ASSERT_API_ENTRY(thr);
21622 
21623 	idx = duk_require_normalize_index(thr, idx);
21624 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
21625 	DUK_ASSERT(tv != NULL);
21626 
21627 	switch (DUK_TVAL_GET_TAG(tv)) {
21628 #if !defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21629 	case DUK_TAG_BUFFER:  /* With no bufferobject support, don't object coerce. */
21630 #endif
21631 	case DUK_TAG_UNDEFINED:
21632 	case DUK_TAG_NULL: {
21633 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_OBJECT_COERCIBLE);
21634 		DUK_WO_NORETURN(return;);
21635 		break;
21636 	}
21637 	case DUK_TAG_BOOLEAN: {
21638 		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21639 		        DUK_HOBJECT_FLAG_FASTREFS |
21640 		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BOOLEAN);
21641 		proto = DUK_BIDX_BOOLEAN_PROTOTYPE;
21642 		goto create_object;
21643 	}
21644 	case DUK_TAG_STRING: {
21645 		duk_hstring *h;
21646 		h = DUK_TVAL_GET_STRING(tv);
21647 		DUK_ASSERT(h != NULL);
21648 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
21649 			flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21650 			        DUK_HOBJECT_FLAG_FASTREFS |
21651 			        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_SYMBOL);
21652 			proto = DUK_BIDX_SYMBOL_PROTOTYPE;
21653 		} else {
21654 			flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21655 			        DUK_HOBJECT_FLAG_FASTREFS |
21656 			        DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ |
21657 			        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_STRING);
21658 			proto = DUK_BIDX_STRING_PROTOTYPE;
21659 		}
21660 		goto create_object;
21661 	}
21662 	case DUK_TAG_OBJECT: {
21663 		/* nop */
21664 		break;
21665 	}
21666 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21667 	case DUK_TAG_BUFFER: {
21668 		/* A plain buffer object coerces to a full ArrayBuffer which
21669 		 * is not fully transparent behavior (ToObject() should be a
21670 		 * nop for an object).  This behavior matches lightfuncs which
21671 		 * also coerce to an equivalent Function object.  There are
21672 		 * also downsides to defining ToObject(plainBuffer) as a no-op;
21673 		 * for example duk_to_hobject() could result in a NULL pointer.
21674 		 */
21675 		duk_hbuffer *h_buf;
21676 
21677 		h_buf = DUK_TVAL_GET_BUFFER(tv);
21678 		DUK_ASSERT(h_buf != NULL);
21679 		duk_hbufobj_push_uint8array_from_plain(thr, h_buf);
21680 		goto replace_value;
21681 	}
21682 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
21683 	case DUK_TAG_POINTER: {
21684 		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21685 		        DUK_HOBJECT_FLAG_FASTREFS |
21686 		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER);
21687 		proto = DUK_BIDX_POINTER_PROTOTYPE;
21688 		goto create_object;
21689 	}
21690 	case DUK_TAG_LIGHTFUNC: {
21691 		/* Lightfunc coerces to a Function instance with concrete
21692 		 * properties.  Since 'length' is virtual for Duktape/C
21693 		 * functions, don't need to define that.  The result is made
21694 		 * extensible to mimic what happens to strings in object
21695 		 * coercion:
21696 		 *
21697 		 *   > Object.isExtensible(Object('foo'))
21698 		 *   true
21699 		 */
21700 		duk_small_uint_t lf_flags;
21701 		duk_c_function func;
21702 
21703 		DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
21704 		duk__push_func_from_lightfunc(thr, func, lf_flags);
21705 		goto replace_value;
21706 	}
21707 #if defined(DUK_USE_FASTINT)
21708 	case DUK_TAG_FASTINT:
21709 #endif
21710 	default: {
21711 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
21712 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
21713 		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21714 		        DUK_HOBJECT_FLAG_FASTREFS |
21715 		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_NUMBER);
21716 		proto = DUK_BIDX_NUMBER_PROTOTYPE;
21717 		goto create_object;
21718 	}
21719 	}
21720 	DUK_ASSERT(duk_is_object(thr, idx));
21721 	return;
21722 
21723  create_object:
21724 	(void) duk_push_object_helper(thr, flags, proto);
21725 
21726 	/* Note: Boolean prototype's internal value property is not writable,
21727 	 * but duk_xdef_prop_stridx() disregards the write protection.  Boolean
21728 	 * instances are immutable.
21729 	 *
21730 	 * String and buffer special behaviors are already enabled which is not
21731 	 * ideal, but a write to the internal value is not affected by them.
21732 	 */
21733 	duk_dup(thr, idx);
21734 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
21735 
21736  replace_value:
21737 	duk_replace(thr, idx);
21738 	DUK_ASSERT(duk_is_object(thr, idx));
21739 }
21740 
duk_to_hobject(duk_hthread * thr,duk_idx_t idx)21741 DUK_INTERNAL duk_hobject *duk_to_hobject(duk_hthread *thr, duk_idx_t idx) {
21742 	duk_hobject *ret;
21743 
21744 	DUK_ASSERT_API_ENTRY(thr);
21745 
21746 	duk_to_object(thr, idx);
21747 	ret = duk_known_hobject(thr, idx);
21748 	return ret;
21749 }
21750 
21751 /*
21752  *  Type checking
21753  */
21754 
duk__tag_check(duk_hthread * thr,duk_idx_t idx,duk_small_uint_t tag)21755 DUK_LOCAL duk_bool_t duk__tag_check(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t tag) {
21756 	duk_tval *tv;
21757 
21758 	tv = duk_get_tval_or_unused(thr, idx);
21759 	DUK_ASSERT(tv != NULL);
21760 	return (DUK_TVAL_GET_TAG(tv) == tag);
21761 }
21762 
duk__obj_flag_any_default_false(duk_hthread * thr,duk_idx_t idx,duk_uint_t flag_mask)21763 DUK_LOCAL duk_bool_t duk__obj_flag_any_default_false(duk_hthread *thr, duk_idx_t idx, duk_uint_t flag_mask) {
21764 	duk_hobject *obj;
21765 
21766 	DUK_ASSERT_API_ENTRY(thr);
21767 
21768 	obj = duk_get_hobject(thr, idx);
21769 	if (obj) {
21770 		return (DUK_HEAPHDR_CHECK_FLAG_BITS((duk_heaphdr *) obj, flag_mask) ? 1 : 0);
21771 	}
21772 	return 0;
21773 }
21774 
duk_get_type_tval(duk_tval * tv)21775 DUK_INTERNAL duk_int_t duk_get_type_tval(duk_tval *tv) {
21776 	DUK_ASSERT(tv != NULL);
21777 
21778 #if defined(DUK_USE_PACKED_TVAL)
21779 	switch (DUK_TVAL_GET_TAG(tv)) {
21780 	case DUK_TAG_UNUSED:
21781 		return DUK_TYPE_NONE;
21782 	case DUK_TAG_UNDEFINED:
21783 		return DUK_TYPE_UNDEFINED;
21784 	case DUK_TAG_NULL:
21785 		return DUK_TYPE_NULL;
21786 	case DUK_TAG_BOOLEAN:
21787 		return DUK_TYPE_BOOLEAN;
21788 	case DUK_TAG_STRING:
21789 		return DUK_TYPE_STRING;
21790 	case DUK_TAG_OBJECT:
21791 		return DUK_TYPE_OBJECT;
21792 	case DUK_TAG_BUFFER:
21793 		return DUK_TYPE_BUFFER;
21794 	case DUK_TAG_POINTER:
21795 		return DUK_TYPE_POINTER;
21796 	case DUK_TAG_LIGHTFUNC:
21797 		return DUK_TYPE_LIGHTFUNC;
21798 #if defined(DUK_USE_FASTINT)
21799 	case DUK_TAG_FASTINT:
21800 #endif
21801 	default:
21802 		/* Note: number has no explicit tag (in 8-byte representation) */
21803 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
21804 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
21805 		return DUK_TYPE_NUMBER;
21806 	}
21807 #else  /* DUK_USE_PACKED_TVAL */
21808 	DUK_ASSERT(DUK_TVAL_IS_VALID_TAG(tv));
21809 	DUK_ASSERT(sizeof(duk__type_from_tag) / sizeof(duk_uint_t) == DUK_TAG_MAX - DUK_TAG_MIN + 1);
21810 	return (duk_int_t) duk__type_from_tag[DUK_TVAL_GET_TAG(tv) - DUK_TAG_MIN];
21811 #endif  /* DUK_USE_PACKED_TVAL */
21812 }
21813 
duk_get_type(duk_hthread * thr,duk_idx_t idx)21814 DUK_EXTERNAL duk_int_t duk_get_type(duk_hthread *thr, duk_idx_t idx) {
21815 	duk_tval *tv;
21816 
21817 	DUK_ASSERT_API_ENTRY(thr);
21818 
21819 	tv = duk_get_tval_or_unused(thr, idx);
21820 	DUK_ASSERT(tv != NULL);
21821 
21822 	return duk_get_type_tval(tv);
21823 }
21824 
21825 #if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)
21826 DUK_LOCAL const char * const duk__type_names[] = {
21827 	"none",
21828 	"undefined",
21829 	"null",
21830 	"boolean",
21831 	"number",
21832 	"string",
21833 	"object",
21834 	"buffer",
21835 	"pointer",
21836 	"lightfunc"
21837 };
21838 
duk_get_type_name(duk_hthread * thr,duk_idx_t idx)21839 DUK_INTERNAL const char *duk_get_type_name(duk_hthread *thr, duk_idx_t idx) {
21840 	duk_int_t type_tag;
21841 
21842 	DUK_ASSERT_API_ENTRY(thr);
21843 
21844 	type_tag = duk_get_type(thr, idx);
21845 	DUK_ASSERT(type_tag >= DUK_TYPE_MIN && type_tag <= DUK_TYPE_MAX);
21846 	DUK_ASSERT(DUK_TYPE_MIN == 0 && sizeof(duk__type_names) / sizeof(const char *) == DUK_TYPE_MAX + 1);
21847 
21848 	return duk__type_names[type_tag];
21849 }
21850 #endif  /* DUK_USE_VERBOSE_ERRORS && DUK_USE_PARANOID_ERRORS */
21851 
duk_get_class_number(duk_hthread * thr,duk_idx_t idx)21852 DUK_INTERNAL duk_small_uint_t duk_get_class_number(duk_hthread *thr, duk_idx_t idx) {
21853 	duk_tval *tv;
21854 	duk_hobject *obj;
21855 
21856 	DUK_ASSERT_API_ENTRY(thr);
21857 
21858 	tv = duk_get_tval_or_unused(thr, idx);
21859 	DUK_ASSERT(tv != NULL);
21860 
21861 	switch (DUK_TVAL_GET_TAG(tv)) {
21862 	case DUK_TAG_OBJECT:
21863 		obj = DUK_TVAL_GET_OBJECT(tv);
21864 		DUK_ASSERT(obj != NULL);
21865 		return DUK_HOBJECT_GET_CLASS_NUMBER(obj);
21866 	case DUK_TAG_BUFFER:
21867 		/* Buffers behave like Uint8Array objects. */
21868 		return DUK_HOBJECT_CLASS_UINT8ARRAY;
21869 	case DUK_TAG_LIGHTFUNC:
21870 		/* Lightfuncs behave like Function objects. */
21871 		return DUK_HOBJECT_CLASS_FUNCTION;
21872 	default:
21873 		/* Primitive or UNUSED, no class number. */
21874 		return DUK_HOBJECT_CLASS_NONE;
21875 	}
21876 }
21877 
duk_check_type(duk_hthread * thr,duk_idx_t idx,duk_int_t type)21878 DUK_EXTERNAL duk_bool_t duk_check_type(duk_hthread *thr, duk_idx_t idx, duk_int_t type) {
21879 	DUK_ASSERT_API_ENTRY(thr);
21880 
21881 	return (duk_get_type(thr, idx) == type) ? 1 : 0;
21882 }
21883 
duk_get_type_mask_tval(duk_tval * tv)21884 DUK_INTERNAL duk_uint_t duk_get_type_mask_tval(duk_tval *tv) {
21885 	DUK_ASSERT(tv != NULL);
21886 
21887 #if defined(DUK_USE_PACKED_TVAL)
21888 	switch (DUK_TVAL_GET_TAG(tv)) {
21889 	case DUK_TAG_UNUSED:
21890 		return DUK_TYPE_MASK_NONE;
21891 	case DUK_TAG_UNDEFINED:
21892 		return DUK_TYPE_MASK_UNDEFINED;
21893 	case DUK_TAG_NULL:
21894 		return DUK_TYPE_MASK_NULL;
21895 	case DUK_TAG_BOOLEAN:
21896 		return DUK_TYPE_MASK_BOOLEAN;
21897 	case DUK_TAG_STRING:
21898 		return DUK_TYPE_MASK_STRING;
21899 	case DUK_TAG_OBJECT:
21900 		return DUK_TYPE_MASK_OBJECT;
21901 	case DUK_TAG_BUFFER:
21902 		return DUK_TYPE_MASK_BUFFER;
21903 	case DUK_TAG_POINTER:
21904 		return DUK_TYPE_MASK_POINTER;
21905 	case DUK_TAG_LIGHTFUNC:
21906 		return DUK_TYPE_MASK_LIGHTFUNC;
21907 #if defined(DUK_USE_FASTINT)
21908 	case DUK_TAG_FASTINT:
21909 #endif
21910 	default:
21911 		/* Note: number has no explicit tag (in 8-byte representation) */
21912 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
21913 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
21914 		return DUK_TYPE_MASK_NUMBER;
21915 	}
21916 #else  /* DUK_USE_PACKED_TVAL */
21917 	DUK_ASSERT(DUK_TVAL_IS_VALID_TAG(tv));
21918 	DUK_ASSERT(sizeof(duk__type_mask_from_tag) / sizeof(duk_uint_t) == DUK_TAG_MAX - DUK_TAG_MIN + 1);
21919 	return duk__type_mask_from_tag[DUK_TVAL_GET_TAG(tv) - DUK_TAG_MIN];
21920 #endif  /* DUK_USE_PACKED_TVAL */
21921 }
21922 
duk_get_type_mask(duk_hthread * thr,duk_idx_t idx)21923 DUK_EXTERNAL duk_uint_t duk_get_type_mask(duk_hthread *thr, duk_idx_t idx) {
21924 	duk_tval *tv;
21925 
21926 	DUK_ASSERT_API_ENTRY(thr);
21927 
21928 	tv = duk_get_tval_or_unused(thr, idx);
21929 	DUK_ASSERT(tv != NULL);
21930 
21931 	return duk_get_type_mask_tval(tv);
21932 }
21933 
duk_check_type_mask(duk_hthread * thr,duk_idx_t idx,duk_uint_t mask)21934 DUK_EXTERNAL duk_bool_t duk_check_type_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t mask) {
21935 	DUK_ASSERT_API_ENTRY(thr);
21936 
21937 	if (DUK_LIKELY((duk_get_type_mask(thr, idx) & mask) != 0U)) {
21938 		return 1;
21939 	}
21940 	if (mask & DUK_TYPE_MASK_THROW) {
21941 		DUK_ERROR_TYPE(thr, DUK_STR_UNEXPECTED_TYPE);
21942 		DUK_WO_NORETURN(return 0;);
21943 	}
21944 	return 0;
21945 }
21946 
duk_is_undefined(duk_hthread * thr,duk_idx_t idx)21947 DUK_EXTERNAL duk_bool_t duk_is_undefined(duk_hthread *thr, duk_idx_t idx) {
21948 	DUK_ASSERT_API_ENTRY(thr);
21949 	return duk__tag_check(thr, idx, DUK_TAG_UNDEFINED);
21950 }
21951 
duk_is_null(duk_hthread * thr,duk_idx_t idx)21952 DUK_EXTERNAL duk_bool_t duk_is_null(duk_hthread *thr, duk_idx_t idx) {
21953 	DUK_ASSERT_API_ENTRY(thr);
21954 	return duk__tag_check(thr, idx, DUK_TAG_NULL);
21955 }
21956 
duk_is_boolean(duk_hthread * thr,duk_idx_t idx)21957 DUK_EXTERNAL duk_bool_t duk_is_boolean(duk_hthread *thr, duk_idx_t idx) {
21958 	DUK_ASSERT_API_ENTRY(thr);
21959 	return duk__tag_check(thr, idx, DUK_TAG_BOOLEAN);
21960 }
21961 
duk_is_number(duk_hthread * thr,duk_idx_t idx)21962 DUK_EXTERNAL duk_bool_t duk_is_number(duk_hthread *thr, duk_idx_t idx) {
21963 	duk_tval *tv;
21964 
21965 	DUK_ASSERT_API_ENTRY(thr);
21966 
21967 	/*
21968 	 *  Number is special because it doesn't have a specific
21969 	 *  tag in the 8-byte representation.
21970 	 */
21971 
21972 	/* XXX: shorter version for unpacked representation? */
21973 
21974 	tv = duk_get_tval_or_unused(thr, idx);
21975 	DUK_ASSERT(tv != NULL);
21976 	return DUK_TVAL_IS_NUMBER(tv);
21977 }
21978 
duk_is_nan(duk_hthread * thr,duk_idx_t idx)21979 DUK_EXTERNAL duk_bool_t duk_is_nan(duk_hthread *thr, duk_idx_t idx) {
21980 	/* XXX: This will now return false for non-numbers, even though they would
21981 	 * coerce to NaN (as a general rule).  In particular, duk_get_number()
21982 	 * returns a NaN for non-numbers, so should this function also return
21983 	 * true for non-numbers?
21984 	 */
21985 
21986 	duk_tval *tv;
21987 
21988 	DUK_ASSERT_API_ENTRY(thr);
21989 
21990 	tv = duk_get_tval_or_unused(thr, idx);
21991 	DUK_ASSERT(tv != NULL);
21992 
21993 	/* XXX: for packed duk_tval an explicit "is number" check is unnecessary */
21994 	if (!DUK_TVAL_IS_NUMBER(tv)) {
21995 		return 0;
21996 	}
21997 	return (duk_bool_t) DUK_ISNAN(DUK_TVAL_GET_NUMBER(tv));
21998 }
21999 
duk_is_string(duk_hthread * thr,duk_idx_t idx)22000 DUK_EXTERNAL duk_bool_t duk_is_string(duk_hthread *thr, duk_idx_t idx) {
22001 	DUK_ASSERT_API_ENTRY(thr);
22002 	return duk__tag_check(thr, idx, DUK_TAG_STRING);
22003 }
22004 
duk_is_string_notsymbol(duk_hthread * thr,duk_idx_t idx)22005 DUK_INTERNAL duk_bool_t duk_is_string_notsymbol(duk_hthread *thr, duk_idx_t idx) {
22006 	DUK_ASSERT_API_ENTRY(thr);
22007 	return duk_get_hstring_notsymbol(thr, idx) != NULL;
22008 }
22009 
duk_is_object(duk_hthread * thr,duk_idx_t idx)22010 DUK_EXTERNAL duk_bool_t duk_is_object(duk_hthread *thr, duk_idx_t idx) {
22011 	DUK_ASSERT_API_ENTRY(thr);
22012 	return duk__tag_check(thr, idx, DUK_TAG_OBJECT);
22013 }
22014 
duk_is_buffer(duk_hthread * thr,duk_idx_t idx)22015 DUK_EXTERNAL duk_bool_t duk_is_buffer(duk_hthread *thr, duk_idx_t idx) {
22016 	DUK_ASSERT_API_ENTRY(thr);
22017 	return duk__tag_check(thr, idx, DUK_TAG_BUFFER);
22018 }
22019 
22020 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_is_buffer_data(duk_hthread * thr,duk_idx_t idx)22021 DUK_EXTERNAL duk_bool_t duk_is_buffer_data(duk_hthread *thr, duk_idx_t idx) {
22022 	duk_tval *tv;
22023 
22024 	DUK_ASSERT_API_ENTRY(thr);
22025 
22026 	tv = duk_get_tval_or_unused(thr, idx);
22027 	DUK_ASSERT(tv != NULL);
22028 	if (DUK_TVAL_IS_BUFFER(tv)) {
22029 		return 1;
22030 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
22031 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
22032 		DUK_ASSERT(h != NULL);
22033 		if (DUK_HOBJECT_IS_BUFOBJ(h)) {
22034 			return 1;
22035 		}
22036 	}
22037 	return 0;
22038 }
22039 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
duk_is_buffer_data(duk_hthread * thr,duk_idx_t idx)22040 DUK_EXTERNAL duk_bool_t duk_is_buffer_data(duk_hthread *thr, duk_idx_t idx) {
22041 	DUK_ASSERT_API_ENTRY(thr);
22042 
22043 	return duk_is_buffer(thr, idx);
22044 }
22045 
22046 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
22047 
duk_is_pointer(duk_hthread * thr,duk_idx_t idx)22048 DUK_EXTERNAL duk_bool_t duk_is_pointer(duk_hthread *thr, duk_idx_t idx) {
22049 	DUK_ASSERT_API_ENTRY(thr);
22050 	return duk__tag_check(thr, idx, DUK_TAG_POINTER);
22051 }
22052 
duk_is_lightfunc(duk_hthread * thr,duk_idx_t idx)22053 DUK_EXTERNAL duk_bool_t duk_is_lightfunc(duk_hthread *thr, duk_idx_t idx) {
22054 	DUK_ASSERT_API_ENTRY(thr);
22055 	return duk__tag_check(thr, idx, DUK_TAG_LIGHTFUNC);
22056 }
22057 
duk_is_symbol(duk_hthread * thr,duk_idx_t idx)22058 DUK_EXTERNAL duk_bool_t duk_is_symbol(duk_hthread *thr, duk_idx_t idx) {
22059 	duk_hstring *h;
22060 
22061 	DUK_ASSERT_API_ENTRY(thr);
22062 	h = duk_get_hstring(thr, idx);
22063 	/* Use DUK_LIKELY() here because caller may be more likely to type
22064 	 * check an expected symbol than not.
22065 	 */
22066 	if (DUK_LIKELY(h != NULL && DUK_HSTRING_HAS_SYMBOL(h))) {
22067 		return 1;
22068 	}
22069 	return 0;
22070 }
22071 
22072 /* IsArray(), returns true for Array instance or Proxy of Array instance. */
duk_is_array(duk_hthread * thr,duk_idx_t idx)22073 DUK_EXTERNAL duk_bool_t duk_is_array(duk_hthread *thr, duk_idx_t idx) {
22074 	duk_tval *tv;
22075 
22076 	DUK_ASSERT_API_ENTRY(thr);
22077 
22078 	tv = duk_get_tval(thr, idx);
22079 	if (tv) {
22080 		return duk_js_isarray(tv);
22081 	}
22082 	return 0;
22083 }
22084 
duk_is_function(duk_hthread * thr,duk_idx_t idx)22085 DUK_EXTERNAL duk_bool_t duk_is_function(duk_hthread *thr, duk_idx_t idx) {
22086 	duk_tval *tv;
22087 
22088 	DUK_ASSERT_API_ENTRY(thr);
22089 
22090 	tv = duk_get_tval_or_unused(thr, idx);
22091 	if (DUK_TVAL_IS_OBJECT(tv)) {
22092 		duk_hobject *h;
22093 		h = DUK_TVAL_GET_OBJECT(tv);
22094 		DUK_ASSERT(h != NULL);
22095 		return DUK_HOBJECT_HAS_CALLABLE(h) ? 1 : 0;
22096 	}
22097 	if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
22098 		return 1;
22099 	}
22100 	return 0;
22101 }
22102 
duk_is_callable_tval(duk_hthread * thr,duk_tval * tv)22103 DUK_INTERNAL duk_bool_t duk_is_callable_tval(duk_hthread *thr, duk_tval *tv) {
22104 	DUK_ASSERT_API_ENTRY(thr);
22105 
22106 	DUK_UNREF(thr);
22107 
22108 	if (DUK_TVAL_IS_OBJECT(tv)) {
22109 		duk_hobject *h;
22110 		h = DUK_TVAL_GET_OBJECT(tv);
22111 		DUK_ASSERT(h != NULL);
22112 		return DUK_HOBJECT_HAS_CALLABLE(h) ? 1 : 0;
22113 	}
22114 	if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
22115 		return 1;
22116 	}
22117 	return 0;
22118 }
22119 
duk_is_constructable(duk_hthread * thr,duk_idx_t idx)22120 DUK_EXTERNAL duk_bool_t duk_is_constructable(duk_hthread *thr, duk_idx_t idx) {
22121 	duk_tval *tv;
22122 
22123 	DUK_ASSERT_API_ENTRY(thr);
22124 
22125 	tv = duk_get_tval_or_unused(thr, idx);
22126 	if (DUK_TVAL_IS_OBJECT(tv)) {
22127 		duk_hobject *h;
22128 		h = DUK_TVAL_GET_OBJECT(tv);
22129 		DUK_ASSERT(h != NULL);
22130 		return DUK_HOBJECT_HAS_CONSTRUCTABLE(h) ? 1 : 0;
22131 	}
22132 	if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
22133 		return 1;
22134 	}
22135 	return 0;
22136 }
22137 
duk_is_c_function(duk_hthread * thr,duk_idx_t idx)22138 DUK_EXTERNAL duk_bool_t duk_is_c_function(duk_hthread *thr, duk_idx_t idx) {
22139 	DUK_ASSERT_API_ENTRY(thr);
22140 	return duk__obj_flag_any_default_false(thr,
22141 	                                       idx,
22142 	                                       DUK_HOBJECT_FLAG_NATFUNC);
22143 }
22144 
duk_is_ecmascript_function(duk_hthread * thr,duk_idx_t idx)22145 DUK_EXTERNAL duk_bool_t duk_is_ecmascript_function(duk_hthread *thr, duk_idx_t idx) {
22146 	DUK_ASSERT_API_ENTRY(thr);
22147 	return duk__obj_flag_any_default_false(thr,
22148 	                                       idx,
22149 	                                       DUK_HOBJECT_FLAG_COMPFUNC);
22150 }
22151 
duk_is_bound_function(duk_hthread * thr,duk_idx_t idx)22152 DUK_EXTERNAL duk_bool_t duk_is_bound_function(duk_hthread *thr, duk_idx_t idx) {
22153 	DUK_ASSERT_API_ENTRY(thr);
22154 	return duk__obj_flag_any_default_false(thr,
22155 	                                       idx,
22156 	                                       DUK_HOBJECT_FLAG_BOUNDFUNC);
22157 }
22158 
duk_is_thread(duk_hthread * thr,duk_idx_t idx)22159 DUK_EXTERNAL duk_bool_t duk_is_thread(duk_hthread *thr, duk_idx_t idx) {
22160 	duk_hobject *obj;
22161 
22162 	DUK_ASSERT_API_ENTRY(thr);
22163 
22164 	obj = duk_get_hobject(thr, idx);
22165 	if (obj) {
22166 		return (DUK_HOBJECT_GET_CLASS_NUMBER(obj) == DUK_HOBJECT_CLASS_THREAD ? 1 : 0);
22167 	}
22168 	return 0;
22169 }
22170 
duk_is_fixed_buffer(duk_hthread * thr,duk_idx_t idx)22171 DUK_EXTERNAL duk_bool_t duk_is_fixed_buffer(duk_hthread *thr, duk_idx_t idx) {
22172 	duk_tval *tv;
22173 
22174 	DUK_ASSERT_API_ENTRY(thr);
22175 
22176 	tv = duk_get_tval_or_unused(thr, idx);
22177 	DUK_ASSERT(tv != NULL);
22178 	if (DUK_TVAL_IS_BUFFER(tv)) {
22179 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
22180 		DUK_ASSERT(h != NULL);
22181 		return (DUK_HBUFFER_HAS_DYNAMIC(h) ? 0 : 1);
22182 	}
22183 	return 0;
22184 }
22185 
duk_is_dynamic_buffer(duk_hthread * thr,duk_idx_t idx)22186 DUK_EXTERNAL duk_bool_t duk_is_dynamic_buffer(duk_hthread *thr, duk_idx_t idx) {
22187 	duk_tval *tv;
22188 
22189 	DUK_ASSERT_API_ENTRY(thr);
22190 
22191 	tv = duk_get_tval_or_unused(thr, idx);
22192 	DUK_ASSERT(tv != NULL);
22193 	if (DUK_TVAL_IS_BUFFER(tv)) {
22194 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
22195 		DUK_ASSERT(h != NULL);
22196 		return (DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0);
22197 	}
22198 	return 0;
22199 }
22200 
duk_is_external_buffer(duk_hthread * thr,duk_idx_t idx)22201 DUK_EXTERNAL duk_bool_t duk_is_external_buffer(duk_hthread *thr, duk_idx_t idx) {
22202 	duk_tval *tv;
22203 
22204 	DUK_ASSERT_API_ENTRY(thr);
22205 
22206 	tv = duk_get_tval_or_unused(thr, idx);
22207 	DUK_ASSERT(tv != NULL);
22208 	if (DUK_TVAL_IS_BUFFER(tv)) {
22209 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
22210 		DUK_ASSERT(h != NULL);
22211 		return (DUK_HBUFFER_HAS_DYNAMIC(h) && DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0);
22212 	}
22213 	return 0;
22214 }
22215 
duk_get_error_code(duk_hthread * thr,duk_idx_t idx)22216 DUK_EXTERNAL duk_errcode_t duk_get_error_code(duk_hthread *thr, duk_idx_t idx) {
22217 	duk_hobject *h;
22218 	duk_uint_t sanity;
22219 
22220 	DUK_ASSERT_API_ENTRY(thr);
22221 
22222 	h = duk_get_hobject(thr, idx);
22223 
22224 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
22225 	do {
22226 		if (!h) {
22227 			return DUK_ERR_NONE;
22228 		}
22229 
22230 		/* XXX: something more convenient? */
22231 
22232 		if (h == thr->builtins[DUK_BIDX_EVAL_ERROR_PROTOTYPE]) {
22233 			return DUK_ERR_EVAL_ERROR;
22234 		}
22235 		if (h == thr->builtins[DUK_BIDX_RANGE_ERROR_PROTOTYPE]) {
22236 			return DUK_ERR_RANGE_ERROR;
22237 		}
22238 		if (h == thr->builtins[DUK_BIDX_REFERENCE_ERROR_PROTOTYPE]) {
22239 			return DUK_ERR_REFERENCE_ERROR;
22240 		}
22241 		if (h == thr->builtins[DUK_BIDX_SYNTAX_ERROR_PROTOTYPE]) {
22242 			return DUK_ERR_SYNTAX_ERROR;
22243 		}
22244 		if (h == thr->builtins[DUK_BIDX_TYPE_ERROR_PROTOTYPE]) {
22245 			return DUK_ERR_TYPE_ERROR;
22246 		}
22247 		if (h == thr->builtins[DUK_BIDX_URI_ERROR_PROTOTYPE]) {
22248 			return DUK_ERR_URI_ERROR;
22249 		}
22250 		if (h == thr->builtins[DUK_BIDX_ERROR_PROTOTYPE]) {
22251 			return DUK_ERR_ERROR;
22252 		}
22253 
22254 		h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
22255 	} while (--sanity > 0);
22256 
22257 	return DUK_ERR_NONE;
22258 }
22259 
22260 /*
22261  *  Pushers
22262  */
22263 
duk_push_tval(duk_hthread * thr,duk_tval * tv)22264 DUK_INTERNAL void duk_push_tval(duk_hthread *thr, duk_tval *tv) {
22265 	duk_tval *tv_slot;
22266 
22267 	DUK_ASSERT_API_ENTRY(thr);
22268 	DUK_ASSERT(tv != NULL);
22269 
22270 	DUK__CHECK_SPACE();
22271 	tv_slot = thr->valstack_top++;
22272 	DUK_TVAL_SET_TVAL(tv_slot, tv);
22273 	DUK_TVAL_INCREF(thr, tv);  /* no side effects */
22274 }
22275 
duk_push_undefined(duk_hthread * thr)22276 DUK_EXTERNAL void duk_push_undefined(duk_hthread *thr) {
22277 	DUK_ASSERT_API_ENTRY(thr);
22278 
22279 	DUK__CHECK_SPACE();
22280 
22281 	/* Because value stack init policy is 'undefined above top',
22282 	 * we don't need to write, just assert.
22283 	 */
22284 	thr->valstack_top++;
22285 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 1));
22286 }
22287 
duk_push_null(duk_hthread * thr)22288 DUK_EXTERNAL void duk_push_null(duk_hthread *thr) {
22289 	duk_tval *tv_slot;
22290 
22291 	DUK_ASSERT_API_ENTRY(thr);
22292 	DUK__CHECK_SPACE();
22293 	tv_slot = thr->valstack_top++;
22294 	DUK_TVAL_SET_NULL(tv_slot);
22295 }
22296 
duk_push_boolean(duk_hthread * thr,duk_bool_t val)22297 DUK_EXTERNAL void duk_push_boolean(duk_hthread *thr, duk_bool_t val) {
22298 	duk_tval *tv_slot;
22299 	duk_small_int_t b;
22300 
22301 	DUK_ASSERT_API_ENTRY(thr);
22302 	DUK__CHECK_SPACE();
22303 	b = (val ? 1 : 0);  /* ensure value is 1 or 0 (not other non-zero) */
22304 	tv_slot = thr->valstack_top++;
22305 	DUK_TVAL_SET_BOOLEAN(tv_slot, b);
22306 }
22307 
duk_push_true(duk_hthread * thr)22308 DUK_EXTERNAL void duk_push_true(duk_hthread *thr) {
22309 	duk_tval *tv_slot;
22310 
22311 	DUK_ASSERT_API_ENTRY(thr);
22312 	DUK__CHECK_SPACE();
22313 	tv_slot = thr->valstack_top++;
22314 	DUK_TVAL_SET_BOOLEAN_TRUE(tv_slot);
22315 }
22316 
duk_push_false(duk_hthread * thr)22317 DUK_EXTERNAL void duk_push_false(duk_hthread *thr) {
22318 	duk_tval *tv_slot;
22319 
22320 	DUK_ASSERT_API_ENTRY(thr);
22321 	DUK__CHECK_SPACE();
22322 	tv_slot = thr->valstack_top++;
22323 	DUK_TVAL_SET_BOOLEAN_FALSE(tv_slot);
22324 }
22325 
22326 /* normalize NaN which may not match our canonical internal NaN */
duk_push_number(duk_hthread * thr,duk_double_t val)22327 DUK_EXTERNAL void duk_push_number(duk_hthread *thr, duk_double_t val) {
22328 	duk_tval *tv_slot;
22329 	duk_double_union du;
22330 
22331 	DUK_ASSERT_API_ENTRY(thr);
22332 	DUK__CHECK_SPACE();
22333 	du.d = val;
22334 	DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
22335 	tv_slot = thr->valstack_top++;
22336 	DUK_TVAL_SET_NUMBER(tv_slot, du.d);
22337 }
22338 
duk_push_int(duk_hthread * thr,duk_int_t val)22339 DUK_EXTERNAL void duk_push_int(duk_hthread *thr, duk_int_t val) {
22340 #if defined(DUK_USE_FASTINT)
22341 	duk_tval *tv_slot;
22342 
22343 	DUK_ASSERT_API_ENTRY(thr);
22344 	DUK__CHECK_SPACE();
22345 	tv_slot = thr->valstack_top++;
22346 #if DUK_INT_MAX <= 0x7fffffffL
22347 	DUK_TVAL_SET_I32(tv_slot, (duk_int32_t) val);
22348 #else
22349 	if (val >= DUK_FASTINT_MIN && val <= DUK_FASTINT_MAX) {
22350 		DUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val);
22351 	} else {
22352 		duk_double_t = (duk_double_t) val;
22353 		DUK_TVAL_SET_NUMBER(tv_slot, d);
22354 	}
22355 #endif
22356 #else  /* DUK_USE_FASTINT */
22357 	duk_tval *tv_slot;
22358 	duk_double_t d;
22359 
22360 	DUK_ASSERT_API_ENTRY(thr);
22361 	DUK__CHECK_SPACE();
22362 	d = (duk_double_t) val;
22363 	tv_slot = thr->valstack_top++;
22364 	DUK_TVAL_SET_NUMBER(tv_slot, d);
22365 #endif  /* DUK_USE_FASTINT */
22366 }
22367 
duk_push_uint(duk_hthread * thr,duk_uint_t val)22368 DUK_EXTERNAL void duk_push_uint(duk_hthread *thr, duk_uint_t val) {
22369 #if defined(DUK_USE_FASTINT)
22370 	duk_tval *tv_slot;
22371 
22372 	DUK_ASSERT_API_ENTRY(thr);
22373 	DUK__CHECK_SPACE();
22374 	tv_slot = thr->valstack_top++;
22375 #if DUK_UINT_MAX <= 0xffffffffUL
22376 	DUK_TVAL_SET_U32(tv_slot, (duk_uint32_t) val);
22377 #else
22378 	if (val <= DUK_FASTINT_MAX) {  /* val is unsigned so >= 0 */
22379 		/* XXX: take advantage of val being unsigned, no need to mask */
22380 		DUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val);
22381 	} else {
22382 		duk_double_t = (duk_double_t) val;
22383 		DUK_TVAL_SET_NUMBER(tv_slot, d);
22384 	}
22385 #endif
22386 #else  /* DUK_USE_FASTINT */
22387 	duk_tval *tv_slot;
22388 	duk_double_t d;
22389 
22390 	DUK_ASSERT_API_ENTRY(thr);
22391 	DUK__CHECK_SPACE();
22392 	d = (duk_double_t) val;
22393 	tv_slot = thr->valstack_top++;
22394 	DUK_TVAL_SET_NUMBER(tv_slot, d);
22395 #endif  /* DUK_USE_FASTINT */
22396 }
22397 
duk_push_nan(duk_hthread * thr)22398 DUK_EXTERNAL void duk_push_nan(duk_hthread *thr) {
22399 	duk_tval *tv_slot;
22400 	duk_double_union du;
22401 
22402 	DUK_ASSERT_API_ENTRY(thr);
22403 	DUK__CHECK_SPACE();
22404 	DUK_DBLUNION_SET_NAN(&du);
22405 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
22406 	tv_slot = thr->valstack_top++;
22407 	DUK_TVAL_SET_NUMBER(tv_slot, du.d);
22408 }
22409 
duk_push_lstring(duk_hthread * thr,const char * str,duk_size_t len)22410 DUK_EXTERNAL const char *duk_push_lstring(duk_hthread *thr, const char *str, duk_size_t len) {
22411 	duk_hstring *h;
22412 	duk_tval *tv_slot;
22413 
22414 	DUK_ASSERT_API_ENTRY(thr);
22415 
22416 	/* Check stack before interning (avoid hanging temp). */
22417 	DUK__CHECK_SPACE();
22418 
22419 	/* NULL with zero length represents an empty string; NULL with higher
22420 	 * length is also now treated like an empty string although it is
22421 	 * a bit dubious.  This is unlike duk_push_string() which pushes a
22422 	 * 'null' if the input string is a NULL.
22423 	 */
22424 	if (DUK_UNLIKELY(str == NULL)) {
22425 		len = 0U;
22426 	}
22427 
22428 	/* Check for maximum string length. */
22429 	if (DUK_UNLIKELY(len > DUK_HSTRING_MAX_BYTELEN)) {
22430 		DUK_ERROR_RANGE(thr, DUK_STR_STRING_TOO_LONG);
22431 		DUK_WO_NORETURN(return NULL;);
22432 	}
22433 
22434 	h = duk_heap_strtable_intern_checked(thr, (const duk_uint8_t *) str, (duk_uint32_t) len);
22435 	DUK_ASSERT(h != NULL);
22436 
22437 	tv_slot = thr->valstack_top++;
22438 	DUK_TVAL_SET_STRING(tv_slot, h);
22439 	DUK_HSTRING_INCREF(thr, h);  /* no side effects */
22440 
22441 	return (const char *) DUK_HSTRING_GET_DATA(h);
22442 }
22443 
duk_push_string(duk_hthread * thr,const char * str)22444 DUK_EXTERNAL const char *duk_push_string(duk_hthread *thr, const char *str) {
22445 	DUK_ASSERT_API_ENTRY(thr);
22446 
22447 	if (str) {
22448 		return duk_push_lstring(thr, str, DUK_STRLEN(str));
22449 	} else {
22450 		duk_push_null(thr);
22451 		return NULL;
22452 	}
22453 }
22454 
22455 #if !defined(DUK_USE_PREFER_SIZE)
22456 #if defined(DUK_USE_LITCACHE_SIZE)
duk_push_literal_raw(duk_hthread * thr,const char * str,duk_size_t len)22457 DUK_EXTERNAL const char *duk_push_literal_raw(duk_hthread *thr, const char *str, duk_size_t len) {
22458 	duk_hstring *h;
22459 	duk_tval *tv_slot;
22460 
22461 	DUK_ASSERT_API_ENTRY(thr);
22462 	DUK_ASSERT(str != NULL);
22463 	DUK_ASSERT(str[len] == (char) 0);
22464 
22465 	/* Check for maximum string length. */
22466 	if (DUK_UNLIKELY(len > DUK_HSTRING_MAX_BYTELEN)) {
22467 		DUK_ERROR_RANGE(thr, DUK_STR_STRING_TOO_LONG);
22468 		DUK_WO_NORETURN(return NULL;);
22469 	}
22470 
22471 	h = duk_heap_strtable_intern_literal_checked(thr, (const duk_uint8_t *) str, (duk_uint32_t) len);
22472 	DUK_ASSERT(h != NULL);
22473 
22474 	tv_slot = thr->valstack_top++;
22475 	DUK_TVAL_SET_STRING(tv_slot, h);
22476 	DUK_HSTRING_INCREF(thr, h);  /* no side effects */
22477 
22478 	return (const char *) DUK_HSTRING_GET_DATA(h);
22479 }
22480 #else  /* DUK_USE_LITCACHE_SIZE */
duk_push_literal_raw(duk_hthread * thr,const char * str,duk_size_t len)22481 DUK_EXTERNAL const char *duk_push_literal_raw(duk_hthread *thr, const char *str, duk_size_t len) {
22482 	DUK_ASSERT_API_ENTRY(thr);
22483 	DUK_ASSERT(str != NULL);
22484 	DUK_ASSERT(str[len] == (char) 0);
22485 
22486 	return duk_push_lstring(thr, str, len);
22487 }
22488 #endif  /* DUK_USE_LITCACHE_SIZE */
22489 #endif  /* !DUK_USE_PREFER_SIZE */
22490 
duk_push_pointer(duk_hthread * thr,void * val)22491 DUK_EXTERNAL void duk_push_pointer(duk_hthread *thr, void *val) {
22492 	duk_tval *tv_slot;
22493 
22494 	DUK_ASSERT_API_ENTRY(thr);
22495 	DUK__CHECK_SPACE();
22496 	tv_slot = thr->valstack_top++;
22497 	DUK_TVAL_SET_POINTER(tv_slot, val);
22498 }
22499 
duk_push_uint_to_hstring(duk_hthread * thr,duk_uint_t i)22500 DUK_INTERNAL duk_hstring *duk_push_uint_to_hstring(duk_hthread *thr, duk_uint_t i) {
22501 	duk_hstring *h_tmp;
22502 
22503 	DUK_ASSERT_API_ENTRY(thr);
22504 
22505 	/* XXX: this could be a direct DUK_SPRINTF to a buffer followed by duk_push_string() */
22506 	duk_push_uint(thr, (duk_uint_t) i);
22507 	h_tmp = duk_to_hstring_m1(thr);
22508 	DUK_ASSERT(h_tmp != NULL);
22509 	return h_tmp;
22510 }
22511 
duk__push_this_helper(duk_hthread * thr,duk_small_uint_t check_object_coercible)22512 DUK_LOCAL void duk__push_this_helper(duk_hthread *thr, duk_small_uint_t check_object_coercible) {
22513 	duk_tval *tv_slot;
22514 
22515 	DUK__CHECK_SPACE();
22516 
22517 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* because of valstack init policy */
22518 	tv_slot = thr->valstack_top++;
22519 
22520 	if (DUK_UNLIKELY(thr->callstack_curr == NULL)) {
22521 		if (check_object_coercible) {
22522 			goto type_error;
22523 		}
22524 		/* 'undefined' already on stack top */
22525 	} else {
22526 		duk_tval *tv;
22527 
22528 		/* 'this' binding is just before current activation's bottom */
22529 		DUK_ASSERT(thr->valstack_bottom > thr->valstack);
22530 		tv = thr->valstack_bottom - 1;
22531 		if (check_object_coercible &&
22532 		    (DUK_TVAL_IS_UNDEFINED(tv) || DUK_TVAL_IS_NULL(tv))) {
22533 			/* XXX: better macro for DUK_TVAL_IS_UNDEFINED_OR_NULL(tv) */
22534 			goto type_error;
22535 		}
22536 
22537 		DUK_TVAL_SET_TVAL(tv_slot, tv);
22538 		DUK_TVAL_INCREF(thr, tv);
22539 	}
22540 	return;
22541 
22542  type_error:
22543 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_OBJECT_COERCIBLE);
22544 	DUK_WO_NORETURN(return;);
22545 }
22546 
duk_push_this(duk_hthread * thr)22547 DUK_EXTERNAL void duk_push_this(duk_hthread *thr) {
22548 	DUK_ASSERT_API_ENTRY(thr);
22549 
22550 	duk__push_this_helper(thr, 0 /*check_object_coercible*/);
22551 }
22552 
duk_push_this_check_object_coercible(duk_hthread * thr)22553 DUK_INTERNAL void duk_push_this_check_object_coercible(duk_hthread *thr) {
22554 	DUK_ASSERT_API_ENTRY(thr);
22555 
22556 	duk__push_this_helper(thr, 1 /*check_object_coercible*/);
22557 }
22558 
duk_push_this_coercible_to_object(duk_hthread * thr)22559 DUK_INTERNAL duk_hobject *duk_push_this_coercible_to_object(duk_hthread *thr) {
22560 	duk_hobject *h;
22561 
22562 	DUK_ASSERT_API_ENTRY(thr);
22563 
22564 	duk__push_this_helper(thr, 1 /*check_object_coercible*/);
22565 	h = duk_to_hobject(thr, -1);
22566 	DUK_ASSERT(h != NULL);
22567 	return h;
22568 }
22569 
duk_push_this_coercible_to_string(duk_hthread * thr)22570 DUK_INTERNAL duk_hstring *duk_push_this_coercible_to_string(duk_hthread *thr) {
22571 	DUK_ASSERT_API_ENTRY(thr);
22572 
22573 	duk__push_this_helper(thr, 1 /*check_object_coercible*/);
22574 	return duk_to_hstring_m1(thr);  /* This will reject all Symbol values; accepts Symbol objects. */
22575 }
22576 
duk_get_borrowed_this_tval(duk_hthread * thr)22577 DUK_INTERNAL duk_tval *duk_get_borrowed_this_tval(duk_hthread *thr) {
22578 	DUK_ASSERT_API_ENTRY(thr);
22579 
22580 	DUK_ASSERT(thr->callstack_top > 0);  /* caller required to know */
22581 	DUK_ASSERT(thr->callstack_curr != NULL);  /* caller required to know */
22582 	DUK_ASSERT(thr->valstack_bottom > thr->valstack);  /* consequence of above */
22583 	DUK_ASSERT(thr->valstack_bottom - 1 >= thr->valstack);  /* 'this' binding exists */
22584 
22585 	return thr->valstack_bottom - 1;
22586 }
22587 
duk_push_new_target(duk_hthread * thr)22588 DUK_EXTERNAL void duk_push_new_target(duk_hthread *thr) {
22589 	duk_activation *act;
22590 
22591 	DUK_ASSERT_API_ENTRY(thr);
22592 
22593 	/* https://www.ecma-international.org/ecma-262/6.0/#sec-meta-properties-runtime-semantics-evaluation
22594 	 * https://www.ecma-international.org/ecma-262/6.0/#sec-getnewtarget
22595 	 *
22596 	 * No newTarget support now, so as a first approximation
22597 	 * use the resolved (non-bound) target function.
22598 	 *
22599 	 * Check CONSTRUCT flag from current function, or if running
22600 	 * direct eval, from a non-direct-eval parent (with possibly
22601 	 * more than one nested direct eval).  An alternative to this
22602 	 * would be to store [[NewTarget]] as a hidden symbol of the
22603 	 * lexical scope, and then just look up that variable.
22604 	 *
22605 	 * Calls from the application will either be for an empty
22606 	 * call stack, or a Duktape/C function as the top activation.
22607 	 */
22608 
22609 	act = thr->callstack_curr;
22610 	for (;;) {
22611 		if (act == NULL) {
22612 			break;
22613 		}
22614 
22615 		if (act->flags & DUK_ACT_FLAG_CONSTRUCT) {
22616 			duk_push_tval(thr, &act->tv_func);
22617 			return;
22618 		} else if (act->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
22619 			act = act->parent;
22620 		} else {
22621 			break;
22622 		}
22623 	}
22624 
22625 	duk_push_undefined(thr);
22626 }
22627 
duk_push_current_function(duk_hthread * thr)22628 DUK_EXTERNAL void duk_push_current_function(duk_hthread *thr) {
22629 	duk_activation *act;
22630 
22631 	DUK_ASSERT_API_ENTRY(thr);
22632 
22633 	act = thr->callstack_curr;
22634 	if (act != NULL) {
22635 		duk_push_tval(thr, &act->tv_func);
22636 	} else {
22637 		duk_push_undefined(thr);
22638 	}
22639 }
22640 
duk_push_current_thread(duk_hthread * thr)22641 DUK_EXTERNAL void duk_push_current_thread(duk_hthread *thr) {
22642 	DUK_ASSERT_API_ENTRY(thr);
22643 
22644 	if (thr->heap->curr_thread) {
22645 		duk_push_hobject(thr, (duk_hobject *) thr->heap->curr_thread);
22646 	} else {
22647 		duk_push_undefined(thr);
22648 	}
22649 }
22650 
duk_push_global_object(duk_hthread * thr)22651 DUK_EXTERNAL void duk_push_global_object(duk_hthread *thr) {
22652 	DUK_ASSERT_API_ENTRY(thr);
22653 
22654 	duk_push_hobject_bidx(thr, DUK_BIDX_GLOBAL);
22655 }
22656 
22657 /* XXX: size optimize */
duk__push_stash(duk_hthread * thr)22658 DUK_LOCAL void duk__push_stash(duk_hthread *thr) {
22659 	if (!duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE)) {
22660 		DUK_DDD(DUK_DDDPRINT("creating heap/global/thread stash on first use"));
22661 		duk_pop_unsafe(thr);
22662 		duk_push_bare_object(thr);
22663 		duk_dup_top(thr);
22664 		duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_C);  /* [ ... parent stash stash ] -> [ ... parent stash ] */
22665 	}
22666 	duk_remove_m2(thr);
22667 }
22668 
duk_push_heap_stash(duk_hthread * thr)22669 DUK_EXTERNAL void duk_push_heap_stash(duk_hthread *thr) {
22670 	duk_heap *heap;
22671 	DUK_ASSERT_API_ENTRY(thr);
22672 	heap = thr->heap;
22673 	DUK_ASSERT(heap->heap_object != NULL);
22674 	duk_push_hobject(thr, heap->heap_object);
22675 	duk__push_stash(thr);
22676 }
22677 
duk_push_global_stash(duk_hthread * thr)22678 DUK_EXTERNAL void duk_push_global_stash(duk_hthread *thr) {
22679 	DUK_ASSERT_API_ENTRY(thr);
22680 	duk_push_global_object(thr);
22681 	duk__push_stash(thr);
22682 }
22683 
duk_push_thread_stash(duk_hthread * thr,duk_hthread * target_thr)22684 DUK_EXTERNAL void duk_push_thread_stash(duk_hthread *thr, duk_hthread *target_thr) {
22685 	DUK_ASSERT_API_ENTRY(thr);
22686 	if (DUK_UNLIKELY(target_thr == NULL)) {
22687 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
22688 		DUK_WO_NORETURN(return;);
22689 	}
22690 	duk_push_hobject(thr, (duk_hobject *) target_thr);
22691 	duk__push_stash(thr);
22692 }
22693 
22694 /* XXX: duk_ssize_t would be useful here */
duk__try_push_vsprintf(duk_hthread * thr,void * buf,duk_size_t sz,const char * fmt,va_list ap)22695 DUK_LOCAL duk_int_t duk__try_push_vsprintf(duk_hthread *thr, void *buf, duk_size_t sz, const char *fmt, va_list ap) {
22696 	duk_int_t len;
22697 
22698 	DUK_CTX_ASSERT_VALID(thr);
22699 	DUK_UNREF(thr);
22700 
22701 	/* NUL terminator handling doesn't matter here */
22702 	len = DUK_VSNPRINTF((char *) buf, sz, fmt, ap);
22703 	if (len < (duk_int_t) sz) {
22704 		/* Return value of 'sz' or more indicates output was (potentially)
22705 		 * truncated.
22706 		 */
22707 		return (duk_int_t) len;
22708 	}
22709 	return -1;
22710 }
22711 
duk_push_vsprintf(duk_hthread * thr,const char * fmt,va_list ap)22712 DUK_EXTERNAL const char *duk_push_vsprintf(duk_hthread *thr, const char *fmt, va_list ap) {
22713 	duk_uint8_t stack_buf[DUK_PUSH_SPRINTF_INITIAL_SIZE];
22714 	duk_size_t sz = DUK_PUSH_SPRINTF_INITIAL_SIZE;
22715 	duk_bool_t pushed_buf = 0;
22716 	void *buf;
22717 	duk_int_t len;  /* XXX: duk_ssize_t */
22718 	const char *res;
22719 
22720 	DUK_ASSERT_API_ENTRY(thr);
22721 
22722 	/* special handling of fmt==NULL */
22723 	if (!fmt) {
22724 		duk_hstring *h_str;
22725 		duk_push_hstring_empty(thr);
22726 		h_str = duk_known_hstring(thr, -1);
22727 		return (const char *) DUK_HSTRING_GET_DATA(h_str);
22728 	}
22729 
22730 	/* initial estimate based on format string */
22731 	sz = DUK_STRLEN(fmt) + 16;  /* format plus something to avoid just missing */
22732 	if (sz < DUK_PUSH_SPRINTF_INITIAL_SIZE) {
22733 		sz = DUK_PUSH_SPRINTF_INITIAL_SIZE;
22734 	}
22735 	DUK_ASSERT(sz > 0);
22736 
22737 	/* Try to make do with a stack buffer to avoid allocating a temporary buffer.
22738 	 * This works 99% of the time which is quite nice.
22739 	 */
22740 	for (;;) {
22741 		va_list ap_copy;  /* copied so that 'ap' can be reused */
22742 
22743 		if (sz <= sizeof(stack_buf)) {
22744 			buf = stack_buf;
22745 		} else if (!pushed_buf) {
22746 			pushed_buf = 1;
22747 			buf = duk_push_dynamic_buffer(thr, sz);
22748 		} else {
22749 			buf = duk_resize_buffer(thr, -1, sz);
22750 		}
22751 		DUK_ASSERT(buf != NULL);
22752 
22753 		DUK_VA_COPY(ap_copy, ap);
22754 		len = duk__try_push_vsprintf(thr, buf, sz, fmt, ap_copy);
22755 		va_end(ap_copy);
22756 		if (len >= 0) {
22757 			break;
22758 		}
22759 
22760 		/* failed, resize and try again */
22761 		sz = sz * 2;
22762 		if (DUK_UNLIKELY(sz >= DUK_PUSH_SPRINTF_SANITY_LIMIT)) {
22763 			DUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG);
22764 			DUK_WO_NORETURN(return NULL;);
22765 		}
22766 	}
22767 
22768 	/* Cannot use duk_buffer_to_string() on the buffer because it is
22769 	 * usually larger than 'len'; 'buf' is also usually a stack buffer.
22770 	 */
22771 	res = duk_push_lstring(thr, (const char *) buf, (duk_size_t) len);  /* [ buf? res ] */
22772 	if (pushed_buf) {
22773 		duk_remove_m2(thr);
22774 	}
22775 	return res;
22776 }
22777 
duk_push_sprintf(duk_hthread * thr,const char * fmt,...)22778 DUK_EXTERNAL const char *duk_push_sprintf(duk_hthread *thr, const char *fmt, ...) {
22779 	va_list ap;
22780 	const char *ret;
22781 
22782 	DUK_ASSERT_API_ENTRY(thr);
22783 
22784 	/* allow fmt==NULL */
22785 	va_start(ap, fmt);
22786 	ret = duk_push_vsprintf(thr, fmt, ap);
22787 	va_end(ap);
22788 
22789 	return ret;
22790 }
22791 
duk_push_object_helper(duk_hthread * thr,duk_uint_t hobject_flags_and_class,duk_small_int_t prototype_bidx)22792 DUK_INTERNAL duk_hobject *duk_push_object_helper(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) {
22793 	duk_tval *tv_slot;
22794 	duk_hobject *h;
22795 
22796 	DUK_ASSERT_API_ENTRY(thr);
22797 	DUK_ASSERT(prototype_bidx == -1 ||
22798 	           (prototype_bidx >= 0 && prototype_bidx < DUK_NUM_BUILTINS));
22799 
22800 	DUK__CHECK_SPACE();
22801 
22802 	h = duk_hobject_alloc(thr, hobject_flags_and_class);
22803 	DUK_ASSERT(h != NULL);
22804 
22805 	DUK_DDD(DUK_DDDPRINT("created object with flags: 0x%08lx", (unsigned long) h->hdr.h_flags));
22806 
22807 	tv_slot = thr->valstack_top;
22808 	DUK_TVAL_SET_OBJECT(tv_slot, h);
22809 	DUK_HOBJECT_INCREF(thr, h);  /* no side effects */
22810 	thr->valstack_top++;
22811 
22812 	/* object is now reachable */
22813 
22814 	if (prototype_bidx >= 0) {
22815 		DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, h, thr->builtins[prototype_bidx]);
22816 	} else {
22817 		DUK_ASSERT(prototype_bidx == -1);
22818 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h) == NULL);
22819 	}
22820 
22821 	return h;
22822 }
22823 
duk_push_object_helper_proto(duk_hthread * thr,duk_uint_t hobject_flags_and_class,duk_hobject * proto)22824 DUK_INTERNAL duk_hobject *duk_push_object_helper_proto(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_hobject *proto) {
22825 	duk_hobject *h;
22826 
22827 	DUK_ASSERT_API_ENTRY(thr);
22828 
22829 	h = duk_push_object_helper(thr, hobject_flags_and_class, -1);
22830 	DUK_ASSERT(h != NULL);
22831 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, h, proto);
22832 	return h;
22833 }
22834 
duk_push_object(duk_hthread * thr)22835 DUK_EXTERNAL duk_idx_t duk_push_object(duk_hthread *thr) {
22836 	DUK_ASSERT_API_ENTRY(thr);
22837 
22838 	(void) duk_push_object_helper(thr,
22839 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
22840 	                              DUK_HOBJECT_FLAG_FASTREFS |
22841 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
22842 	                              DUK_BIDX_OBJECT_PROTOTYPE);
22843 	return duk_get_top_index_unsafe(thr);
22844 }
22845 
duk_push_array(duk_hthread * thr)22846 DUK_EXTERNAL duk_idx_t duk_push_array(duk_hthread *thr) {
22847 	duk_uint_t flags;
22848 	duk_harray *obj;
22849 	duk_idx_t ret;
22850 	duk_tval *tv_slot;
22851 
22852 	DUK_ASSERT_API_ENTRY(thr);
22853 
22854 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
22855 	        DUK_HOBJECT_FLAG_FASTREFS |
22856 	        DUK_HOBJECT_FLAG_ARRAY_PART |
22857 	        DUK_HOBJECT_FLAG_EXOTIC_ARRAY |
22858 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAY);
22859 
22860 	obj = duk_harray_alloc(thr, flags);
22861 	DUK_ASSERT(obj != NULL);
22862 
22863 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[DUK_BIDX_ARRAY_PROTOTYPE]);
22864 
22865 	tv_slot = thr->valstack_top;
22866 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
22867 	DUK_HOBJECT_INCREF(thr, obj);  /* XXX: could preallocate with refcount = 1 */
22868 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
22869 	thr->valstack_top++;
22870 
22871 	DUK_ASSERT(obj->length == 0);  /* Array .length starts at zero. */
22872 	return ret;
22873 }
22874 
duk_push_bare_array(duk_hthread * thr)22875 DUK_EXTERNAL duk_idx_t duk_push_bare_array(duk_hthread *thr) {
22876 	duk_uint_t flags;
22877 	duk_harray *obj;
22878 	duk_idx_t ret;
22879 	duk_tval *tv_slot;
22880 
22881 	DUK_ASSERT_API_ENTRY(thr);
22882 
22883 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
22884 	        DUK_HOBJECT_FLAG_FASTREFS |
22885 	        DUK_HOBJECT_FLAG_ARRAY_PART |
22886 	        DUK_HOBJECT_FLAG_EXOTIC_ARRAY |
22887 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAY);
22888 
22889 	obj = duk_harray_alloc(thr, flags);
22890 	DUK_ASSERT(obj != NULL);
22891 
22892 	tv_slot = thr->valstack_top;
22893 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
22894 	DUK_HOBJECT_INCREF(thr, obj);  /* XXX: could preallocate with refcount = 1 */
22895 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
22896 	thr->valstack_top++;
22897 
22898 	DUK_ASSERT(obj->length == 0);  /* Array .length starts at zero. */
22899 	return ret;
22900 }
22901 
duk_push_harray(duk_hthread * thr)22902 DUK_INTERNAL duk_harray *duk_push_harray(duk_hthread *thr) {
22903 	/* XXX: API call could do this directly, cast to void in API macro. */
22904 	duk_harray *a;
22905 
22906 	DUK_ASSERT_API_ENTRY(thr);
22907 
22908 	(void) duk_push_array(thr);
22909 	DUK_ASSERT(DUK_TVAL_IS_OBJECT(thr->valstack_top - 1));
22910 	a = (duk_harray *) DUK_TVAL_GET_OBJECT(thr->valstack_top - 1);
22911 	DUK_ASSERT(a != NULL);
22912 	return a;
22913 }
22914 
22915 /* Push a duk_harray with preallocated size (.length also set to match size).
22916  * Caller may then populate array part of the duk_harray directly.
22917  */
duk_push_harray_with_size(duk_hthread * thr,duk_uint32_t size)22918 DUK_INTERNAL duk_harray *duk_push_harray_with_size(duk_hthread *thr, duk_uint32_t size) {
22919 	duk_harray *a;
22920 
22921 	DUK_ASSERT_API_ENTRY(thr);
22922 
22923 	a = duk_push_harray(thr);
22924 
22925 	duk_hobject_realloc_props(thr,
22926 	                          (duk_hobject *) a,
22927 	                          0,
22928 	                          size,
22929 	                          0,
22930 	                          0);
22931 	a->length = size;
22932 	return a;
22933 }
22934 
duk_push_harray_with_size_outptr(duk_hthread * thr,duk_uint32_t size)22935 DUK_INTERNAL duk_tval *duk_push_harray_with_size_outptr(duk_hthread *thr, duk_uint32_t size) {
22936 	duk_harray *a;
22937 
22938 	DUK_ASSERT_API_ENTRY(thr);
22939 
22940 	a = duk_push_harray_with_size(thr, size);
22941 	DUK_ASSERT(a != NULL);
22942 	return DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) a);
22943 }
22944 
duk_push_thread_raw(duk_hthread * thr,duk_uint_t flags)22945 DUK_EXTERNAL duk_idx_t duk_push_thread_raw(duk_hthread *thr, duk_uint_t flags) {
22946 	duk_hthread *obj;
22947 	duk_idx_t ret;
22948 	duk_tval *tv_slot;
22949 
22950 	DUK_ASSERT_API_ENTRY(thr);
22951 
22952 	DUK__CHECK_SPACE();
22953 
22954 	obj = duk_hthread_alloc(thr,
22955 	                        DUK_HOBJECT_FLAG_EXTENSIBLE |
22956 	                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_THREAD));
22957 	DUK_ASSERT(obj != NULL);
22958 	obj->state = DUK_HTHREAD_STATE_INACTIVE;
22959 #if defined(DUK_USE_ROM_STRINGS)
22960 	/* Nothing to initialize, strs[] is in ROM. */
22961 #else
22962 #if defined(DUK_USE_HEAPPTR16)
22963 	obj->strs16 = thr->strs16;
22964 #else
22965 	obj->strs = thr->strs;
22966 #endif
22967 #endif
22968 	DUK_DDD(DUK_DDDPRINT("created thread object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags));
22969 
22970 	/* make the new thread reachable */
22971 	tv_slot = thr->valstack_top;
22972 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
22973 	DUK_HTHREAD_INCREF(thr, obj);
22974 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
22975 	thr->valstack_top++;
22976 
22977 	/* important to do this *after* pushing, to make the thread reachable for gc */
22978 	if (DUK_UNLIKELY(!duk_hthread_init_stacks(thr->heap, obj))) {
22979 		DUK_ERROR_ALLOC_FAILED(thr);
22980 		DUK_WO_NORETURN(return 0;);
22981 	}
22982 
22983 	/* initialize built-ins - either by copying or creating new ones */
22984 	if (flags & DUK_THREAD_NEW_GLOBAL_ENV) {
22985 		duk_hthread_create_builtin_objects(obj);
22986 	} else {
22987 		duk_hthread_copy_builtin_objects(thr, obj);
22988 	}
22989 
22990 	/* default prototype */
22991 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, obj->builtins[DUK_BIDX_THREAD_PROTOTYPE]);
22992 
22993 	/* Initial stack size satisfies the stack slack constraints so there
22994 	 * is no need to require stack here.
22995 	 */
22996 	DUK_ASSERT(DUK_VALSTACK_INITIAL_SIZE >=
22997 	           DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
22998 
22999 	return ret;
23000 }
23001 
duk_push_hcompfunc(duk_hthread * thr)23002 DUK_INTERNAL duk_hcompfunc *duk_push_hcompfunc(duk_hthread *thr) {
23003 	duk_hcompfunc *obj;
23004 	duk_tval *tv_slot;
23005 
23006 	DUK_ASSERT_API_ENTRY(thr);
23007 
23008 	DUK__CHECK_SPACE();
23009 
23010 	/* Template functions are not strictly constructable (they don't
23011 	 * have a "prototype" property for instance), so leave the
23012 	 * DUK_HOBJECT_FLAG_CONSRUCTABLE flag cleared here.
23013 	 */
23014 
23015 	obj = duk_hcompfunc_alloc(thr,
23016 	                          DUK_HOBJECT_FLAG_EXTENSIBLE |
23017 	                          DUK_HOBJECT_FLAG_CALLABLE |
23018 	                          DUK_HOBJECT_FLAG_COMPFUNC |
23019 	                          DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION));
23020 	if (DUK_UNLIKELY(obj == NULL)) {
23021 		DUK_ERROR_ALLOC_FAILED(thr);
23022 		DUK_WO_NORETURN(return NULL;);
23023 	}
23024 
23025 	DUK_DDD(DUK_DDDPRINT("created compiled function object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags));
23026 
23027 	tv_slot = thr->valstack_top;
23028 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
23029 	DUK_HOBJECT_INCREF(thr, obj);
23030 	thr->valstack_top++;
23031 
23032 	/* default prototype */
23033 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) obj) == NULL);
23034 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
23035 
23036 	return obj;
23037 }
23038 
duk_push_hboundfunc(duk_hthread * thr)23039 DUK_INTERNAL duk_hboundfunc *duk_push_hboundfunc(duk_hthread *thr) {
23040 	duk_hboundfunc *obj;
23041 	duk_tval *tv_slot;
23042 
23043 	DUK_ASSERT_API_ENTRY(thr);
23044 
23045 	DUK__CHECK_SPACE();
23046 	obj = duk_hboundfunc_alloc(thr->heap,
23047 	                           DUK_HOBJECT_FLAG_EXTENSIBLE |
23048 	                           DUK_HOBJECT_FLAG_BOUNDFUNC |
23049 	                           DUK_HOBJECT_FLAG_CONSTRUCTABLE |
23050 	                           DUK_HOBJECT_FLAG_CALLABLE |
23051 	                           DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION));
23052 	if (!obj) {
23053 		DUK_ERROR_ALLOC_FAILED(thr);
23054 		DUK_WO_NORETURN(return NULL;);
23055 	}
23056 
23057 	tv_slot = thr->valstack_top++;
23058 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
23059 	DUK_HOBJECT_INCREF(thr, obj);
23060 
23061 	/* Prototype is left as NULL because the caller always sets it (and
23062 	 * it depends on the target function).
23063 	 */
23064 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) obj) == NULL);
23065 
23066 	return obj;
23067 }
23068 
duk__push_c_function_raw(duk_hthread * thr,duk_c_function func,duk_idx_t nargs,duk_uint_t flags,duk_small_uint_t proto_bidx)23069 DUK_LOCAL duk_idx_t duk__push_c_function_raw(duk_hthread *thr, duk_c_function func, duk_idx_t nargs, duk_uint_t flags, duk_small_uint_t proto_bidx) {
23070 	duk_hnatfunc *obj;
23071 	duk_idx_t ret;
23072 	duk_tval *tv_slot;
23073 	duk_int16_t func_nargs;
23074 
23075 	DUK_CTX_ASSERT_VALID(thr);
23076 
23077 	DUK__CHECK_SPACE();
23078 
23079 	if (DUK_UNLIKELY(func == NULL)) {
23080 		goto api_error;
23081 	}
23082 	if (nargs >= 0 && nargs < DUK_HNATFUNC_NARGS_MAX) {
23083 		func_nargs = (duk_int16_t) nargs;
23084 	} else if (nargs == DUK_VARARGS) {
23085 		func_nargs = DUK_HNATFUNC_NARGS_VARARGS;
23086 	} else {
23087 		goto api_error;
23088 	}
23089 
23090 	obj = duk_hnatfunc_alloc(thr, flags);
23091 	DUK_ASSERT(obj != NULL);
23092 
23093 	obj->func = func;
23094 	obj->nargs = func_nargs;
23095 
23096 	DUK_DDD(DUK_DDDPRINT("created native function object with flags: 0x%08lx, nargs=%ld",
23097 	                     (unsigned long) obj->obj.hdr.h_flags, (long) obj->nargs));
23098 
23099 	tv_slot = thr->valstack_top;
23100 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
23101 	DUK_HOBJECT_INCREF(thr, obj);
23102 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
23103 	thr->valstack_top++;
23104 
23105 	DUK_ASSERT_BIDX_VALID(proto_bidx);
23106 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[proto_bidx]);
23107 	return ret;
23108 
23109  api_error:
23110 	DUK_ERROR_TYPE_INVALID_ARGS(thr);
23111 	DUK_WO_NORETURN(return 0;);
23112 }
23113 
duk_push_c_function(duk_hthread * thr,duk_c_function func,duk_int_t nargs)23114 DUK_EXTERNAL duk_idx_t duk_push_c_function(duk_hthread *thr, duk_c_function func, duk_int_t nargs) {
23115 	duk_uint_t flags;
23116 
23117 	DUK_ASSERT_API_ENTRY(thr);
23118 
23119 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
23120 	        DUK_HOBJECT_FLAG_CONSTRUCTABLE |
23121 	        DUK_HOBJECT_FLAG_CALLABLE |
23122 	        DUK_HOBJECT_FLAG_FASTREFS |
23123 	        DUK_HOBJECT_FLAG_NATFUNC |
23124 	        DUK_HOBJECT_FLAG_NEWENV |
23125 	        DUK_HOBJECT_FLAG_STRICT |
23126 	        DUK_HOBJECT_FLAG_NOTAIL |
23127 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
23128 
23129 	/* Default prototype is a Duktape specific %NativeFunctionPrototype%
23130 	 * which provides .length and .name getters.
23131 	 */
23132 	return duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE);
23133 }
23134 
duk_push_c_function_builtin(duk_hthread * thr,duk_c_function func,duk_int_t nargs)23135 DUK_INTERNAL void duk_push_c_function_builtin(duk_hthread *thr, duk_c_function func, duk_int_t nargs) {
23136 	duk_uint_t flags;
23137 
23138 	DUK_ASSERT_API_ENTRY(thr);
23139 
23140 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
23141 	        DUK_HOBJECT_FLAG_CONSTRUCTABLE |
23142 	        DUK_HOBJECT_FLAG_CALLABLE |
23143 	        DUK_HOBJECT_FLAG_FASTREFS |
23144 	        DUK_HOBJECT_FLAG_NATFUNC |
23145 	        DUK_HOBJECT_FLAG_NEWENV |
23146 	        DUK_HOBJECT_FLAG_STRICT |
23147 	        DUK_HOBJECT_FLAG_NOTAIL |
23148 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
23149 
23150 	/* Must use Function.prototype for standard built-in functions. */
23151 	(void) duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_FUNCTION_PROTOTYPE);
23152 }
23153 
duk_push_c_function_builtin_noconstruct(duk_hthread * thr,duk_c_function func,duk_int_t nargs)23154 DUK_INTERNAL void duk_push_c_function_builtin_noconstruct(duk_hthread *thr, duk_c_function func, duk_int_t nargs) {
23155 	duk_uint_t flags;
23156 
23157 	DUK_ASSERT_API_ENTRY(thr);
23158 
23159 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
23160 	        DUK_HOBJECT_FLAG_CALLABLE |
23161 	        DUK_HOBJECT_FLAG_FASTREFS |
23162 	        DUK_HOBJECT_FLAG_NATFUNC |
23163 	        DUK_HOBJECT_FLAG_NEWENV |
23164 	        DUK_HOBJECT_FLAG_STRICT |
23165 	        DUK_HOBJECT_FLAG_NOTAIL |
23166 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
23167 
23168 	/* Must use Function.prototype for standard built-in functions. */
23169 	(void) duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_FUNCTION_PROTOTYPE);
23170 }
23171 
duk_push_c_lightfunc(duk_hthread * thr,duk_c_function func,duk_idx_t nargs,duk_idx_t length,duk_int_t magic)23172 DUK_EXTERNAL duk_idx_t duk_push_c_lightfunc(duk_hthread *thr, duk_c_function func, duk_idx_t nargs, duk_idx_t length, duk_int_t magic) {
23173 	duk_small_uint_t lf_flags;
23174 	duk_tval *tv_slot;
23175 
23176 	DUK_ASSERT_API_ENTRY(thr);
23177 
23178 	DUK__CHECK_SPACE();
23179 
23180 	if (nargs >= DUK_LFUNC_NARGS_MIN && nargs <= DUK_LFUNC_NARGS_MAX) {
23181 		/* as is */
23182 	} else if (nargs == DUK_VARARGS) {
23183 		nargs = DUK_LFUNC_NARGS_VARARGS;
23184 	} else {
23185 		goto api_error;
23186 	}
23187 	if (DUK_UNLIKELY(!(length >= DUK_LFUNC_LENGTH_MIN && length <= DUK_LFUNC_LENGTH_MAX))) {
23188 		goto api_error;
23189 	}
23190 	if (DUK_UNLIKELY(!(magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX))) {
23191 		goto api_error;
23192 	}
23193 
23194 	lf_flags = DUK_LFUNC_FLAGS_PACK((duk_small_int_t) magic, (duk_small_uint_t) length, (duk_small_uint_t) nargs);
23195 	tv_slot = thr->valstack_top++;
23196 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv_slot));
23197 	DUK_TVAL_SET_LIGHTFUNC(tv_slot, func, lf_flags);
23198 	DUK_ASSERT(tv_slot >= thr->valstack_bottom);
23199 	return (duk_idx_t) (tv_slot - thr->valstack_bottom);
23200 
23201  api_error:
23202 	DUK_ERROR_TYPE_INVALID_ARGS(thr);
23203 	DUK_WO_NORETURN(return 0;);
23204 }
23205 
23206 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_push_bufobj_raw(duk_hthread * thr,duk_uint_t hobject_flags_and_class,duk_small_int_t prototype_bidx)23207 DUK_INTERNAL duk_hbufobj *duk_push_bufobj_raw(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) {
23208 	duk_hbufobj *obj;
23209 	duk_tval *tv_slot;
23210 
23211 	DUK_ASSERT_API_ENTRY(thr);
23212 	DUK_ASSERT(prototype_bidx >= 0);
23213 
23214 	DUK__CHECK_SPACE();
23215 
23216 	obj = duk_hbufobj_alloc(thr, hobject_flags_and_class);
23217 	DUK_ASSERT(obj != NULL);
23218 
23219 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[prototype_bidx]);
23220 	DUK_HBUFOBJ_ASSERT_VALID(obj);
23221 
23222 	tv_slot = thr->valstack_top;
23223 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
23224 	DUK_HOBJECT_INCREF(thr, obj);
23225 	thr->valstack_top++;
23226 
23227 	return obj;
23228 }
23229 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
23230 
23231 /* XXX: There's quite a bit of overlap with buffer creation handling in
23232  * duk_bi_buffer.c.  Look for overlap and refactor.
23233  */
23234 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
23235 #define DUK__PACK_ARGS(classnum,protobidx,elemtype,elemshift,istypedarray) \
23236 	(((classnum) << 24) | ((protobidx) << 16) | ((elemtype) << 8) | ((elemshift) << 4) | (istypedarray))
23237 
23238 static const duk_uint32_t duk__bufobj_flags_lookup[] = {
23239 	/* Node.js Buffers are Uint8Array instances which inherit from Buffer.prototype. */
23240 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_ARRAYBUFFER,       DUK_BIDX_ARRAYBUFFER_PROTOTYPE,       DUK_HBUFOBJ_ELEM_UINT8,        0, 0),  /* DUK_BUFOBJ_ARRAYBUFFER */
23241 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8ARRAY,        DUK_BIDX_NODEJS_BUFFER_PROTOTYPE,     DUK_HBUFOBJ_ELEM_UINT8,        0, 1),  /* DUK_BUFOBJ_NODEJS_BUFFER */
23242 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_DATAVIEW,          DUK_BIDX_DATAVIEW_PROTOTYPE,          DUK_HBUFOBJ_ELEM_UINT8,        0, 0),  /* DUK_BUFOBJ_DATAVIEW */
23243 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT8ARRAY,         DUK_BIDX_INT8ARRAY_PROTOTYPE,         DUK_HBUFOBJ_ELEM_INT8,         0, 1),  /* DUK_BUFOBJ_INT8ARRAY */
23244 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8ARRAY,        DUK_BIDX_UINT8ARRAY_PROTOTYPE,        DUK_HBUFOBJ_ELEM_UINT8,        0, 1),  /* DUK_BUFOBJ_UINT8ARRAY */
23245 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY, DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE, DUK_HBUFOBJ_ELEM_UINT8CLAMPED, 0, 1),  /* DUK_BUFOBJ_UINT8CLAMPEDARRAY */
23246 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT16ARRAY,        DUK_BIDX_INT16ARRAY_PROTOTYPE,        DUK_HBUFOBJ_ELEM_INT16,        1, 1),  /* DUK_BUFOBJ_INT16ARRAY */
23247 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT16ARRAY,       DUK_BIDX_UINT16ARRAY_PROTOTYPE,       DUK_HBUFOBJ_ELEM_UINT16,       1, 1),  /* DUK_BUFOBJ_UINT16ARRAY */
23248 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT32ARRAY,        DUK_BIDX_INT32ARRAY_PROTOTYPE,        DUK_HBUFOBJ_ELEM_INT32,        2, 1),  /* DUK_BUFOBJ_INT32ARRAY */
23249 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT32ARRAY,       DUK_BIDX_UINT32ARRAY_PROTOTYPE,       DUK_HBUFOBJ_ELEM_UINT32,       2, 1),  /* DUK_BUFOBJ_UINT32ARRAY */
23250 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_FLOAT32ARRAY,      DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,      DUK_HBUFOBJ_ELEM_FLOAT32,      2, 1),  /* DUK_BUFOBJ_FLOAT32ARRAY */
23251 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_FLOAT64ARRAY,      DUK_BIDX_FLOAT64ARRAY_PROTOTYPE,      DUK_HBUFOBJ_ELEM_FLOAT64,      3, 1)   /* DUK_BUFOBJ_FLOAT64ARRAY */
23252 };
23253 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
23254 
23255 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_push_buffer_object(duk_hthread * thr,duk_idx_t idx_buffer,duk_size_t byte_offset,duk_size_t byte_length,duk_uint_t flags)23256 DUK_EXTERNAL void duk_push_buffer_object(duk_hthread *thr, duk_idx_t idx_buffer, duk_size_t byte_offset, duk_size_t byte_length, duk_uint_t flags) {
23257 	duk_hbufobj *h_bufobj;
23258 	duk_hbuffer *h_val;
23259 	duk_hobject *h_arraybuf;
23260 	duk_uint32_t tmp;
23261 	duk_uint_t classnum;
23262 	duk_uint_t protobidx;
23263 	duk_uint_t lookupidx;
23264 	duk_uint_t uint_offset, uint_length, uint_added;
23265 
23266 	DUK_ASSERT_API_ENTRY(thr);
23267 
23268 	/* The underlying types for offset/length in duk_hbufobj is
23269 	 * duk_uint_t; make sure argument values fit.
23270 	 */
23271 	uint_offset = (duk_uint_t) byte_offset;
23272 	uint_length = (duk_uint_t) byte_length;
23273 	if (sizeof(duk_size_t) != sizeof(duk_uint_t)) {
23274 		if (DUK_UNLIKELY((duk_size_t) uint_offset != byte_offset || (duk_size_t) uint_length != byte_length)) {
23275 			goto range_error;
23276 		}
23277 	}
23278 
23279 	DUK_ASSERT_DISABLE(flags >= 0);  /* flags is unsigned */
23280 	lookupidx = flags;
23281 	if (DUK_UNLIKELY(lookupidx >= sizeof(duk__bufobj_flags_lookup) / sizeof(duk_uint32_t))) {
23282 		goto arg_error;
23283 	}
23284 	tmp = duk__bufobj_flags_lookup[lookupidx];
23285 	classnum = tmp >> 24;
23286 	protobidx = (tmp >> 16) & 0xff;
23287 
23288 	h_arraybuf = duk_get_hobject(thr, idx_buffer);
23289 	if (h_arraybuf != NULL &&  /* argument is an object */
23290 	    flags != DUK_BUFOBJ_ARRAYBUFFER &&  /* creating a view */
23291 	    DUK_HOBJECT_GET_CLASS_NUMBER(h_arraybuf) == DUK_HOBJECT_CLASS_ARRAYBUFFER  /* argument is ArrayBuffer */) {
23292 		duk_uint_t tmp_offset;
23293 
23294 		DUK_HBUFOBJ_ASSERT_VALID((duk_hbufobj *) h_arraybuf);
23295 		h_val = ((duk_hbufobj *) h_arraybuf)->buf;
23296 		if (DUK_UNLIKELY(h_val == NULL)) {
23297 			goto arg_error;
23298 		}
23299 
23300 		tmp_offset = uint_offset + ((duk_hbufobj *) h_arraybuf)->offset;
23301 		if (DUK_UNLIKELY(tmp_offset < uint_offset)) {
23302 			goto range_error;
23303 		}
23304 		uint_offset = tmp_offset;
23305 
23306 		/* Note intentional difference to new TypedArray(): we allow
23307 		 * caller to create an uncovered typed array (which is memory
23308 		 * safe); new TypedArray() rejects it.
23309 		 */
23310 	} else {
23311 		/* Handle unexpected object arguments here too, for nice error
23312 		 * messages.
23313 		 */
23314 		h_arraybuf = NULL;
23315 		h_val = duk_require_hbuffer(thr, idx_buffer);
23316 	}
23317 
23318 	/* Wrap check for offset+length. */
23319 	uint_added = uint_offset + uint_length;
23320 	if (DUK_UNLIKELY(uint_added < uint_offset)) {
23321 		goto range_error;
23322 	}
23323 	DUK_ASSERT(uint_added >= uint_offset && uint_added >= uint_length);
23324 
23325 	DUK_ASSERT(h_val != NULL);
23326 
23327 	h_bufobj = duk_push_bufobj_raw(thr,
23328 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
23329 	                               DUK_HOBJECT_FLAG_BUFOBJ |
23330 	                               DUK_HOBJECT_CLASS_AS_FLAGS(classnum),
23331 	                               (duk_small_int_t) protobidx);
23332 	DUK_ASSERT(h_bufobj != NULL);
23333 
23334 	h_bufobj->buf = h_val;
23335 	DUK_HBUFFER_INCREF(thr, h_val);
23336 	h_bufobj->buf_prop = h_arraybuf;
23337 	DUK_HOBJECT_INCREF_ALLOWNULL(thr, h_arraybuf);
23338 	h_bufobj->offset = uint_offset;
23339 	h_bufobj->length = uint_length;
23340 	h_bufobj->shift = (tmp >> 4) & 0x0f;
23341 	h_bufobj->elem_type = (tmp >> 8) & 0xff;
23342 	h_bufobj->is_typedarray = tmp & 0x0f;
23343 	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
23344 
23345 	/* TypedArray views need an automatic ArrayBuffer which must be
23346 	 * provided as .buffer property of the view.  The ArrayBuffer is
23347 	 * referenced via duk_hbufobj->buf_prop and an inherited .buffer
23348 	 * accessor returns it.  The ArrayBuffer is created lazily on first
23349 	 * access if necessary so we don't need to do anything more here.
23350 	 */
23351 	return;
23352 
23353  range_error:
23354 	DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARGS);
23355 	DUK_WO_NORETURN(return;);
23356 
23357  arg_error:
23358 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_ARGS);
23359 	DUK_WO_NORETURN(return;);
23360 }
23361 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
duk_push_buffer_object(duk_hthread * thr,duk_idx_t idx_buffer,duk_size_t byte_offset,duk_size_t byte_length,duk_uint_t flags)23362 DUK_EXTERNAL void duk_push_buffer_object(duk_hthread *thr, duk_idx_t idx_buffer, duk_size_t byte_offset, duk_size_t byte_length, duk_uint_t flags) {
23363 	DUK_ASSERT_API_ENTRY(thr);
23364 	DUK_UNREF(idx_buffer);
23365 	DUK_UNREF(byte_offset);
23366 	DUK_UNREF(byte_length);
23367 	DUK_UNREF(flags);
23368 	DUK_ERROR_UNSUPPORTED(thr);
23369 	DUK_WO_NORETURN(return;);
23370 }
23371 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
23372 
duk_push_error_object_va_raw(duk_hthread * thr,duk_errcode_t err_code,const char * filename,duk_int_t line,const char * fmt,va_list ap)23373 DUK_EXTERNAL duk_idx_t duk_push_error_object_va_raw(duk_hthread *thr, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap) {
23374 	duk_hobject *proto;
23375 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
23376 	duk_small_uint_t augment_flags;
23377 #endif
23378 
23379 	DUK_ASSERT_API_ENTRY(thr);
23380 	DUK_ASSERT(thr != NULL);
23381 	DUK_UNREF(filename);
23382 	DUK_UNREF(line);
23383 
23384 	/* Error code also packs a tracedata related flag. */
23385 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
23386 	augment_flags = 0;
23387 	if (err_code & DUK_ERRCODE_FLAG_NOBLAME_FILELINE) {
23388 		augment_flags = DUK_AUGMENT_FLAG_NOBLAME_FILELINE;
23389 	}
23390 #endif
23391 	err_code = err_code & (~DUK_ERRCODE_FLAG_NOBLAME_FILELINE);
23392 
23393 	/* error gets its 'name' from the prototype */
23394 	proto = duk_error_prototype_from_code(thr, err_code);
23395 	(void) duk_push_object_helper_proto(thr,
23396 	                                    DUK_HOBJECT_FLAG_EXTENSIBLE |
23397 	                                    DUK_HOBJECT_FLAG_FASTREFS |
23398 	                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR),
23399 	                                    proto);
23400 
23401 	/* ... and its 'message' from an instance property */
23402 	if (fmt) {
23403 		duk_push_vsprintf(thr, fmt, ap);
23404 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
23405 	} else {
23406 		/* If no explicit message given, put error code into message field
23407 		 * (as a number).  This is not fully in keeping with the ECMAScript
23408 		 * error model because messages are supposed to be strings (Error
23409 		 * constructors use ToString() on their argument).  However, it's
23410 		 * probably more useful than having a separate 'code' property.
23411 		 */
23412 		duk_push_int(thr, err_code);
23413 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
23414 	}
23415 
23416 	/* XXX: .code = err_code disabled, not sure if useful */
23417 
23418 	/* Creation time error augmentation */
23419 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
23420 	/* filename may be NULL in which case file/line is not recorded */
23421 	duk_err_augment_error_create(thr, thr, filename, line, augment_flags);  /* may throw an error */
23422 #endif
23423 
23424 	return duk_get_top_index_unsafe(thr);
23425 }
23426 
duk_push_error_object_raw(duk_hthread * thr,duk_errcode_t err_code,const char * filename,duk_int_t line,const char * fmt,...)23427 DUK_EXTERNAL duk_idx_t duk_push_error_object_raw(duk_hthread *thr, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) {
23428 	va_list ap;
23429 	duk_idx_t ret;
23430 
23431 	DUK_ASSERT_API_ENTRY(thr);
23432 
23433 	va_start(ap, fmt);
23434 	ret = duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
23435 	va_end(ap);
23436 	return ret;
23437 }
23438 
23439 #if !defined(DUK_USE_VARIADIC_MACROS)
duk_push_error_object_stash(duk_hthread * thr,duk_errcode_t err_code,const char * fmt,...)23440 DUK_EXTERNAL duk_idx_t duk_push_error_object_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, ...) {
23441 	const char *filename = duk_api_global_filename;
23442 	duk_int_t line = duk_api_global_line;
23443 	va_list ap;
23444 	duk_idx_t ret;
23445 
23446 	DUK_ASSERT_API_ENTRY(thr);
23447 
23448 	duk_api_global_filename = NULL;
23449 	duk_api_global_line = 0;
23450 	va_start(ap, fmt);
23451 	ret = duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
23452 	va_end(ap);
23453 	return ret;
23454 }
23455 #endif  /* DUK_USE_VARIADIC_MACROS */
23456 
duk_push_buffer_raw(duk_hthread * thr,duk_size_t size,duk_small_uint_t flags)23457 DUK_EXTERNAL void *duk_push_buffer_raw(duk_hthread *thr, duk_size_t size, duk_small_uint_t flags) {
23458 	duk_tval *tv_slot;
23459 	duk_hbuffer *h;
23460 	void *buf_data;
23461 
23462 	DUK_ASSERT_API_ENTRY(thr);
23463 
23464 	DUK__CHECK_SPACE();
23465 
23466 	/* Check for maximum buffer length. */
23467 	if (DUK_UNLIKELY(size > DUK_HBUFFER_MAX_BYTELEN)) {
23468 		DUK_ERROR_RANGE(thr, DUK_STR_BUFFER_TOO_LONG);
23469 		DUK_WO_NORETURN(return NULL;);
23470 	}
23471 
23472 	h = duk_hbuffer_alloc(thr->heap, size, flags, &buf_data);
23473 	if (DUK_UNLIKELY(h == NULL)) {
23474 		DUK_ERROR_ALLOC_FAILED(thr);
23475 		DUK_WO_NORETURN(return NULL;);
23476 	}
23477 
23478 	tv_slot = thr->valstack_top;
23479 	DUK_TVAL_SET_BUFFER(tv_slot, h);
23480 	DUK_HBUFFER_INCREF(thr, h);
23481 	thr->valstack_top++;
23482 
23483 	return (void *) buf_data;
23484 }
23485 
duk_push_fixed_buffer_nozero(duk_hthread * thr,duk_size_t len)23486 DUK_INTERNAL void *duk_push_fixed_buffer_nozero(duk_hthread *thr, duk_size_t len) {
23487 	DUK_ASSERT_API_ENTRY(thr);
23488 	return duk_push_buffer_raw(thr, len, DUK_BUF_FLAG_NOZERO);
23489 }
23490 
duk_push_fixed_buffer_zero(duk_hthread * thr,duk_size_t len)23491 DUK_INTERNAL void *duk_push_fixed_buffer_zero(duk_hthread *thr, duk_size_t len) {
23492 	void *ptr;
23493 
23494 	DUK_ASSERT_API_ENTRY(thr);
23495 
23496 	ptr = duk_push_buffer_raw(thr, len, 0);
23497 	DUK_ASSERT(ptr != NULL);
23498 #if !defined(DUK_USE_ZERO_BUFFER_DATA)
23499 	/* ES2015 requires zeroing even when DUK_USE_ZERO_BUFFER_DATA
23500 	 * is not set.
23501 	 */
23502 	duk_memzero((void *) ptr, (size_t) len);
23503 #endif
23504 	return ptr;
23505 }
23506 
23507 #if defined(DUK_USE_ES6_PROXY)
duk_push_proxy(duk_hthread * thr,duk_uint_t proxy_flags)23508 DUK_EXTERNAL duk_idx_t duk_push_proxy(duk_hthread *thr, duk_uint_t proxy_flags) {
23509 	duk_hobject *h_target;
23510 	duk_hobject *h_handler;
23511 	duk_hproxy *h_proxy;
23512 	duk_tval *tv_slot;
23513 	duk_uint_t flags;
23514 
23515 	DUK_ASSERT_API_ENTRY(thr);
23516 	DUK_UNREF(proxy_flags);
23517 
23518 	/* DUK__CHECK_SPACE() unnecessary because the Proxy is written to
23519 	 * value stack in-place.
23520 	 */
23521 #if 0
23522 	DUK__CHECK_SPACE();
23523 #endif
23524 
23525 	/* Reject a proxy object as the target because it would need
23526 	 * special handling in property lookups.  (ES2015 has no such
23527 	 * restriction.)
23528 	 */
23529 	h_target = duk_require_hobject_promote_mask(thr, -2, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
23530 	DUK_ASSERT(h_target != NULL);
23531 	if (DUK_HOBJECT_IS_PROXY(h_target)) {
23532 		goto fail_args;
23533 	}
23534 
23535 	/* Reject a proxy object as the handler because it would cause
23536 	 * potentially unbounded recursion.  (ES2015 has no such
23537 	 * restriction.)
23538 	 *
23539 	 * There's little practical reason to use a lightfunc or a plain
23540 	 * buffer as the handler table: one could only provide traps via
23541 	 * their prototype objects (Function.prototype and ArrayBuffer.prototype).
23542 	 * Even so, as lightfuncs and plain buffers mimic their object
23543 	 * counterparts, they're promoted and accepted here.
23544 	 */
23545 	h_handler = duk_require_hobject_promote_mask(thr, -1, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
23546 	DUK_ASSERT(h_handler != NULL);
23547 	if (DUK_HOBJECT_IS_PROXY(h_handler)) {
23548 		goto fail_args;
23549 	}
23550 
23551 	/* XXX: Proxy object currently has no prototype, so ToPrimitive()
23552 	 * coercion fails which is a bit confusing.
23553 	 */
23554 
23555 	/* CALLABLE and CONSTRUCTABLE flags are copied from the (initial)
23556 	 * target, see ES2015 Sections 9.5.15 and 9.5.13.
23557 	 */
23558 	flags = DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h_target) &
23559 	        (DUK_HOBJECT_FLAG_CALLABLE | DUK_HOBJECT_FLAG_CONSTRUCTABLE);
23560 	flags |= DUK_HOBJECT_FLAG_EXTENSIBLE |
23561 	         DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ;
23562 	if (flags & DUK_HOBJECT_FLAG_CALLABLE) {
23563 		flags |= DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION) |
23564 		         DUK_HOBJECT_FLAG_SPECIAL_CALL;
23565 	} else {
23566 		flags |= DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT);
23567 	}
23568 
23569 	h_proxy = duk_hproxy_alloc(thr, flags);
23570 	DUK_ASSERT(h_proxy != NULL);
23571 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_proxy) == NULL);
23572 
23573 	/* Initialize Proxy target and handler references; avoid INCREF
23574 	 * by stealing the value stack refcounts via direct value stack
23575 	 * manipulation.  INCREF is needed for the Proxy itself however.
23576 	 */
23577 	DUK_ASSERT(h_target != NULL);
23578 	h_proxy->target = h_target;
23579 	DUK_ASSERT(h_handler != NULL);
23580 	h_proxy->handler = h_handler;
23581 	DUK_HPROXY_ASSERT_VALID(h_proxy);
23582 
23583 	DUK_ASSERT(duk_get_hobject(thr, -2) == h_target);
23584 	DUK_ASSERT(duk_get_hobject(thr, -1) == h_handler);
23585 	tv_slot = thr->valstack_top - 2;
23586 	DUK_ASSERT(tv_slot >= thr->valstack_bottom);
23587 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) h_proxy);
23588 	DUK_HOBJECT_INCREF(thr, (duk_hobject *) h_proxy);
23589 	tv_slot++;
23590 	DUK_TVAL_SET_UNDEFINED(tv_slot);  /* [ ... target handler ] -> [ ... proxy undefined ] */
23591 	thr->valstack_top = tv_slot;      /* -> [ ... proxy ] */
23592 
23593 	DUK_DD(DUK_DDPRINT("created Proxy: %!iT", duk_get_tval(thr, -1)));
23594 
23595 	return (duk_idx_t) (thr->valstack_top - thr->valstack_bottom - 1);
23596 
23597  fail_args:
23598 	DUK_ERROR_TYPE_INVALID_ARGS(thr);
23599 	DUK_WO_NORETURN(return 0;);
23600 }
23601 #else  /* DUK_USE_ES6_PROXY */
duk_push_proxy(duk_hthread * thr,duk_uint_t proxy_flags)23602 DUK_EXTERNAL duk_idx_t duk_push_proxy(duk_hthread *thr, duk_uint_t proxy_flags) {
23603 	DUK_ASSERT_API_ENTRY(thr);
23604 	DUK_UNREF(proxy_flags);
23605 	DUK_ERROR_UNSUPPORTED(thr);
23606 	DUK_WO_NORETURN(return 0;);
23607 }
23608 #endif  /* DUK_USE_ES6_PROXY */
23609 
23610 #if defined(DUK_USE_ASSERTIONS)
duk__validate_push_heapptr(duk_hthread * thr,void * ptr)23611 DUK_LOCAL void duk__validate_push_heapptr(duk_hthread *thr, void *ptr) {
23612 	duk_heaphdr *h;
23613 	duk_heaphdr *curr;
23614 	duk_bool_t found = 0;
23615 
23616 	h = (duk_heaphdr *) ptr;
23617 	if (h == NULL) {
23618 		/* Allowed. */
23619 		return;
23620 	}
23621 	DUK_ASSERT(h != NULL);
23622 	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
23623 
23624 	/* One particular problem case is where an object has been
23625 	 * queued for finalization but the finalizer hasn't yet been
23626 	 * executed.
23627 	 *
23628 	 * Corner case: we're running in a finalizer for object X, and
23629 	 * user code calls duk_push_heapptr() for X itself.  In this
23630 	 * case X will be in finalize_list, and we can detect the case
23631 	 * by seeing that X's FINALIZED flag is set (which is done before
23632 	 * the finalizer starts executing).
23633 	 */
23634 #if defined(DUK_USE_FINALIZER_SUPPORT)
23635 	for (curr = thr->heap->finalize_list;
23636 	     curr != NULL;
23637 	     curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
23638 		/* FINALIZABLE is set for all objects on finalize_list
23639 		 * except for an object being finalized right now.  So
23640 		 * can't assert here.
23641 		 */
23642 #if 0
23643 		DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZABLE(curr));
23644 #endif
23645 
23646 		if (curr == h) {
23647 			if (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h)) {
23648 				/* Object is currently being finalized. */
23649 				DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
23650 				found = 1;
23651 			} else {
23652 				/* Not being finalized but on finalize_list,
23653 				 * allowed since Duktape 2.1.
23654 				 */
23655 				DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
23656 				found = 1;
23657 			}
23658 		}
23659 	}
23660 #endif  /* DUK_USE_FINALIZER_SUPPORT */
23661 
23662 #if defined(DUK_USE_REFERENCE_COUNTING)
23663 	/* Because refzero_list is now processed to completion inline with
23664 	 * no side effects, it's always empty here.
23665 	 */
23666 	DUK_ASSERT(thr->heap->refzero_list == NULL);
23667 #endif
23668 
23669 	/* If not present in finalize_list (or refzero_list), it
23670 	 * must be either in heap_allocated or the string table.
23671 	 */
23672 	if (DUK_HEAPHDR_IS_STRING(h)) {
23673 		duk_uint32_t i;
23674 		duk_hstring *str;
23675 		duk_heap *heap = thr->heap;
23676 
23677 		DUK_ASSERT(found == 0);
23678 		for (i = 0; i < heap->st_size; i++) {
23679 #if defined(DUK_USE_STRTAB_PTRCOMP)
23680 			str = DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, heap->strtable16[i]);
23681 #else
23682 			str = heap->strtable[i];
23683 #endif
23684 			while (str != NULL) {
23685 				if (str == (duk_hstring *) h) {
23686 					DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
23687 					found = 1;
23688 					break;
23689 				}
23690 				str = str->hdr.h_next;
23691 			}
23692 		}
23693 		DUK_ASSERT(found != 0);
23694 	} else {
23695 		for (curr = thr->heap->heap_allocated;
23696 		     curr != NULL;
23697 		     curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
23698 			if (curr == h) {
23699 				DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
23700 				found = 1;
23701 			}
23702 		}
23703 		DUK_ASSERT(found != 0);
23704 	}
23705 }
23706 #endif  /* DUK_USE_ASSERTIONS */
23707 
duk_push_heapptr(duk_hthread * thr,void * ptr)23708 DUK_EXTERNAL duk_idx_t duk_push_heapptr(duk_hthread *thr, void *ptr) {
23709 	duk_idx_t ret;
23710 	duk_tval *tv;
23711 
23712 	DUK_ASSERT_API_ENTRY(thr);
23713 
23714 	/* Reviving an object using a heap pointer is a dangerous API
23715 	 * operation: if the application doesn't guarantee that the
23716 	 * pointer target is always reachable, difficult-to-diagnose
23717 	 * problems may ensue.  Try to validate the 'ptr' argument to
23718 	 * the extent possible.
23719 	 */
23720 
23721 #if defined(DUK_USE_ASSERTIONS)
23722 	duk__validate_push_heapptr(thr, ptr);
23723 #endif
23724 
23725 	DUK__CHECK_SPACE();
23726 
23727 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
23728 	tv = thr->valstack_top++;
23729 
23730 	if (ptr == NULL) {
23731 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
23732 		return ret;
23733 	}
23734 
23735 	DUK_HEAPHDR_ASSERT_VALID((duk_heaphdr *) ptr);
23736 
23737 	/* If the argument is on finalize_list it has technically been
23738 	 * unreachable before duk_push_heapptr() but it's still safe to
23739 	 * push it.  Starting from Duktape 2.1 allow application code to
23740 	 * do so.  There are two main cases:
23741 	 *
23742 	 *   (1) The object is on the finalize_list and we're called by
23743 	 *       the finalizer for the object being finalized.  In this
23744 	 *       case do nothing: finalize_list handling will deal with
23745 	 *       the object queueing.  This is detected by the object not
23746 	 *       having a FINALIZABLE flag despite being on the finalize_list;
23747 	 *       the flag is cleared for the object being finalized only.
23748 	 *
23749 	 *   (2) The object is on the finalize_list but is not currently
23750 	 *       being processed.  In this case the object can be queued
23751 	 *       back to heap_allocated with a few flags cleared, in effect
23752 	 *       cancelling the finalizer.
23753 	 */
23754 	if (DUK_UNLIKELY(DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) ptr))) {
23755 		duk_heaphdr *curr;
23756 
23757 		DUK_D(DUK_DPRINT("duk_push_heapptr() with a pointer on finalize_list, autorescue"));
23758 
23759 		curr = (duk_heaphdr *) ptr;
23760 		DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);
23761 
23762 		/* Because FINALIZED is set prior to finalizer call, it will
23763 		 * be set for the object being currently finalized, but not
23764 		 * for other objects on finalize_list.
23765 		 */
23766 		DUK_HEAPHDR_CLEAR_FINALIZED(curr);
23767 
23768 		/* Dequeue object from finalize_list and queue it back to
23769 		 * heap_allocated.
23770 		 */
23771 #if defined(DUK_USE_REFERENCE_COUNTING)
23772 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) >= 1);  /* Preincremented on finalize_list insert. */
23773 		DUK_HEAPHDR_PREDEC_REFCOUNT(curr);
23774 #endif
23775 		DUK_HEAP_REMOVE_FROM_FINALIZE_LIST(thr->heap, curr);
23776 		DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(thr->heap, curr);
23777 
23778 		/* Continue with the rest. */
23779 	}
23780 
23781 	switch (DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) ptr)) {
23782 	case DUK_HTYPE_STRING:
23783 		DUK_TVAL_SET_STRING(tv, (duk_hstring *) ptr);
23784 		break;
23785 	case DUK_HTYPE_OBJECT:
23786 		DUK_TVAL_SET_OBJECT(tv, (duk_hobject *) ptr);
23787 		break;
23788 	default:
23789 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) ptr) == DUK_HTYPE_BUFFER);
23790 		DUK_TVAL_SET_BUFFER(tv, (duk_hbuffer *) ptr);
23791 		break;
23792 	}
23793 
23794 	DUK_HEAPHDR_INCREF(thr, (duk_heaphdr *) ptr);
23795 
23796 	return ret;
23797 }
23798 
23799 /* Push object with no prototype, i.e. a "bare" object. */
duk_push_bare_object(duk_hthread * thr)23800 DUK_EXTERNAL duk_idx_t duk_push_bare_object(duk_hthread *thr) {
23801 	DUK_ASSERT_API_ENTRY(thr);
23802 
23803 	(void) duk_push_object_helper(thr,
23804 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
23805 	                              DUK_HOBJECT_FLAG_FASTREFS |
23806 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
23807 	                              -1);  /* no prototype */
23808 	return duk_get_top_index_unsafe(thr);
23809 }
23810 
duk_push_hstring(duk_hthread * thr,duk_hstring * h)23811 DUK_INTERNAL void duk_push_hstring(duk_hthread *thr, duk_hstring *h) {
23812 	duk_tval tv;
23813 
23814 	DUK_ASSERT_API_ENTRY(thr);
23815 	DUK_ASSERT(h != NULL);
23816 
23817 	DUK_TVAL_SET_STRING(&tv, h);
23818 	duk_push_tval(thr, &tv);
23819 }
23820 
duk_push_hstring_stridx(duk_hthread * thr,duk_small_uint_t stridx)23821 DUK_INTERNAL void duk_push_hstring_stridx(duk_hthread *thr, duk_small_uint_t stridx) {
23822 	DUK_ASSERT_API_ENTRY(thr);
23823 	DUK_ASSERT_STRIDX_VALID(stridx);
23824 	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
23825 }
23826 
duk_push_hstring_empty(duk_hthread * thr)23827 DUK_INTERNAL void duk_push_hstring_empty(duk_hthread *thr) {
23828 	DUK_ASSERT_API_ENTRY(thr);
23829 	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, DUK_STRIDX_EMPTY_STRING));
23830 }
23831 
duk_push_hobject(duk_hthread * thr,duk_hobject * h)23832 DUK_INTERNAL void duk_push_hobject(duk_hthread *thr, duk_hobject *h) {
23833 	duk_tval tv;
23834 
23835 	DUK_ASSERT_API_ENTRY(thr);
23836 	DUK_ASSERT(h != NULL);
23837 
23838 	DUK_TVAL_SET_OBJECT(&tv, h);
23839 	duk_push_tval(thr, &tv);
23840 }
23841 
duk_push_hbuffer(duk_hthread * thr,duk_hbuffer * h)23842 DUK_INTERNAL void duk_push_hbuffer(duk_hthread *thr, duk_hbuffer *h) {
23843 	duk_tval tv;
23844 
23845 	DUK_ASSERT_API_ENTRY(thr);
23846 	DUK_ASSERT(h != NULL);
23847 
23848 	DUK_TVAL_SET_BUFFER(&tv, h);
23849 	duk_push_tval(thr, &tv);
23850 }
23851 
duk_push_hobject_bidx(duk_hthread * thr,duk_small_int_t builtin_idx)23852 DUK_INTERNAL void duk_push_hobject_bidx(duk_hthread *thr, duk_small_int_t builtin_idx) {
23853 	DUK_ASSERT_API_ENTRY(thr);
23854 	DUK_ASSERT(builtin_idx >= 0 && builtin_idx < DUK_NUM_BUILTINS);
23855 	DUK_ASSERT(thr->builtins[builtin_idx] != NULL);
23856 
23857 	duk_push_hobject(thr, thr->builtins[builtin_idx]);
23858 }
23859 
23860 /*
23861  *  Poppers
23862  */
23863 
duk__pop_n_unsafe_raw(duk_hthread * thr,duk_idx_t count)23864 DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_n_unsafe_raw(duk_hthread *thr, duk_idx_t count) {
23865 	duk_tval *tv;
23866 #if defined(DUK_USE_REFERENCE_COUNTING)
23867 	duk_tval *tv_end;
23868 #endif
23869 
23870 	DUK_CTX_ASSERT_VALID(thr);
23871 	DUK_ASSERT(count >= 0);
23872 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) count);
23873 
23874 #if defined(DUK_USE_REFERENCE_COUNTING)
23875 	tv = thr->valstack_top;
23876 	tv_end = tv - count;
23877 	while (tv != tv_end) {
23878 		tv--;
23879 		DUK_ASSERT(tv >= thr->valstack_bottom);
23880 		DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);
23881 	}
23882 	thr->valstack_top = tv;
23883 	DUK_REFZERO_CHECK_FAST(thr);
23884 #else
23885 	tv = thr->valstack_top;
23886 	while (count > 0) {
23887 		count--;
23888 		tv--;
23889 		DUK_ASSERT(tv >= thr->valstack_bottom);
23890 		DUK_TVAL_SET_UNDEFINED(tv);
23891 	}
23892 	thr->valstack_top = tv;
23893 #endif
23894 
23895 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23896 }
23897 
duk_pop_n(duk_hthread * thr,duk_idx_t count)23898 DUK_EXTERNAL void duk_pop_n(duk_hthread *thr, duk_idx_t count) {
23899 	DUK_ASSERT_API_ENTRY(thr);
23900 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23901 
23902 	if (DUK_UNLIKELY((duk_uidx_t) (thr->valstack_top - thr->valstack_bottom) < (duk_uidx_t) count)) {
23903 		DUK_ERROR_RANGE_INVALID_COUNT(thr);
23904 		DUK_WO_NORETURN(return;);
23905 	}
23906 	DUK_ASSERT(count >= 0);
23907 
23908 	duk__pop_n_unsafe_raw(thr, count);
23909 }
23910 
23911 #if defined(DUK_USE_PREFER_SIZE)
duk_pop_n_unsafe(duk_hthread * thr,duk_idx_t count)23912 DUK_INTERNAL void duk_pop_n_unsafe(duk_hthread *thr, duk_idx_t count) {
23913 	DUK_ASSERT_API_ENTRY(thr);
23914 	duk_pop_n(thr, count);
23915 }
23916 #else  /* DUK_USE_PREFER_SIZE */
duk_pop_n_unsafe(duk_hthread * thr,duk_idx_t count)23917 DUK_INTERNAL void duk_pop_n_unsafe(duk_hthread *thr, duk_idx_t count) {
23918 	DUK_ASSERT_API_ENTRY(thr);
23919 	duk__pop_n_unsafe_raw(thr, count);
23920 }
23921 #endif  /* DUK_USE_PREFER_SIZE */
23922 
23923 /* Pop N elements without DECREF (in effect "stealing" any actual refcounts). */
23924 #if defined(DUK_USE_REFERENCE_COUNTING)
duk_pop_n_nodecref_unsafe(duk_hthread * thr,duk_idx_t count)23925 DUK_INTERNAL void duk_pop_n_nodecref_unsafe(duk_hthread *thr, duk_idx_t count) {
23926 	duk_tval *tv;
23927 
23928 	DUK_ASSERT_API_ENTRY(thr);
23929 	DUK_ASSERT(count >= 0);
23930 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23931 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) count);
23932 
23933 	tv = thr->valstack_top;
23934 	while (count > 0) {
23935 		count--;
23936 		tv--;
23937 		DUK_ASSERT(tv >= thr->valstack_bottom);
23938 		DUK_TVAL_SET_UNDEFINED(tv);
23939 	}
23940 	thr->valstack_top = tv;
23941 
23942 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23943 }
23944 #else  /* DUK_USE_REFERENCE_COUNTING */
duk_pop_n_nodecref_unsafe(duk_hthread * thr,duk_idx_t count)23945 DUK_INTERNAL void duk_pop_n_nodecref_unsafe(duk_hthread *thr, duk_idx_t count) {
23946 	DUK_ASSERT_API_ENTRY(thr);
23947 	duk_pop_n_unsafe(thr, count);
23948 }
23949 #endif  /* DUK_USE_REFERENCE_COUNTING */
23950 
23951 /* Popping one element is called so often that when footprint is not an issue,
23952  * compile a specialized function for it.
23953  */
23954 #if defined(DUK_USE_PREFER_SIZE)
duk_pop(duk_hthread * thr)23955 DUK_EXTERNAL void duk_pop(duk_hthread *thr) {
23956 	DUK_ASSERT_API_ENTRY(thr);
23957 	duk_pop_n(thr, 1);
23958 }
duk_pop_unsafe(duk_hthread * thr)23959 DUK_INTERNAL void duk_pop_unsafe(duk_hthread *thr) {
23960 	DUK_ASSERT_API_ENTRY(thr);
23961 	duk_pop_n_unsafe(thr, 1);
23962 }
duk_pop_nodecref_unsafe(duk_hthread * thr)23963 DUK_INTERNAL void duk_pop_nodecref_unsafe(duk_hthread *thr) {
23964 	DUK_ASSERT_API_ENTRY(thr);
23965 	duk_pop_n_nodecref_unsafe(thr, 1);
23966 }
23967 #else  /* DUK_USE_PREFER_SIZE */
duk__pop_unsafe_raw(duk_hthread * thr)23968 DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_unsafe_raw(duk_hthread *thr) {
23969 	duk_tval *tv;
23970 
23971 	DUK_CTX_ASSERT_VALID(thr);
23972 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
23973 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23974 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 1);
23975 
23976 	tv = --thr->valstack_top;
23977 	DUK_ASSERT(tv >= thr->valstack_bottom);
23978 #if defined(DUK_USE_REFERENCE_COUNTING)
23979 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
23980 #else
23981 	DUK_TVAL_SET_UNDEFINED(tv);
23982 #endif
23983 
23984 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23985 }
duk_pop(duk_hthread * thr)23986 DUK_EXTERNAL void duk_pop(duk_hthread *thr) {
23987 	DUK_ASSERT_API_ENTRY(thr);
23988 
23989 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23990 	if (DUK_UNLIKELY(thr->valstack_top == thr->valstack_bottom)) {
23991 		DUK_ERROR_RANGE_INVALID_COUNT(thr);
23992 		DUK_WO_NORETURN(return;);
23993 	}
23994 
23995 	duk__pop_unsafe_raw(thr);
23996 }
duk_pop_unsafe(duk_hthread * thr)23997 DUK_INTERNAL void duk_pop_unsafe(duk_hthread *thr) {
23998 	DUK_ASSERT_API_ENTRY(thr);
23999 	duk__pop_unsafe_raw(thr);
24000 }
duk_pop_nodecref_unsafe(duk_hthread * thr)24001 DUK_INTERNAL void duk_pop_nodecref_unsafe(duk_hthread *thr) {
24002 	duk_tval *tv;
24003 
24004 	DUK_ASSERT_API_ENTRY(thr);
24005 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
24006 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
24007 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 1);
24008 
24009 	tv = --thr->valstack_top;
24010 	DUK_ASSERT(tv >= thr->valstack_bottom);
24011 	DUK_TVAL_SET_UNDEFINED(tv);
24012 
24013 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
24014 }
24015 #endif  /* !DUK_USE_PREFER_SIZE */
24016 
24017 #if defined(DUK_USE_PREFER_SIZE)
duk_pop_undefined(duk_hthread * thr)24018 DUK_INTERNAL void duk_pop_undefined(duk_hthread *thr) {
24019 	DUK_ASSERT_API_ENTRY(thr);
24020 	duk_pop_nodecref_unsafe(thr);
24021 }
24022 #else  /* DUK_USE_PREFER_SIZE */
duk_pop_undefined(duk_hthread * thr)24023 DUK_INTERNAL void duk_pop_undefined(duk_hthread *thr) {
24024 	DUK_ASSERT_API_ENTRY(thr);
24025 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
24026 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
24027 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 1);
24028 
24029 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 1));
24030 	thr->valstack_top--;
24031 
24032 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
24033 }
24034 #endif  /* !DUK_USE_PREFER_SIZE */
24035 
24036 #if defined(DUK_USE_PREFER_SIZE)
duk_pop_2(duk_hthread * thr)24037 DUK_EXTERNAL void duk_pop_2(duk_hthread *thr) {
24038 	DUK_ASSERT_API_ENTRY(thr);
24039 	duk_pop_n(thr, 2);
24040 }
duk_pop_2_unsafe(duk_hthread * thr)24041 DUK_INTERNAL void duk_pop_2_unsafe(duk_hthread *thr) {
24042 	DUK_ASSERT_API_ENTRY(thr);
24043 	duk_pop_n_unsafe(thr, 2);
24044 }
duk_pop_2_nodecref_unsafe(duk_hthread * thr)24045 DUK_INTERNAL void duk_pop_2_nodecref_unsafe(duk_hthread *thr) {
24046 	DUK_ASSERT_API_ENTRY(thr);
24047 	duk_pop_n_nodecref_unsafe(thr, 2);
24048 }
24049 #else
duk__pop_2_unsafe_raw(duk_hthread * thr)24050 DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_2_unsafe_raw(duk_hthread *thr) {
24051 	duk_tval *tv;
24052 
24053 	DUK_CTX_ASSERT_VALID(thr);
24054 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
24055 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
24056 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 2);
24057 
24058 	tv = --thr->valstack_top;
24059 	DUK_ASSERT(tv >= thr->valstack_bottom);
24060 #if defined(DUK_USE_REFERENCE_COUNTING)
24061 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
24062 #else
24063 	DUK_TVAL_SET_UNDEFINED(tv);
24064 #endif
24065 	tv = --thr->valstack_top;
24066 	DUK_ASSERT(tv >= thr->valstack_bottom);
24067 #if defined(DUK_USE_REFERENCE_COUNTING)
24068 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
24069 #else
24070 	DUK_TVAL_SET_UNDEFINED(tv);
24071 #endif
24072 
24073 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
24074 }
duk_pop_2(duk_hthread * thr)24075 DUK_EXTERNAL void duk_pop_2(duk_hthread *thr) {
24076 	DUK_ASSERT_API_ENTRY(thr);
24077 
24078 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
24079 	if (DUK_UNLIKELY(thr->valstack_top - 2 < thr->valstack_bottom)) {
24080 		DUK_ERROR_RANGE_INVALID_COUNT(thr);
24081 		DUK_WO_NORETURN(return;);
24082 	}
24083 
24084 	duk__pop_2_unsafe_raw(thr);
24085 }
duk_pop_2_unsafe(duk_hthread * thr)24086 DUK_INTERNAL void duk_pop_2_unsafe(duk_hthread *thr) {
24087 	DUK_ASSERT_API_ENTRY(thr);
24088 	duk__pop_2_unsafe_raw(thr);
24089 }
duk_pop_2_nodecref_unsafe(duk_hthread * thr)24090 DUK_INTERNAL void duk_pop_2_nodecref_unsafe(duk_hthread *thr) {
24091 	DUK_ASSERT_API_ENTRY(thr);
24092 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
24093 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
24094 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 2);
24095 
24096 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 1));
24097 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 2));
24098 	thr->valstack_top -= 2;
24099 
24100 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
24101 }
24102 #endif  /* !DUK_USE_PREFER_SIZE */
24103 
duk_pop_3(duk_hthread * thr)24104 DUK_EXTERNAL void duk_pop_3(duk_hthread *thr) {
24105 	DUK_ASSERT_API_ENTRY(thr);
24106 	duk_pop_n(thr, 3);
24107 }
24108 
duk_pop_3_unsafe(duk_hthread * thr)24109 DUK_INTERNAL void duk_pop_3_unsafe(duk_hthread *thr) {
24110 	DUK_ASSERT_API_ENTRY(thr);
24111 	duk_pop_n_unsafe(thr, 3);
24112 }
24113 
duk_pop_3_nodecref_unsafe(duk_hthread * thr)24114 DUK_INTERNAL void duk_pop_3_nodecref_unsafe(duk_hthread *thr) {
24115 	DUK_ASSERT_API_ENTRY(thr);
24116 	duk_pop_n_nodecref_unsafe(thr, 3);
24117 }
24118 
24119 /*
24120  *  Pack and unpack (pack value stack entries into an array and vice versa)
24121  */
24122 
24123 /* XXX: pack index range? array index offset? */
24124 /* XXX: need ability to pack into a bare array? */
duk_pack(duk_hthread * thr,duk_idx_t count)24125 DUK_INTERNAL void duk_pack(duk_hthread *thr, duk_idx_t count) {
24126 	duk_tval *tv_src;
24127 	duk_tval *tv_dst;
24128 	duk_tval *tv_curr;
24129 	duk_tval *tv_limit;
24130 	duk_idx_t top;
24131 
24132 	DUK_ASSERT_API_ENTRY(thr);
24133 
24134 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
24135 	top = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
24136 	DUK_ASSERT(top >= 0);
24137 	if (DUK_UNLIKELY((duk_uidx_t) count > (duk_uidx_t) top)) {
24138 		/* Also handles negative count. */
24139 		DUK_ERROR_RANGE_INVALID_COUNT(thr);
24140 		DUK_WO_NORETURN(return;);
24141 	}
24142 	DUK_ASSERT(count >= 0);
24143 
24144 	/* Wrapping is controlled by the check above: value stack top can be
24145 	 * at most DUK_USE_VALSTACK_LIMIT which is low enough so that
24146 	 * multiplying with sizeof(duk_tval) won't wrap.
24147 	 */
24148 	DUK_ASSERT(count >= 0 && count <= (duk_idx_t) DUK_USE_VALSTACK_LIMIT);
24149 	DUK_ASSERT((duk_size_t) count <= DUK_SIZE_MAX / sizeof(duk_tval));  /* no wrapping */
24150 
24151 	tv_dst = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) count);  /* XXX: uninitialized would be OK */
24152 	DUK_ASSERT(count == 0 || tv_dst != NULL);
24153 	DUK_ASSERT(!duk_is_bare_object(thr, -1));
24154 
24155 	/* Copy value stack values directly to the array part without
24156 	 * any refcount updates: net refcount changes are zero.
24157 	 */
24158 	tv_src = thr->valstack_top - count - 1;
24159 	duk_memcpy_unsafe((void *) tv_dst, (const void *) tv_src, (size_t) count * sizeof(duk_tval));
24160 
24161 	/* Overwrite result array to final value stack location and wipe
24162 	 * the rest; no refcount operations needed.
24163 	 */
24164 
24165 	tv_dst = tv_src;  /* when count == 0, same as tv_src (OK) */
24166 	tv_src = thr->valstack_top - 1;
24167 	DUK_TVAL_SET_TVAL(tv_dst, tv_src);
24168 
24169 	/* XXX: internal helper to wipe a value stack segment? */
24170 	tv_curr = tv_dst + 1;
24171 	tv_limit = thr->valstack_top;
24172 	while (tv_curr != tv_limit) {
24173 		/* Wipe policy: keep as 'undefined'. */
24174 		DUK_TVAL_SET_UNDEFINED(tv_curr);
24175 		tv_curr++;
24176 	}
24177 	thr->valstack_top = tv_dst + 1;
24178 }
24179 
duk_unpack_array_like(duk_hthread * thr,duk_idx_t idx)24180 DUK_INTERNAL duk_idx_t duk_unpack_array_like(duk_hthread *thr, duk_idx_t idx) {
24181 	duk_tval *tv;
24182 
24183 	DUK_ASSERT_API_ENTRY(thr);
24184 
24185 	tv = duk_require_tval(thr, idx);
24186 	if (DUK_LIKELY(DUK_TVAL_IS_OBJECT(tv))) {
24187 		duk_hobject *h;
24188 		duk_uint32_t len;
24189 		duk_uint32_t i;
24190 
24191 		h = DUK_TVAL_GET_OBJECT(tv);
24192 		DUK_ASSERT(h != NULL);
24193 		DUK_UNREF(h);
24194 
24195 #if defined(DUK_USE_ARRAY_FASTPATH)  /* close enough */
24196 		if (DUK_LIKELY(DUK_HOBJECT_IS_ARRAY(h) &&
24197 		               ((duk_harray *) h)->length <= DUK_HOBJECT_GET_ASIZE(h))) {
24198 			duk_harray *h_arr;
24199 			duk_tval *tv_src;
24200 			duk_tval *tv_dst;
24201 
24202 			h_arr = (duk_harray *) h;
24203 			len = h_arr->length;
24204 			if (DUK_UNLIKELY(len >= 0x80000000UL)) {
24205 				goto fail_over_2g;
24206 			}
24207 			duk_require_stack(thr, (duk_idx_t) len);
24208 
24209 			/* The potential allocation in duk_require_stack() may
24210 			 * run a finalizer which modifies the argArray so that
24211 			 * e.g. becomes sparse.  So, we need to recheck that the
24212 			 * array didn't change size and that there's still a
24213 			 * valid backing array part.
24214 			 *
24215 			 * XXX: alternatively, could prevent finalizers for the
24216 			 * duration.
24217 			 */
24218 			if (DUK_UNLIKELY(len != h_arr->length ||
24219 			                 h_arr->length > DUK_HOBJECT_GET_ASIZE((duk_hobject *) h_arr))) {
24220 				goto skip_fast;
24221 			}
24222 
24223 			/* Main fast path: arguments array is almost always
24224 			 * an actual array (though it might also be an arguments
24225 			 * object).
24226 			 */
24227 
24228 			DUK_DDD(DUK_DDDPRINT("fast path for %ld elements", (long) h_arr->length));
24229 			tv_src = DUK_HOBJECT_A_GET_BASE(thr->heap, h);
24230 			tv_dst = thr->valstack_top;
24231 			while (len-- > 0) {
24232 				DUK_ASSERT(tv_dst < thr->valstack_end);
24233 				if (DUK_UNLIKELY(DUK_TVAL_IS_UNUSED(tv_src))) {
24234 					/* Gaps are very unlikely.  Skip over them,
24235 					 * without an ancestor lookup (technically
24236 					 * not compliant).
24237 					 */
24238 					DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv_dst));  /* valstack policy */
24239 				} else {
24240 					DUK_TVAL_SET_TVAL(tv_dst, tv_src);
24241 					DUK_TVAL_INCREF(thr, tv_dst);
24242 				}
24243 				tv_src++;
24244 				tv_dst++;
24245 			}
24246 			DUK_ASSERT(tv_dst <= thr->valstack_end);
24247 			thr->valstack_top = tv_dst;
24248 			return (duk_idx_t) h_arr->length;
24249 		}
24250 	 skip_fast:
24251 #endif  /* DUK_USE_ARRAY_FASTPATH */
24252 
24253 		/* Slow path: actual lookups.  The initial 'length' lookup
24254 		 * decides the output length, regardless of side effects that
24255 		 * may resize or change the argArray while we read the
24256 		 * indices.
24257 		 */
24258 		idx = duk_normalize_index(thr, idx);
24259 		duk_get_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);
24260 		len = duk_to_uint32(thr, -1);  /* ToUint32() coercion required */
24261 		if (DUK_UNLIKELY(len >= 0x80000000UL)) {
24262 			goto fail_over_2g;
24263 		}
24264 		duk_pop_unsafe(thr);
24265 		DUK_DDD(DUK_DDDPRINT("slow path for %ld elements", (long) len));
24266 
24267 		duk_require_stack(thr, (duk_idx_t) len);
24268 		for (i = 0; i < len; i++) {
24269 			duk_get_prop_index(thr, idx, (duk_uarridx_t) i);
24270 		}
24271 		return (duk_idx_t) len;
24272 	} else if (DUK_TVAL_IS_UNDEFINED(tv) || DUK_TVAL_IS_NULL(tv)) {
24273 		return 0;
24274 	}
24275 
24276 	DUK_ERROR_TYPE_INVALID_ARGS(thr);
24277 	DUK_WO_NORETURN(return 0;);
24278 
24279  fail_over_2g:
24280 	DUK_ERROR_RANGE_INVALID_LENGTH(thr);
24281 	DUK_WO_NORETURN(return 0;);
24282 }
24283 
24284 /*
24285  *  Error throwing
24286  */
24287 
24288 #if defined(DUK_USE_GCC_PRAGMAS)
24289 #pragma GCC diagnostic push
24290 #pragma GCC diagnostic ignored "-Wsuggest-attribute=noreturn"
24291 #elif defined(DUK_USE_CLANG_PRAGMAS)
24292 #pragma clang diagnostic push
24293 #endif
24294 
duk_throw_raw(duk_hthread * thr)24295 DUK_EXTERNAL void duk_throw_raw(duk_hthread *thr) {
24296 	duk_tval *tv_val;
24297 
24298 	DUK_ASSERT_API_ENTRY(thr);
24299 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
24300 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
24301 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
24302 
24303 	if (DUK_UNLIKELY(thr->valstack_top == thr->valstack_bottom)) {
24304 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
24305 		DUK_WO_NORETURN(return;);
24306 	}
24307 
24308 	/* Errors are augmented when they are created, not when they are
24309 	 * thrown or re-thrown.  The current error handler, however, runs
24310 	 * just before an error is thrown.
24311 	 */
24312 
24313 	/* Sync so that augmentation sees up-to-date activations, NULL
24314 	 * thr->ptr_curr_pc so that it's not used if side effects occur
24315 	 * in augmentation or longjmp handling.
24316 	 */
24317 	duk_hthread_sync_and_null_currpc(thr);
24318 
24319 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
24320 	DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (before throw augment)", (duk_tval *) duk_get_tval(thr, -1)));
24321 	duk_err_augment_error_throw(thr);
24322 #endif
24323 	DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (after throw augment)", (duk_tval *) duk_get_tval(thr, -1)));
24324 
24325 	tv_val = DUK_GET_TVAL_NEGIDX(thr, -1);
24326 	duk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, tv_val);
24327 #if defined(DUK_USE_DEBUGGER_SUPPORT)
24328 	duk_err_check_debugger_integration(thr);
24329 #endif
24330 
24331 	/* thr->heap->lj.jmpbuf_ptr is checked by duk_err_longjmp() so we don't
24332 	 * need to check that here.  If the value is NULL, a fatal error occurs
24333 	 * because we can't return.
24334 	 */
24335 
24336 	duk_err_longjmp(thr);
24337 	DUK_UNREACHABLE();
24338 }
24339 
duk_fatal_raw(duk_hthread * thr,const char * err_msg)24340 DUK_EXTERNAL void duk_fatal_raw(duk_hthread *thr, const char *err_msg) {
24341 	DUK_ASSERT_API_ENTRY(thr);
24342 	DUK_ASSERT(thr != NULL);
24343 	DUK_ASSERT(thr->heap != NULL);
24344 	DUK_ASSERT(thr->heap->fatal_func != NULL);
24345 
24346 	DUK_D(DUK_DPRINT("fatal error occurred: %s", err_msg ? err_msg : "NULL"));
24347 
24348 	/* fatal_func should be noreturn, but noreturn declarations on function
24349 	 * pointers has a very spotty support apparently so it's not currently
24350 	 * done.
24351 	 */
24352 	thr->heap->fatal_func(thr->heap->heap_udata, err_msg);
24353 
24354 	/* If the fatal handler returns, all bets are off.  It'd be nice to
24355 	 * print something here but since we don't want to depend on stdio,
24356 	 * there's no way to do so portably.
24357 	 */
24358 	DUK_D(DUK_DPRINT("fatal error handler returned, all bets are off!"));
24359 	for (;;) {
24360 		/* loop forever, don't return (function marked noreturn) */
24361 	}
24362 }
24363 
duk_error_va_raw(duk_hthread * thr,duk_errcode_t err_code,const char * filename,duk_int_t line,const char * fmt,va_list ap)24364 DUK_EXTERNAL void duk_error_va_raw(duk_hthread *thr, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap) {
24365 	DUK_ASSERT_API_ENTRY(thr);
24366 
24367 	duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
24368 	(void) duk_throw(thr);
24369 	DUK_WO_NORETURN(return;);
24370 }
24371 
duk_error_raw(duk_hthread * thr,duk_errcode_t err_code,const char * filename,duk_int_t line,const char * fmt,...)24372 DUK_EXTERNAL void duk_error_raw(duk_hthread *thr, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) {
24373 	va_list ap;
24374 
24375 	DUK_ASSERT_API_ENTRY(thr);
24376 
24377 	va_start(ap, fmt);
24378 	duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
24379 	va_end(ap);
24380 	(void) duk_throw(thr);
24381 	DUK_WO_NORETURN(return;);
24382 }
24383 
24384 #if defined(DUK_USE_GCC_PRAGMAS)
24385 #pragma GCC diagnostic pop
24386 #elif defined(DUK_USE_CLANG_PRAGMAS)
24387 #pragma clang diagnostic pop
24388 #endif
24389 
24390 #if !defined(DUK_USE_VARIADIC_MACROS)
24391 DUK_NORETURN(DUK_LOCAL_DECL void duk__throw_error_from_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, va_list ap));
24392 
duk__throw_error_from_stash(duk_hthread * thr,duk_errcode_t err_code,const char * fmt,va_list ap)24393 DUK_LOCAL void duk__throw_error_from_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, va_list ap) {
24394 	const char *filename;
24395 	duk_int_t line;
24396 
24397 	DUK_CTX_ASSERT_VALID(thr);
24398 
24399 	filename = duk_api_global_filename;
24400 	line = duk_api_global_line;
24401 	duk_api_global_filename = NULL;
24402 	duk_api_global_line = 0;
24403 
24404 	duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
24405 	(void) duk_throw(thr);
24406 	DUK_WO_NORETURN(return;);
24407 }
24408 
24409 #define DUK__ERROR_STASH_SHARED(code) do { \
24410 		va_list ap; \
24411 		va_start(ap, fmt); \
24412 		duk__throw_error_from_stash(thr, (code), fmt, ap); \
24413 		va_end(ap); \
24414 		DUK_WO_NORETURN(return 0;); \
24415 	} while (0)
24416 
duk_error_stash(duk_hthread * thr,duk_errcode_t err_code,const char * fmt,...)24417 DUK_EXTERNAL duk_ret_t duk_error_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, ...) {
24418 	DUK_ASSERT_API_ENTRY(thr);
24419 	DUK__ERROR_STASH_SHARED(err_code);
24420 }
duk_generic_error_stash(duk_hthread * thr,const char * fmt,...)24421 DUK_EXTERNAL duk_ret_t duk_generic_error_stash(duk_hthread *thr, const char *fmt, ...) {
24422 	DUK_ASSERT_API_ENTRY(thr);
24423 	DUK__ERROR_STASH_SHARED(DUK_ERR_ERROR);
24424 }
duk_eval_error_stash(duk_hthread * thr,const char * fmt,...)24425 DUK_EXTERNAL duk_ret_t duk_eval_error_stash(duk_hthread *thr, const char *fmt, ...) {
24426 	DUK_ASSERT_API_ENTRY(thr);
24427 	DUK__ERROR_STASH_SHARED(DUK_ERR_EVAL_ERROR);
24428 }
duk_range_error_stash(duk_hthread * thr,const char * fmt,...)24429 DUK_EXTERNAL duk_ret_t duk_range_error_stash(duk_hthread *thr, const char *fmt, ...) {
24430 	DUK_ASSERT_API_ENTRY(thr);
24431 	DUK__ERROR_STASH_SHARED(DUK_ERR_RANGE_ERROR);
24432 }
duk_reference_error_stash(duk_hthread * thr,const char * fmt,...)24433 DUK_EXTERNAL duk_ret_t duk_reference_error_stash(duk_hthread *thr, const char *fmt, ...) {
24434 	DUK_ASSERT_API_ENTRY(thr);
24435 	DUK__ERROR_STASH_SHARED(DUK_ERR_REFERENCE_ERROR);
24436 }
duk_syntax_error_stash(duk_hthread * thr,const char * fmt,...)24437 DUK_EXTERNAL duk_ret_t duk_syntax_error_stash(duk_hthread *thr, const char *fmt, ...) {
24438 	DUK_ASSERT_API_ENTRY(thr);
24439 	DUK__ERROR_STASH_SHARED(DUK_ERR_SYNTAX_ERROR);
24440 }
duk_type_error_stash(duk_hthread * thr,const char * fmt,...)24441 DUK_EXTERNAL duk_ret_t duk_type_error_stash(duk_hthread *thr, const char *fmt, ...) {
24442 	DUK_ASSERT_API_ENTRY(thr);
24443 	DUK__ERROR_STASH_SHARED(DUK_ERR_TYPE_ERROR);
24444 }
duk_uri_error_stash(duk_hthread * thr,const char * fmt,...)24445 DUK_EXTERNAL duk_ret_t duk_uri_error_stash(duk_hthread *thr, const char *fmt, ...) {
24446 	DUK_ASSERT_API_ENTRY(thr);
24447 	DUK__ERROR_STASH_SHARED(DUK_ERR_URI_ERROR);
24448 }
24449 #endif  /* DUK_USE_VARIADIC_MACROS */
24450 
24451 /*
24452  *  Comparison
24453  */
24454 
duk_equals(duk_hthread * thr,duk_idx_t idx1,duk_idx_t idx2)24455 DUK_EXTERNAL duk_bool_t duk_equals(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
24456 	duk_tval *tv1, *tv2;
24457 
24458 	DUK_ASSERT_API_ENTRY(thr);
24459 
24460 	tv1 = duk_get_tval(thr, idx1);
24461 	tv2 = duk_get_tval(thr, idx2);
24462 	if ((tv1 == NULL) || (tv2 == NULL)) {
24463 		return 0;
24464 	}
24465 
24466 	/* Coercion may be needed, the helper handles that by pushing the
24467 	 * tagged values to the stack.
24468 	 */
24469 	return duk_js_equals(thr, tv1, tv2);
24470 }
24471 
duk_strict_equals(duk_hthread * thr,duk_idx_t idx1,duk_idx_t idx2)24472 DUK_EXTERNAL duk_bool_t duk_strict_equals(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
24473 	duk_tval *tv1, *tv2;
24474 
24475 	DUK_ASSERT_API_ENTRY(thr);
24476 
24477 	tv1 = duk_get_tval(thr, idx1);
24478 	tv2 = duk_get_tval(thr, idx2);
24479 	if ((tv1 == NULL) || (tv2 == NULL)) {
24480 		return 0;
24481 	}
24482 
24483 	/* No coercions or other side effects, so safe */
24484 	return duk_js_strict_equals(tv1, tv2);
24485 }
24486 
duk_samevalue(duk_hthread * thr,duk_idx_t idx1,duk_idx_t idx2)24487 DUK_EXTERNAL duk_bool_t duk_samevalue(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
24488 	duk_tval *tv1, *tv2;
24489 
24490 	DUK_ASSERT_API_ENTRY(thr);
24491 
24492 	tv1 = duk_get_tval(thr, idx1);
24493 	tv2 = duk_get_tval(thr, idx2);
24494 	if ((tv1 == NULL) || (tv2 == NULL)) {
24495 		return 0;
24496 	}
24497 
24498 	/* No coercions or other side effects, so safe */
24499 	return duk_js_samevalue(tv1, tv2);
24500 }
24501 
24502 /*
24503  *  instanceof
24504  */
24505 
duk_instanceof(duk_hthread * thr,duk_idx_t idx1,duk_idx_t idx2)24506 DUK_EXTERNAL duk_bool_t duk_instanceof(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
24507 	duk_tval *tv1, *tv2;
24508 
24509 	DUK_ASSERT_API_ENTRY(thr);
24510 
24511 	/* Index validation is strict, which differs from duk_equals().
24512 	 * The strict behavior mimics how instanceof itself works, e.g.
24513 	 * it is a TypeError if rval is not a -callable- object.  It would
24514 	 * be somewhat inconsistent if rval would be allowed to be
24515 	 * non-existent without a TypeError.
24516 	 */
24517 	tv1 = duk_require_tval(thr, idx1);
24518 	DUK_ASSERT(tv1 != NULL);
24519 	tv2 = duk_require_tval(thr, idx2);
24520 	DUK_ASSERT(tv2 != NULL);
24521 
24522 	return duk_js_instanceof(thr, tv1, tv2);
24523 }
24524 
24525 /*
24526  *  Lightfunc
24527  */
24528 
duk_push_lightfunc_name_raw(duk_hthread * thr,duk_c_function func,duk_small_uint_t lf_flags)24529 DUK_INTERNAL void duk_push_lightfunc_name_raw(duk_hthread *thr, duk_c_function func, duk_small_uint_t lf_flags) {
24530 	/* Lightfunc name, includes Duktape/C native function pointer, which
24531 	 * can often be used to locate the function from a symbol table.
24532 	 * The name also includes the 16-bit duk_tval flags field because it
24533 	 * includes the magic value.  Because a single native function often
24534 	 * provides different functionality depending on the magic value, it
24535 	 * seems reasonably to include it in the name.
24536 	 *
24537 	 * On the other hand, a complicated name increases string table
24538 	 * pressure in low memory environments (but only when function name
24539 	 * is accessed).
24540 	 */
24541 
24542 	DUK_ASSERT_API_ENTRY(thr);
24543 
24544 	duk_push_literal(thr, "light_");
24545 	duk_push_string_funcptr(thr, (duk_uint8_t *) &func, sizeof(func));
24546 	duk_push_sprintf(thr, "_%04x", (unsigned int) lf_flags);
24547 	duk_concat(thr, 3);
24548 }
24549 
duk_push_lightfunc_name(duk_hthread * thr,duk_tval * tv)24550 DUK_INTERNAL void duk_push_lightfunc_name(duk_hthread *thr, duk_tval *tv) {
24551 	duk_c_function func;
24552 	duk_small_uint_t lf_flags;
24553 
24554 	DUK_ASSERT_API_ENTRY(thr);
24555 	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv));
24556 
24557 	DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
24558 	duk_push_lightfunc_name_raw(thr, func, lf_flags);
24559 }
24560 
duk_push_lightfunc_tostring(duk_hthread * thr,duk_tval * tv)24561 DUK_INTERNAL void duk_push_lightfunc_tostring(duk_hthread *thr, duk_tval *tv) {
24562 	duk_c_function func;
24563 	duk_small_uint_t lf_flags;
24564 
24565 	DUK_ASSERT_API_ENTRY(thr);
24566 	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv));
24567 
24568 	DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);  /* read before 'tv' potentially invalidated */
24569 	duk_push_literal(thr, "function ");
24570 	duk_push_lightfunc_name_raw(thr, func, lf_flags);
24571 	duk_push_literal(thr, "() { [lightfunc code] }");
24572 	duk_concat(thr, 3);
24573 }
24574 
24575 /*
24576  *  Function pointers
24577  *
24578  *  Printing function pointers is non-portable, so we do that by hex printing
24579  *  bytes from memory.
24580  */
24581 
duk_push_string_funcptr(duk_hthread * thr,duk_uint8_t * ptr,duk_size_t sz)24582 DUK_INTERNAL void duk_push_string_funcptr(duk_hthread *thr, duk_uint8_t *ptr, duk_size_t sz) {
24583 	duk_uint8_t buf[32 * 2];
24584 	duk_uint8_t *p, *q;
24585 	duk_small_uint_t i;
24586 	duk_small_uint_t t;
24587 
24588 	DUK_ASSERT_API_ENTRY(thr);
24589 	DUK_ASSERT(sz <= 32);  /* sanity limit for function pointer size */
24590 
24591 	p = buf;
24592 #if defined(DUK_USE_INTEGER_LE)
24593 	q = ptr + sz;
24594 #else
24595 	q = ptr;
24596 #endif
24597 	for (i = 0; i < sz; i++) {
24598 #if defined(DUK_USE_INTEGER_LE)
24599 		t = *(--q);
24600 #else
24601 		t = *(q++);
24602 #endif
24603 		*p++ = duk_lc_digits[t >> 4];
24604 		*p++ = duk_lc_digits[t & 0x0f];
24605 	}
24606 
24607 	duk_push_lstring(thr, (const char *) buf, sz * 2);
24608 }
24609 
24610 /*
24611  *  Push readable string summarizing duk_tval.  The operation is side effect
24612  *  free and will only throw from internal errors (e.g. out of memory).
24613  *  This is used by e.g. property access code to summarize a key/base safely,
24614  *  and is not intended to be fast (but small and safe).
24615  */
24616 
24617 /* String limits for summary strings. */
24618 #define DUK__READABLE_SUMMARY_MAXCHARS 96  /* maximum supported by helper */
24619 #define DUK__READABLE_STRING_MAXCHARS  32  /* for strings/symbols */
24620 #define DUK__READABLE_ERRMSG_MAXCHARS  96  /* for error messages */
24621 
24622 /* String sanitizer which escapes ASCII control characters and a few other
24623  * ASCII characters, passes Unicode as is, and replaces invalid UTF-8 with
24624  * question marks.  No errors are thrown for any input string, except in out
24625  * of memory situations.
24626  */
duk__push_hstring_readable_unicode(duk_hthread * thr,duk_hstring * h_input,duk_small_uint_t maxchars)24627 DUK_LOCAL void duk__push_hstring_readable_unicode(duk_hthread *thr, duk_hstring *h_input, duk_small_uint_t maxchars) {
24628 	const duk_uint8_t *p, *p_start, *p_end;
24629 	duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH * DUK__READABLE_SUMMARY_MAXCHARS +
24630 	                2 /*quotes*/ + 3 /*periods*/];
24631 	duk_uint8_t *q;
24632 	duk_ucodepoint_t cp;
24633 	duk_small_uint_t nchars;
24634 
24635 	DUK_CTX_ASSERT_VALID(thr);
24636 	DUK_ASSERT(h_input != NULL);
24637 	DUK_ASSERT(maxchars <= DUK__READABLE_SUMMARY_MAXCHARS);
24638 
24639 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
24640 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
24641 	p = p_start;
24642 	q = buf;
24643 
24644 	nchars = 0;
24645 	*q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;
24646 	for (;;) {
24647 		if (p >= p_end) {
24648 			break;
24649 		}
24650 		if (nchars == maxchars) {
24651 			*q++ = (duk_uint8_t) DUK_ASC_PERIOD;
24652 			*q++ = (duk_uint8_t) DUK_ASC_PERIOD;
24653 			*q++ = (duk_uint8_t) DUK_ASC_PERIOD;
24654 			break;
24655 		}
24656 		if (duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {
24657 			if (cp < 0x20 || cp == 0x7f || cp == DUK_ASC_SINGLEQUOTE || cp == DUK_ASC_BACKSLASH) {
24658 				DUK_ASSERT(DUK_UNICODE_MAX_XUTF8_LENGTH >= 4);  /* estimate is valid */
24659 				DUK_ASSERT((cp >> 4) <= 0x0f);
24660 				*q++ = (duk_uint8_t) DUK_ASC_BACKSLASH;
24661 				*q++ = (duk_uint8_t) DUK_ASC_LC_X;
24662 				*q++ = (duk_uint8_t) duk_lc_digits[cp >> 4];
24663 				*q++ = (duk_uint8_t) duk_lc_digits[cp & 0x0f];
24664 			} else {
24665 				q += duk_unicode_encode_xutf8(cp, q);
24666 			}
24667 		} else {
24668 			p++;  /* advance manually */
24669 			*q++ = (duk_uint8_t) DUK_ASC_QUESTION;
24670 		}
24671 		nchars++;
24672 	}
24673 	*q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;
24674 
24675 	duk_push_lstring(thr, (const char *) buf, (duk_size_t) (q - buf));
24676 }
24677 
duk__push_string_tval_readable(duk_hthread * thr,duk_tval * tv,duk_bool_t error_aware)24678 DUK_LOCAL const char *duk__push_string_tval_readable(duk_hthread *thr, duk_tval *tv, duk_bool_t error_aware) {
24679 	DUK_CTX_ASSERT_VALID(thr);
24680 	/* 'tv' may be NULL */
24681 
24682 	if (tv == NULL) {
24683 		duk_push_literal(thr, "none");
24684 	} else {
24685 		switch (DUK_TVAL_GET_TAG(tv)) {
24686 		case DUK_TAG_STRING: {
24687 			duk_hstring *h = DUK_TVAL_GET_STRING(tv);
24688 			if (DUK_HSTRING_HAS_SYMBOL(h)) {
24689 				/* XXX: string summary produces question marks
24690 				 * so this is not very ideal.
24691 				 */
24692 				duk_push_literal(thr, "[Symbol ");
24693 				duk_push_string(thr, duk__get_symbol_type_string(h));
24694 				duk_push_literal(thr, " ");
24695 				duk__push_hstring_readable_unicode(thr, h, DUK__READABLE_STRING_MAXCHARS);
24696 				duk_push_literal(thr, "]");
24697 				duk_concat(thr, 5);
24698 				break;
24699 			}
24700 			duk__push_hstring_readable_unicode(thr, h, DUK__READABLE_STRING_MAXCHARS);
24701 			break;
24702 		}
24703 		case DUK_TAG_OBJECT: {
24704 			duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
24705 			DUK_ASSERT(h != NULL);
24706 
24707 			if (error_aware &&
24708 			    duk_hobject_prototype_chain_contains(thr, h, thr->builtins[DUK_BIDX_ERROR_PROTOTYPE], 1 /*ignore_loop*/)) {
24709 				/* Get error message in a side effect free way if
24710 				 * possible; if not, summarize as a generic object.
24711 				 * Error message currently gets quoted.
24712 				 */
24713 				/* XXX: better internal getprop call; get without side effects
24714 				 * but traverse inheritance chain.
24715 				 */
24716 				duk_tval *tv_msg;
24717 				tv_msg = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, h, DUK_STRIDX_MESSAGE);
24718 				if (tv_msg != NULL && DUK_TVAL_IS_STRING(tv_msg)) {
24719 					/* It's critical to avoid recursion so
24720 					 * only summarize a string .message.
24721 					 */
24722 					duk__push_hstring_readable_unicode(thr, DUK_TVAL_GET_STRING(tv_msg), DUK__READABLE_ERRMSG_MAXCHARS);
24723 					break;
24724 				}
24725 			}
24726 			duk_push_class_string_tval(thr, tv, 1 /*avoid_side_effects*/);
24727 			break;
24728 		}
24729 		case DUK_TAG_BUFFER: {
24730 			/* While plain buffers mimic Uint8Arrays, they summarize differently.
24731 			 * This is useful so that the summarized string accurately reflects the
24732 			 * internal type which may matter for figuring out bugs etc.
24733 			 */
24734 			/* XXX: Hex encoded, length limited buffer summary here? */
24735 			duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
24736 			DUK_ASSERT(h != NULL);
24737 			duk_push_sprintf(thr, "[buffer:%ld]", (long) DUK_HBUFFER_GET_SIZE(h));
24738 			break;
24739 		}
24740 		case DUK_TAG_POINTER: {
24741 			/* Surround with parentheses like in JX, ensures NULL pointer
24742 			 * is distinguishable from null value ("(null)" vs "null").
24743 			 */
24744 			duk_push_tval(thr, tv);
24745 			duk_push_sprintf(thr, "(%s)", duk_to_string(thr, -1));
24746 			duk_remove_m2(thr);
24747 			break;
24748 		}
24749 		default: {
24750 			duk_push_tval(thr, tv);
24751 			break;
24752 		}
24753 		}
24754 	}
24755 
24756 	return duk_to_string(thr, -1);
24757 }
duk_push_string_tval_readable(duk_hthread * thr,duk_tval * tv)24758 DUK_INTERNAL const char *duk_push_string_tval_readable(duk_hthread *thr, duk_tval *tv) {
24759 	DUK_ASSERT_API_ENTRY(thr);
24760 	return duk__push_string_tval_readable(thr, tv, 0 /*error_aware*/);
24761 }
24762 
duk_push_string_readable(duk_hthread * thr,duk_idx_t idx)24763 DUK_INTERNAL const char *duk_push_string_readable(duk_hthread *thr, duk_idx_t idx) {
24764 	DUK_ASSERT_API_ENTRY(thr);
24765 	return duk_push_string_tval_readable(thr, duk_get_tval(thr, idx));
24766 }
24767 
duk_push_string_tval_readable_error(duk_hthread * thr,duk_tval * tv)24768 DUK_INTERNAL const char *duk_push_string_tval_readable_error(duk_hthread *thr, duk_tval *tv) {
24769 	DUK_ASSERT_API_ENTRY(thr);
24770 	return duk__push_string_tval_readable(thr, tv, 1 /*error_aware*/);
24771 }
24772 
duk_push_symbol_descriptive_string(duk_hthread * thr,duk_hstring * h)24773 DUK_INTERNAL void duk_push_symbol_descriptive_string(duk_hthread *thr, duk_hstring *h) {
24774 	const duk_uint8_t *p;
24775 	const duk_uint8_t *p_end;
24776 	const duk_uint8_t *q;
24777 
24778 	DUK_ASSERT_API_ENTRY(thr);
24779 
24780 	/* .toString() */
24781 	duk_push_literal(thr, "Symbol(");
24782 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
24783 	p_end = p + DUK_HSTRING_GET_BYTELEN(h);
24784 	DUK_ASSERT(p[0] == 0xff || (p[0] & 0xc0) == 0x80);
24785 	p++;
24786 	for (q = p; q < p_end; q++) {
24787 		if (*q == 0xffU) {
24788 			/* Terminate either at end-of-string (but NUL MUST
24789 			 * be accepted without terminating description) or
24790 			 * 0xFF, which is used to mark start of unique trailer
24791 			 * (and cannot occur in CESU-8 / extended UTF-8).
24792 			 */
24793 			break;
24794 		}
24795 	}
24796 	duk_push_lstring(thr, (const char *) p, (duk_size_t) (q - p));
24797 	duk_push_literal(thr, ")");
24798 	duk_concat(thr, 3);
24799 }
24800 
24801 /*
24802  *  Functions
24803  */
24804 
24805 #if 0  /* not used yet */
24806 DUK_INTERNAL void duk_push_hnatfunc_name(duk_hthread *thr, duk_hnatfunc *h) {
24807 	duk_c_function func;
24808 
24809 	DUK_ASSERT_API_ENTRY(thr);
24810 	DUK_ASSERT(h != NULL);
24811 	DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC((duk_hobject *) h));
24812 
24813 	duk_push_sprintf(thr, "native_");
24814 	func = h->func;
24815 	duk_push_string_funcptr(thr, (duk_uint8_t *) &func, sizeof(func));
24816 	duk_push_sprintf(thr, "_%04x_%04x",
24817 	                 (unsigned int) (duk_uint16_t) h->nargs,
24818 	                 (unsigned int) (duk_uint16_t) h->magic);
24819 	duk_concat(thr, 3);
24820 }
24821 #endif
24822 
24823 /*
24824  *  duk_tval slice copy
24825  */
24826 
duk_copy_tvals_incref(duk_hthread * thr,duk_tval * tv_dst,duk_tval * tv_src,duk_size_t count)24827 DUK_INTERNAL void duk_copy_tvals_incref(duk_hthread *thr, duk_tval *tv_dst, duk_tval *tv_src, duk_size_t count) {
24828 	duk_tval *tv;
24829 
24830 	DUK_ASSERT_API_ENTRY(thr);
24831 	DUK_UNREF(thr);
24832 	DUK_ASSERT(count * sizeof(duk_tval) >= count);  /* no wrap */
24833 
24834 	duk_memcpy_unsafe((void *) tv_dst, (const void *) tv_src, count * sizeof(duk_tval));
24835 
24836 	tv = tv_dst;
24837 	while (count-- > 0) {
24838 		DUK_TVAL_INCREF(thr, tv);
24839 		tv++;
24840 	}
24841 }
24842 
24843 /* automatic undefs */
24844 #undef DUK__ASSERT_SPACE
24845 #undef DUK__CHECK_SPACE
24846 #undef DUK__ERROR_STASH_SHARED
24847 #undef DUK__PACK_ARGS
24848 #undef DUK__READABLE_ERRMSG_MAXCHARS
24849 #undef DUK__READABLE_STRING_MAXCHARS
24850 #undef DUK__READABLE_SUMMARY_MAXCHARS
24851 /*
24852  *  String manipulation
24853  */
24854 
24855 /* #include duk_internal.h -> already included */
24856 
duk__concat_and_join_helper(duk_hthread * thr,duk_idx_t count_in,duk_bool_t is_join)24857 DUK_LOCAL void duk__concat_and_join_helper(duk_hthread *thr, duk_idx_t count_in, duk_bool_t is_join) {
24858 	duk_uint_t count;
24859 	duk_uint_t i;
24860 	duk_size_t idx;
24861 	duk_size_t len;
24862 	duk_hstring *h;
24863 	duk_uint8_t *buf;
24864 
24865 	DUK_CTX_ASSERT_VALID(thr);
24866 
24867 	if (DUK_UNLIKELY(count_in <= 0)) {
24868 		if (count_in < 0) {
24869 			DUK_ERROR_RANGE_INVALID_COUNT(thr);
24870 			DUK_WO_NORETURN(return;);
24871 		}
24872 		DUK_ASSERT(count_in == 0);
24873 		duk_push_hstring_empty(thr);
24874 		return;
24875 	}
24876 	count = (duk_uint_t) count_in;
24877 
24878 	if (is_join) {
24879 		duk_size_t t1, t2, limit;
24880 		h = duk_to_hstring(thr, -((duk_idx_t) count) - 1);
24881 		DUK_ASSERT(h != NULL);
24882 
24883 		/* A bit tricky overflow test, see doc/code-issues.rst. */
24884 		t1 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
24885 		t2 = (duk_size_t) (count - 1);
24886 		limit = (duk_size_t) DUK_HSTRING_MAX_BYTELEN;
24887 		if (DUK_UNLIKELY(t2 != 0 && t1 > limit / t2)) {
24888 			/* Combined size of separators already overflows. */
24889 			goto error_overflow;
24890 		}
24891 		len = (duk_size_t) (t1 * t2);
24892 	} else {
24893 		len = (duk_size_t) 0;
24894 	}
24895 
24896 	for (i = count; i >= 1; i--) {
24897 		duk_size_t new_len;
24898 		h = duk_to_hstring(thr, -((duk_idx_t) i));
24899 		new_len = len + (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
24900 
24901 		/* Impose a string maximum length, need to handle overflow
24902 		 * correctly.
24903 		 */
24904 		if (new_len < len ||  /* wrapped */
24905 		    new_len > (duk_size_t) DUK_HSTRING_MAX_BYTELEN) {
24906 			goto error_overflow;
24907 		}
24908 		len = new_len;
24909 	}
24910 
24911 	DUK_DDD(DUK_DDDPRINT("join/concat %lu strings, total length %lu bytes",
24912 	                     (unsigned long) count, (unsigned long) len));
24913 
24914 	/* Use stack allocated buffer to ensure reachability in errors
24915 	 * (e.g. intern error).
24916 	 */
24917 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len);
24918 	DUK_ASSERT(buf != NULL);
24919 
24920 	/* [ ... (sep) str1 str2 ... strN buf ] */
24921 
24922 	idx = 0;
24923 	for (i = count; i >= 1; i--) {
24924 		if (is_join && i != count) {
24925 			h = duk_require_hstring(thr, -((duk_idx_t) count) - 2);  /* extra -1 for buffer */
24926 			duk_memcpy(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
24927 			idx += DUK_HSTRING_GET_BYTELEN(h);
24928 		}
24929 		h = duk_require_hstring(thr, -((duk_idx_t) i) - 1);  /* extra -1 for buffer */
24930 		duk_memcpy(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
24931 		idx += DUK_HSTRING_GET_BYTELEN(h);
24932 	}
24933 
24934 	DUK_ASSERT(idx == len);
24935 
24936 	/* [ ... (sep) str1 str2 ... strN buf ] */
24937 
24938 	/* Get rid of the strings early to minimize memory use before intern. */
24939 
24940 	if (is_join) {
24941 		duk_replace(thr, -((duk_idx_t) count) - 2);  /* overwrite sep */
24942 		duk_pop_n(thr, (duk_idx_t) count);
24943 	} else {
24944 		duk_replace(thr, -((duk_idx_t) count) - 1);  /* overwrite str1 */
24945 		duk_pop_n(thr, (duk_idx_t) (count - 1));
24946 	}
24947 
24948 	/* [ ... buf ] */
24949 
24950 	(void) duk_buffer_to_string(thr, -1);  /* Safe if inputs are safe. */
24951 
24952 	/* [ ... res ] */
24953 	return;
24954 
24955  error_overflow:
24956 	DUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG);
24957 	DUK_WO_NORETURN(return;);
24958 }
24959 
duk_concat(duk_hthread * thr,duk_idx_t count)24960 DUK_EXTERNAL void duk_concat(duk_hthread *thr, duk_idx_t count) {
24961 	DUK_ASSERT_API_ENTRY(thr);
24962 
24963 	duk__concat_and_join_helper(thr, count, 0 /*is_join*/);
24964 }
24965 
24966 #if defined(DUK_USE_PREFER_SIZE)
duk_concat_2(duk_hthread * thr)24967 DUK_INTERNAL void duk_concat_2(duk_hthread *thr) {
24968 	DUK_ASSERT_API_ENTRY(thr);
24969 	duk_concat(thr, 2);
24970 }
24971 #else  /* DUK_USE_PREFER_SIZE */
duk_concat_2(duk_hthread * thr)24972 DUK_INTERNAL void duk_concat_2(duk_hthread *thr) {
24973 	duk_hstring *h1;
24974 	duk_hstring *h2;
24975 	duk_uint8_t *buf;
24976 	duk_size_t len1;
24977 	duk_size_t len2;
24978 	duk_size_t len;
24979 
24980 	DUK_ASSERT_API_ENTRY(thr);
24981 	DUK_ASSERT(duk_get_top(thr) >= 2);  /* Trusted caller. */
24982 
24983 	h1 = duk_to_hstring(thr, -2);
24984 	h2 = duk_to_hstring(thr, -1);
24985 	len1 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1);
24986 	len2 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2);
24987 	len = len1 + len2;
24988 	if (DUK_UNLIKELY(len < len1 ||  /* wrapped */
24989 	                 len > (duk_size_t) DUK_HSTRING_MAX_BYTELEN)) {
24990 		goto error_overflow;
24991 	}
24992 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len);
24993 	DUK_ASSERT(buf != NULL);
24994 
24995 	duk_memcpy((void *) buf, (const void *) DUK_HSTRING_GET_DATA(h1), (size_t) len1);
24996 	duk_memcpy((void *) (buf + len1), (const void *) DUK_HSTRING_GET_DATA(h2), (size_t) len2);
24997 	(void) duk_buffer_to_string(thr, -1);  /* Safe if inputs are safe. */
24998 
24999 	/* [ ... str1 str2 buf ] */
25000 
25001 	duk_replace(thr, -3);
25002 	duk_pop_unsafe(thr);
25003 	return;
25004 
25005  error_overflow:
25006 	DUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG);
25007 	DUK_WO_NORETURN(return;);
25008 }
25009 #endif  /* DUK_USE_PREFER_SIZE */
25010 
duk_join(duk_hthread * thr,duk_idx_t count)25011 DUK_EXTERNAL void duk_join(duk_hthread *thr, duk_idx_t count) {
25012 	DUK_ASSERT_API_ENTRY(thr);
25013 
25014 	duk__concat_and_join_helper(thr, count, 1 /*is_join*/);
25015 }
25016 
25017 /* XXX: could map/decode be unified with duk_unicode_support.c code?
25018  * Case conversion needs also the character surroundings though.
25019  */
25020 
duk_decode_string(duk_hthread * thr,duk_idx_t idx,duk_decode_char_function callback,void * udata)25021 DUK_EXTERNAL void duk_decode_string(duk_hthread *thr, duk_idx_t idx, duk_decode_char_function callback, void *udata) {
25022 	duk_hstring *h_input;
25023 	const duk_uint8_t *p, *p_start, *p_end;
25024 	duk_codepoint_t cp;
25025 
25026 	DUK_ASSERT_API_ENTRY(thr);
25027 
25028 	h_input = duk_require_hstring(thr, idx);  /* Accept symbols. */
25029 	DUK_ASSERT(h_input != NULL);
25030 
25031 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
25032 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
25033 	p = p_start;
25034 
25035 	for (;;) {
25036 		if (p >= p_end) {
25037 			break;
25038 		}
25039 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
25040 		callback(udata, cp);
25041 	}
25042 }
25043 
duk_map_string(duk_hthread * thr,duk_idx_t idx,duk_map_char_function callback,void * udata)25044 DUK_EXTERNAL void duk_map_string(duk_hthread *thr, duk_idx_t idx, duk_map_char_function callback, void *udata) {
25045 	duk_hstring *h_input;
25046 	duk_bufwriter_ctx bw_alloc;
25047 	duk_bufwriter_ctx *bw;
25048 	const duk_uint8_t *p, *p_start, *p_end;
25049 	duk_codepoint_t cp;
25050 
25051 	DUK_ASSERT_API_ENTRY(thr);
25052 
25053 	idx = duk_normalize_index(thr, idx);
25054 
25055 	h_input = duk_require_hstring(thr, idx);  /* Accept symbols. */
25056 	DUK_ASSERT(h_input != NULL);
25057 
25058 	bw = &bw_alloc;
25059 	DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));  /* Reasonable output estimate. */
25060 
25061 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
25062 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
25063 	p = p_start;
25064 
25065 	for (;;) {
25066 		/* XXX: could write output in chunks with fewer ensure calls,
25067 		 * but relative benefit would be small here.
25068 		 */
25069 
25070 		if (p >= p_end) {
25071 			break;
25072 		}
25073 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
25074 		cp = callback(udata, cp);
25075 
25076 		DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp);
25077 	}
25078 
25079 	DUK_BW_COMPACT(thr, bw);
25080 	(void) duk_buffer_to_string(thr, -1);  /* Safe, extended UTF-8 encoded. */
25081 	duk_replace(thr, idx);
25082 }
25083 
duk_substring(duk_hthread * thr,duk_idx_t idx,duk_size_t start_offset,duk_size_t end_offset)25084 DUK_EXTERNAL void duk_substring(duk_hthread *thr, duk_idx_t idx, duk_size_t start_offset, duk_size_t end_offset) {
25085 	duk_hstring *h;
25086 	duk_hstring *res;
25087 	duk_size_t start_byte_offset;
25088 	duk_size_t end_byte_offset;
25089 	duk_size_t charlen;
25090 
25091 	DUK_ASSERT_API_ENTRY(thr);
25092 
25093 	idx = duk_require_normalize_index(thr, idx);  /* Accept symbols. */
25094 	h = duk_require_hstring(thr, idx);
25095 	DUK_ASSERT(h != NULL);
25096 
25097 	charlen = DUK_HSTRING_GET_CHARLEN(h);
25098 	if (end_offset >= charlen) {
25099 		end_offset = charlen;
25100 	}
25101 	if (start_offset > end_offset) {
25102 		start_offset = end_offset;
25103 	}
25104 
25105 	DUK_ASSERT_DISABLE(start_offset >= 0);
25106 	DUK_ASSERT(start_offset <= end_offset && start_offset <= DUK_HSTRING_GET_CHARLEN(h));
25107 	DUK_ASSERT_DISABLE(end_offset >= 0);
25108 	DUK_ASSERT(end_offset >= start_offset && end_offset <= DUK_HSTRING_GET_CHARLEN(h));
25109 
25110 	/* Guaranteed by string limits. */
25111 	DUK_ASSERT(start_offset <= DUK_UINT32_MAX);
25112 	DUK_ASSERT(end_offset <= DUK_UINT32_MAX);
25113 
25114 	start_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) start_offset);
25115 	end_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) end_offset);
25116 
25117 	DUK_ASSERT(end_byte_offset >= start_byte_offset);
25118 	DUK_ASSERT(end_byte_offset - start_byte_offset <= DUK_UINT32_MAX);  /* Guaranteed by string limits. */
25119 
25120 	/* No size check is necessary. */
25121 	res = duk_heap_strtable_intern_checked(thr,
25122 	                                       DUK_HSTRING_GET_DATA(h) + start_byte_offset,
25123 	                                       (duk_uint32_t) (end_byte_offset - start_byte_offset));
25124 
25125 	duk_push_hstring(thr, res);
25126 	duk_replace(thr, idx);
25127 }
25128 
25129 /* XXX: this is quite clunky.  Add Unicode helpers to scan backwards and
25130  * forwards with a callback to process codepoints?
25131  */
duk_trim(duk_hthread * thr,duk_idx_t idx)25132 DUK_EXTERNAL void duk_trim(duk_hthread *thr, duk_idx_t idx) {
25133 	duk_hstring *h;
25134 	const duk_uint8_t *p, *p_start, *p_end, *p_tmp1, *p_tmp2;  /* pointers for scanning */
25135 	const duk_uint8_t *q_start, *q_end;  /* start (incl) and end (excl) of trimmed part */
25136 	duk_codepoint_t cp;
25137 
25138 	DUK_ASSERT_API_ENTRY(thr);
25139 
25140 	idx = duk_require_normalize_index(thr, idx);  /* Accept symbols. */
25141 	h = duk_require_hstring(thr, idx);
25142 	DUK_ASSERT(h != NULL);
25143 
25144 	p_start = DUK_HSTRING_GET_DATA(h);
25145 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h);
25146 
25147 	p = p_start;
25148 	while (p < p_end) {
25149 		p_tmp1 = p;
25150 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp1, p_start, p_end);
25151 		if (!(duk_unicode_is_whitespace(cp) || duk_unicode_is_line_terminator(cp))) {
25152 			break;
25153 		}
25154 		p = p_tmp1;
25155 	}
25156 	q_start = p;
25157 	if (p == p_end) {
25158 		/* Entire string is whitespace. */
25159 		q_end = p;
25160 		goto scan_done;
25161 	}
25162 
25163 	p = p_end;
25164 	while (p > p_start) {
25165 		p_tmp1 = p;
25166 		while (p > p_start) {
25167 			p--;
25168 			if (((*p) & 0xc0) != 0x80) {
25169 				break;
25170 			}
25171 		}
25172 		p_tmp2 = p;
25173 
25174 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp2, p_start, p_end);
25175 		if (!(duk_unicode_is_whitespace(cp) || duk_unicode_is_line_terminator(cp))) {
25176 			p = p_tmp1;
25177 			break;
25178 		}
25179 	}
25180 	q_end = p;
25181 
25182  scan_done:
25183 	/* This may happen when forward and backward scanning disagree
25184 	 * (possible for non-extended-UTF-8 strings).
25185 	 */
25186 	if (q_end < q_start) {
25187 		q_end = q_start;
25188 	}
25189 
25190 	DUK_ASSERT(q_start >= p_start && q_start <= p_end);
25191 	DUK_ASSERT(q_end >= p_start && q_end <= p_end);
25192 	DUK_ASSERT(q_end >= q_start);
25193 
25194 	DUK_DDD(DUK_DDDPRINT("trim: p_start=%p, p_end=%p, q_start=%p, q_end=%p",
25195 	                     (const void *) p_start, (const void *) p_end,
25196 	                     (const void *) q_start, (const void *) q_end));
25197 
25198 	if (q_start == p_start && q_end == p_end) {
25199 		DUK_DDD(DUK_DDDPRINT("nothing was trimmed: avoid interning (hashing etc)"));
25200 		return;
25201 	}
25202 
25203 	duk_push_lstring(thr, (const char *) q_start, (duk_size_t) (q_end - q_start));
25204 	duk_replace(thr, idx);
25205 }
25206 
duk_char_code_at(duk_hthread * thr,duk_idx_t idx,duk_size_t char_offset)25207 DUK_EXTERNAL duk_codepoint_t duk_char_code_at(duk_hthread *thr, duk_idx_t idx, duk_size_t char_offset) {
25208 	duk_hstring *h;
25209 	duk_ucodepoint_t cp;
25210 
25211 	DUK_ASSERT_API_ENTRY(thr);
25212 
25213 	/* XXX: Share code with String.prototype.charCodeAt?  Main difference
25214 	 * is handling of clamped offsets.
25215 	 */
25216 
25217 	h = duk_require_hstring(thr, idx);  /* Accept symbols. */
25218 	DUK_ASSERT(h != NULL);
25219 
25220 	DUK_ASSERT_DISABLE(char_offset >= 0);  /* Always true, arg is unsigned. */
25221 	if (char_offset >= DUK_HSTRING_GET_CHARLEN(h)) {
25222 		return 0;
25223 	}
25224 
25225 	DUK_ASSERT(char_offset <= DUK_UINT_MAX);  /* Guaranteed by string limits. */
25226 	cp = duk_hstring_char_code_at_raw(thr, h, (duk_uint_t) char_offset, 0 /*surrogate_aware*/);
25227 	return (duk_codepoint_t) cp;
25228 }
25229 /*
25230  *  Date/time.
25231  */
25232 
25233 /* #include duk_internal.h -> already included */
25234 
duk_time_get_ecmascript_time(duk_hthread * thr)25235 DUK_INTERNAL duk_double_t duk_time_get_ecmascript_time(duk_hthread *thr) {
25236 	/* ECMAScript time, with millisecond fractions.  Exposed via
25237 	 * duk_get_now() for example.
25238 	 */
25239 	DUK_UNREF(thr);
25240 	return (duk_double_t) DUK_USE_DATE_GET_NOW(thr);
25241 }
25242 
duk_time_get_ecmascript_time_nofrac(duk_hthread * thr)25243 DUK_INTERNAL duk_double_t duk_time_get_ecmascript_time_nofrac(duk_hthread *thr) {
25244 	/* ECMAScript time without millisecond fractions.  Exposed via
25245 	 * the Date built-in which doesn't allow fractions.
25246 	 */
25247 	DUK_UNREF(thr);
25248 	return (duk_double_t) DUK_FLOOR(DUK_USE_DATE_GET_NOW(thr));
25249 }
25250 
duk_time_get_monotonic_time(duk_hthread * thr)25251 DUK_INTERNAL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr) {
25252 	DUK_UNREF(thr);
25253 #if defined(DUK_USE_GET_MONOTONIC_TIME)
25254 	return (duk_double_t) DUK_USE_GET_MONOTONIC_TIME(thr);
25255 #else
25256 	return (duk_double_t) DUK_USE_DATE_GET_NOW(thr);
25257 #endif
25258 }
25259 
duk_get_now(duk_hthread * thr)25260 DUK_EXTERNAL duk_double_t duk_get_now(duk_hthread *thr) {
25261 	DUK_ASSERT_API_ENTRY(thr);
25262 	DUK_UNREF(thr);
25263 
25264 	/* This API intentionally allows millisecond fractions. */
25265 	return duk_time_get_ecmascript_time(thr);
25266 }
25267 
25268 #if 0  /* XXX: worth exposing? */
25269 DUK_EXTERNAL duk_double_t duk_get_monotonic_time(duk_hthread *thr) {
25270 	DUK_ASSERT_API_ENTRY(thr);
25271 	DUK_UNREF(thr);
25272 
25273 	return duk_time_get_monotonic_time(thr);
25274 }
25275 #endif
25276 
duk_time_to_components(duk_hthread * thr,duk_double_t timeval,duk_time_components * comp)25277 DUK_EXTERNAL void duk_time_to_components(duk_hthread *thr, duk_double_t timeval, duk_time_components *comp) {
25278 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
25279 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
25280 	duk_uint_t flags;
25281 
25282 	DUK_ASSERT_API_ENTRY(thr);
25283 	DUK_ASSERT(comp != NULL);  /* XXX: or check? */
25284 	DUK_UNREF(thr);
25285 
25286 	/* Convert as one-based, but change month to zero-based to match the
25287 	 * ECMAScript Date built-in behavior 1:1.
25288 	 */
25289 	flags = DUK_DATE_FLAG_ONEBASED | DUK_DATE_FLAG_NAN_TO_ZERO;
25290 
25291 	duk_bi_date_timeval_to_parts(timeval, parts, dparts, flags);
25292 
25293 	/* XXX: sub-millisecond accuracy for the API */
25294 
25295 	DUK_ASSERT(dparts[DUK_DATE_IDX_MONTH] >= 1.0 && dparts[DUK_DATE_IDX_MONTH] <= 12.0);
25296 	comp->year = dparts[DUK_DATE_IDX_YEAR];
25297 	comp->month = dparts[DUK_DATE_IDX_MONTH] - 1.0;
25298 	comp->day = dparts[DUK_DATE_IDX_DAY];
25299 	comp->hours = dparts[DUK_DATE_IDX_HOUR];
25300 	comp->minutes = dparts[DUK_DATE_IDX_MINUTE];
25301 	comp->seconds = dparts[DUK_DATE_IDX_SECOND];
25302 	comp->milliseconds = dparts[DUK_DATE_IDX_MILLISECOND];
25303 	comp->weekday = dparts[DUK_DATE_IDX_WEEKDAY];
25304 }
25305 
duk_components_to_time(duk_hthread * thr,duk_time_components * comp)25306 DUK_EXTERNAL duk_double_t duk_components_to_time(duk_hthread *thr, duk_time_components *comp) {
25307 	duk_double_t d;
25308 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
25309 	duk_uint_t flags;
25310 
25311 	DUK_ASSERT_API_ENTRY(thr);
25312 	DUK_ASSERT(comp != NULL);  /* XXX: or check? */
25313 	DUK_UNREF(thr);
25314 
25315 	/* Match Date constructor behavior (with UTC time).  Month is given
25316 	 * as zero-based.  Day-of-month is given as one-based so normalize
25317 	 * it to zero-based as the internal conversion helpers expects all
25318 	 * components to be zero-based.
25319 	 */
25320 	flags = 0;
25321 
25322 	/* XXX: expensive conversion; use array format in API instead, or unify
25323 	 * time provider and time API to use same struct?
25324 	 */
25325 
25326 	dparts[DUK_DATE_IDX_YEAR] = comp->year;
25327 	dparts[DUK_DATE_IDX_MONTH] = comp->month;
25328 	dparts[DUK_DATE_IDX_DAY] = comp->day - 1.0;
25329 	dparts[DUK_DATE_IDX_HOUR] = comp->hours;
25330 	dparts[DUK_DATE_IDX_MINUTE] = comp->minutes;
25331 	dparts[DUK_DATE_IDX_SECOND] = comp->seconds;
25332 	dparts[DUK_DATE_IDX_MILLISECOND] = comp->milliseconds;
25333 	dparts[DUK_DATE_IDX_WEEKDAY] = 0;  /* ignored */
25334 
25335 	d = duk_bi_date_get_timeval_from_dparts(dparts, flags);
25336 
25337 	return d;
25338 }
25339 /*
25340  *  Array built-ins
25341  *
25342  *  Most Array built-ins are intentionally generic in ECMAScript, and are
25343  *  intended to work even when the 'this' binding is not an Array instance.
25344  *  This ECMAScript feature is also used by much real world code.  For this
25345  *  reason the implementations here don't assume exotic Array behavior or
25346  *  e.g. presence of a .length property.  However, some algorithms have a
25347  *  fast path for duk_harray backed actual Array instances, enabled when
25348  *  footprint is not a concern.
25349  *
25350  *  XXX: the "Throw" flag should be set for (almost?) all [[Put]] and
25351  *  [[Delete]] operations, but it's currently false throughout.  Go through
25352  *  all put/delete cases and check throw flag use.  Need a new API primitive
25353  *  which allows throws flag to be specified.
25354  *
25355  *  XXX: array lengths above 2G won't work reliably.  There are many places
25356  *  where one needs a full signed 32-bit range ([-0xffffffff, 0xffffffff],
25357  *  i.e. -33- bits).  Although array 'length' cannot be written to be outside
25358  *  the unsigned 32-bit range (E5.1 Section 15.4.5.1 throws a RangeError if so)
25359  *  some intermediate values may be above 0xffffffff and this may not be always
25360  *  correctly handled now (duk_uint32_t is not enough for all algorithms).
25361  *  For instance, push() can legitimately write entries beyond length 0xffffffff
25362  *  and cause a RangeError only at the end.  To do this properly, the current
25363  *  push() implementation tracks the array index using a 'double' instead of a
25364  *  duk_uint32_t (which is somewhat awkward).  See test-bi-array-push-maxlen.js.
25365  *
25366  *  On using "put" vs. "def" prop
25367  *  =============================
25368  *
25369  *  Code below must be careful to use the appropriate primitive as it matters
25370  *  for compliance.  When using "put" there may be inherited properties in
25371  *  Array.prototype which cause side effects when values are written.  When
25372  *  using "define" there are no such side effects, and many test262 test cases
25373  *  check for this (for real world code, such side effects are very rare).
25374  *  Both "put" and "define" are used in the E5.1 specification; as a rule,
25375  *  "put" is used when modifying an existing array (or a non-array 'this'
25376  *  binding) and "define" for setting values into a fresh result array.
25377  */
25378 
25379 /* #include duk_internal.h -> already included */
25380 
25381 /* Perform an intermediate join when this many elements have been pushed
25382  * on the value stack.
25383  */
25384 #define  DUK__ARRAY_MID_JOIN_LIMIT  4096
25385 
25386 #if defined(DUK_USE_ARRAY_BUILTIN)
25387 
25388 /*
25389  *  Shared helpers.
25390  */
25391 
25392 /* Shared entry code for many Array built-ins: the 'this' binding is pushed
25393  * on the value stack and object coerced, and the current .length is returned.
25394  * Note that length is left on stack (it could be popped, but that's not
25395  * usually necessary because call handling will clean it up automatically).
25396  */
duk__push_this_obj_len_u32(duk_hthread * thr)25397 DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32(duk_hthread *thr) {
25398 	duk_uint32_t len;
25399 
25400 	/* XXX: push more directly? */
25401 	(void) duk_push_this_coercible_to_object(thr);
25402 	DUK_HOBJECT_ASSERT_VALID(duk_get_hobject(thr, -1));
25403 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_LENGTH);
25404 	len = duk_to_uint32(thr, -1);
25405 
25406 	/* -> [ ... ToObject(this) ToUint32(length) ] */
25407 	return len;
25408 }
25409 
duk__push_this_obj_len_u32_limited(duk_hthread * thr)25410 DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32_limited(duk_hthread *thr) {
25411 	/* Range limited to [0, 0x7fffffff] range, i.e. range that can be
25412 	 * represented with duk_int32_t.  Use this when the method doesn't
25413 	 * handle the full 32-bit unsigned range correctly.
25414 	 */
25415 	duk_uint32_t ret = duk__push_this_obj_len_u32(thr);
25416 	if (DUK_UNLIKELY(ret >= 0x80000000UL)) {
25417 		DUK_ERROR_RANGE_INVALID_LENGTH(thr);
25418 		DUK_WO_NORETURN(return 0U;);
25419 	}
25420 	return ret;
25421 }
25422 
25423 #if defined(DUK_USE_ARRAY_FASTPATH)
25424 /* Check if 'this' binding is an Array instance (duk_harray) which satisfies
25425  * a few other guarantees for fast path operation.  The fast path doesn't
25426  * need to handle all operations, even for duk_harrays, but must handle a
25427  * significant fraction to improve performance.  Return a non-NULL duk_harray
25428  * pointer when all fast path criteria are met, NULL otherwise.
25429  */
duk__arraypart_fastpath_this(duk_hthread * thr)25430 DUK_LOCAL duk_harray *duk__arraypart_fastpath_this(duk_hthread *thr) {
25431 	duk_tval *tv;
25432 	duk_hobject *h;
25433 	duk_uint_t flags_mask, flags_bits, flags_value;
25434 
25435 	DUK_ASSERT(thr->valstack_bottom > thr->valstack);  /* because call in progress */
25436 	tv = DUK_GET_THIS_TVAL_PTR(thr);
25437 
25438 	/* Fast path requires that 'this' is a duk_harray.  Read only arrays
25439 	 * (ROM backed) are also rejected for simplicity.
25440 	 */
25441 	if (!DUK_TVAL_IS_OBJECT(tv)) {
25442 		DUK_DD(DUK_DDPRINT("reject array fast path: not an object"));
25443 		return NULL;
25444 	}
25445 	h = DUK_TVAL_GET_OBJECT(tv);
25446 	DUK_ASSERT(h != NULL);
25447 	flags_mask = DUK_HOBJECT_FLAG_ARRAY_PART | \
25448 	             DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
25449 	             DUK_HEAPHDR_FLAG_READONLY;
25450 	flags_bits = DUK_HOBJECT_FLAG_ARRAY_PART | \
25451 	             DUK_HOBJECT_FLAG_EXOTIC_ARRAY;
25452 	flags_value = DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) h);
25453 	if ((flags_value & flags_mask) != flags_bits) {
25454 		DUK_DD(DUK_DDPRINT("reject array fast path: object flag check failed"));
25455 		return NULL;
25456 	}
25457 
25458 	/* In some cases a duk_harray's 'length' may be larger than the
25459 	 * current array part allocation.  Avoid the fast path in these
25460 	 * cases, so that all fast path code can safely assume that all
25461 	 * items in the range [0,length[ are backed by the current array
25462 	 * part allocation.
25463 	 */
25464 	if (((duk_harray *) h)->length > DUK_HOBJECT_GET_ASIZE(h)) {
25465 		DUK_DD(DUK_DDPRINT("reject array fast path: length > array part size"));
25466 		return NULL;
25467 	}
25468 
25469 	/* Guarantees for fast path. */
25470 	DUK_ASSERT(h != NULL);
25471 	DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(h) == 0 || DUK_HOBJECT_A_GET_BASE(thr->heap, h) != NULL);
25472 	DUK_ASSERT(((duk_harray *) h)->length <= DUK_HOBJECT_GET_ASIZE(h));
25473 
25474 	DUK_DD(DUK_DDPRINT("array fast path allowed for: %!O", (duk_heaphdr *) h));
25475 	return (duk_harray *) h;
25476 }
25477 #endif  /* DUK_USE_ARRAY_FASTPATH */
25478 
25479 /*
25480  *  Constructor
25481  */
25482 
duk_bi_array_constructor(duk_hthread * thr)25483 DUK_INTERNAL duk_ret_t duk_bi_array_constructor(duk_hthread *thr) {
25484 	duk_idx_t nargs;
25485 	duk_harray *a;
25486 	duk_double_t d;
25487 	duk_uint32_t len;
25488 	duk_uint32_t len_prealloc;
25489 
25490 	nargs = duk_get_top(thr);
25491 
25492 	if (nargs == 1 && duk_is_number(thr, 0)) {
25493 		/* XXX: expensive check (also shared elsewhere - so add a shared internal API call?) */
25494 		d = duk_get_number(thr, 0);
25495 		len = duk_to_uint32(thr, 0);
25496 		if (!duk_double_equals((duk_double_t) len, d)) {
25497 			DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
25498 		}
25499 
25500 		/* For small lengths create a dense preallocated array.
25501 		 * For large arrays preallocate an initial part.
25502 		 */
25503 		len_prealloc = len < 64 ? len : 64;
25504 		a = duk_push_harray_with_size(thr, len_prealloc);
25505 		DUK_ASSERT(a != NULL);
25506 		DUK_ASSERT(!duk_is_bare_object(thr, -1));
25507 		a->length = len;
25508 		return 1;
25509 	}
25510 
25511 	duk_pack(thr, nargs);
25512 	return 1;
25513 }
25514 
25515 /*
25516  *  isArray()
25517  */
25518 
duk_bi_array_constructor_is_array(duk_hthread * thr)25519 DUK_INTERNAL duk_ret_t duk_bi_array_constructor_is_array(duk_hthread *thr) {
25520 	DUK_ASSERT_TOP(thr, 1);
25521 	duk_push_boolean(thr, duk_js_isarray(DUK_GET_TVAL_POSIDX(thr, 0)));
25522 	return 1;
25523 }
25524 
25525 /*
25526  *  toString()
25527  */
25528 
duk_bi_array_prototype_to_string(duk_hthread * thr)25529 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_to_string(duk_hthread *thr) {
25530 	(void) duk_push_this_coercible_to_object(thr);
25531 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_JOIN);
25532 
25533 	/* [ ... this func ] */
25534 	if (!duk_is_callable(thr, -1)) {
25535 		/* Fall back to the initial (original) Object.toString().  We don't
25536 		 * currently have pointers to the built-in functions, only the top
25537 		 * level global objects (like "Array") so this is now done in a bit
25538 		 * of a hacky manner.  It would be cleaner to push the (original)
25539 		 * function and use duk_call_method().
25540 		 */
25541 
25542 		/* XXX: 'this' will be ToObject() coerced twice, which is incorrect
25543 		 * but should have no visible side effects.
25544 		 */
25545 		DUK_DDD(DUK_DDDPRINT("this.join is not callable, fall back to (original) Object.toString"));
25546 		duk_set_top(thr, 0);
25547 		return duk_bi_object_prototype_to_string(thr);  /* has access to 'this' binding */
25548 	}
25549 
25550 	/* [ ... this func ] */
25551 
25552 	duk_insert(thr, -2);
25553 
25554 	/* [ ... func this ] */
25555 
25556 	DUK_DDD(DUK_DDDPRINT("calling: func=%!iT, this=%!iT",
25557 	                     (duk_tval *) duk_get_tval(thr, -2),
25558 	                     (duk_tval *) duk_get_tval(thr, -1)));
25559 	duk_call_method(thr, 0);
25560 
25561 	return 1;
25562 }
25563 
25564 /*
25565  *  concat()
25566  */
25567 
duk_bi_array_prototype_concat(duk_hthread * thr)25568 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_concat(duk_hthread *thr) {
25569 	duk_idx_t i, n;
25570 	duk_uint32_t j, idx, len;
25571 	duk_hobject *h;
25572 	duk_size_t tmp_len;
25573 
25574 	/* XXX: In ES2015 Array .length can be up to 2^53-1.  The current
25575 	 * implementation is limited to 2^32-1.
25576 	 */
25577 
25578 	/* XXX: Fast path for array 'this' and array element. */
25579 
25580 	/* XXX: The insert here is a bit expensive if there are a lot of items.
25581 	 * It could also be special cased in the outermost for loop quite easily
25582 	 * (as the element is dup()'d anyway).
25583 	 */
25584 
25585 	(void) duk_push_this_coercible_to_object(thr);
25586 	duk_insert(thr, 0);
25587 	n = duk_get_top(thr);
25588 	duk_push_array(thr);  /* -> [ ToObject(this) item1 ... itemN arr ] */
25589 
25590 	/* NOTE: The Array special behaviors are NOT invoked by duk_xdef_prop_index()
25591 	 * (which differs from the official algorithm).  If no error is thrown, this
25592 	 * doesn't matter as the length is updated at the end.  However, if an error
25593 	 * is thrown, the length will be unset.  That shouldn't matter because the
25594 	 * caller won't get a reference to the intermediate value.
25595 	 */
25596 
25597 	idx = 0;
25598 	for (i = 0; i < n; i++) {
25599 		duk_bool_t spreadable;
25600 		duk_bool_t need_has_check;
25601 
25602 		DUK_ASSERT_TOP(thr, n + 1);
25603 
25604 		/* [ ToObject(this) item1 ... itemN arr ] */
25605 
25606 		h = duk_get_hobject(thr, i);
25607 
25608 		if (h == NULL) {
25609 			spreadable = 0;
25610 		} else {
25611 #if defined(DUK_USE_SYMBOL_BUILTIN)
25612 			duk_get_prop_stridx(thr, i, DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE);
25613 			if (duk_is_undefined(thr, -1)) {
25614 				spreadable = duk_js_isarray_hobject(h);
25615 			} else {
25616 				spreadable = duk_to_boolean(thr, -1);
25617 			}
25618 			duk_pop_nodecref_unsafe(thr);
25619 #else
25620 			spreadable = duk_js_isarray_hobject(h);
25621 #endif
25622 		}
25623 
25624 		if (!spreadable) {
25625 			duk_dup(thr, i);
25626 			duk_xdef_prop_index_wec(thr, -2, idx);
25627 			idx++;
25628 			if (DUK_UNLIKELY(idx == 0U)) {
25629 				/* Index after update is 0, and index written
25630 				 * was 0xffffffffUL which is no longer a valid
25631 				 * array index.
25632 				 */
25633 				goto fail_wrap;
25634 			}
25635 			continue;
25636 		}
25637 
25638 		DUK_ASSERT(duk_is_object(thr, i));
25639 		need_has_check = (DUK_HOBJECT_IS_PROXY(h) != 0);  /* Always 0 w/o Proxy support. */
25640 
25641 		/* [ ToObject(this) item1 ... itemN arr ] */
25642 
25643 		tmp_len = duk_get_length(thr, i);
25644 		len = (duk_uint32_t) tmp_len;
25645 		if (DUK_UNLIKELY(tmp_len != (duk_size_t) len)) {
25646 			goto fail_wrap;
25647 		}
25648 		if (DUK_UNLIKELY(idx + len < idx)) {
25649 			/* Result length must be at most 0xffffffffUL to be
25650 			 * a valid 32-bit array index.
25651 			 */
25652 			goto fail_wrap;
25653 		}
25654 		for (j = 0; j < len; j++) {
25655 			/* For a Proxy element, an explicit 'has' check is
25656 			 * needed to allow the Proxy to present gaps.
25657 			 */
25658 			if (need_has_check) {
25659 				if (duk_has_prop_index(thr, i, j)) {
25660 					duk_get_prop_index(thr, i, j);
25661 					duk_xdef_prop_index_wec(thr, -2, idx);
25662 				}
25663 			} else {
25664 				if (duk_get_prop_index(thr, i, j)) {
25665 					duk_xdef_prop_index_wec(thr, -2, idx);
25666 				} else {
25667 					duk_pop_undefined(thr);
25668 				}
25669 			}
25670 			idx++;
25671 			DUK_ASSERT(idx != 0U);  /* Wrap check above. */
25672 		}
25673 	}
25674 
25675 	/* ES5.1 has a specification "bug" in that nonexistent trailing
25676 	 * elements don't affect the result .length.  Test262 and other
25677 	 * engines disagree, and the specification bug was fixed in ES2015
25678 	 * (see NOTE 1 in https://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.concat).
25679 	 */
25680 	duk_push_uarridx(thr, idx);
25681 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
25682 
25683 	DUK_ASSERT_TOP(thr, n + 1);
25684 	return 1;
25685 
25686  fail_wrap:
25687 	DUK_ERROR_RANGE_INVALID_LENGTH(thr);
25688 	DUK_WO_NORETURN(return 0;);
25689 }
25690 
25691 /*
25692  *  join(), toLocaleString()
25693  *
25694  *  Note: checking valstack is necessary, but only in the per-element loop.
25695  *
25696  *  Note: the trivial approach of pushing all the elements on the value stack
25697  *  and then calling duk_join() fails when the array contains a large number
25698  *  of elements.  This problem can't be offloaded to duk_join() because the
25699  *  elements to join must be handled here and have special handling.  Current
25700  *  approach is to do intermediate joins with very large number of elements.
25701  *  There is no fancy handling; the prefix gets re-joined multiple times.
25702  */
25703 
duk_bi_array_prototype_join_shared(duk_hthread * thr)25704 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_join_shared(duk_hthread *thr) {
25705 	duk_uint32_t len, count;
25706 	duk_uint32_t idx;
25707 	duk_small_int_t to_locale_string = duk_get_current_magic(thr);
25708 	duk_idx_t valstack_required;
25709 
25710 	/* For join(), nargs is 1.  For toLocaleString(), nargs is 0 and
25711 	 * setting the top essentially pushes an undefined to the stack,
25712 	 * thus defaulting to a comma separator.
25713 	 */
25714 	duk_set_top(thr, 1);
25715 	if (duk_is_undefined(thr, 0)) {
25716 		duk_pop_undefined(thr);
25717 		duk_push_hstring_stridx(thr, DUK_STRIDX_COMMA);
25718 	} else {
25719 		duk_to_string(thr, 0);
25720 	}
25721 
25722 	len = duk__push_this_obj_len_u32(thr);
25723 
25724 	/* [ sep ToObject(this) len ] */
25725 
25726 	DUK_DDD(DUK_DDDPRINT("sep=%!T, this=%!T, len=%lu",
25727 	                     (duk_tval *) duk_get_tval(thr, 0),
25728 	                     (duk_tval *) duk_get_tval(thr, 1),
25729 	                     (unsigned long) len));
25730 
25731 	/* The extra (+4) is tight. */
25732 	valstack_required = (duk_idx_t) ((len >= DUK__ARRAY_MID_JOIN_LIMIT ?
25733 	                                  DUK__ARRAY_MID_JOIN_LIMIT : len) + 4);
25734 	duk_require_stack(thr, valstack_required);
25735 
25736 	duk_dup_0(thr);
25737 
25738 	/* [ sep ToObject(this) len sep ] */
25739 
25740 	count = 0;
25741 	idx = 0;
25742 	for (;;) {
25743 		DUK_DDD(DUK_DDDPRINT("join idx=%ld", (long) idx));
25744 		if (count >= DUK__ARRAY_MID_JOIN_LIMIT ||   /* intermediate join to avoid valstack overflow */
25745 		    idx >= len) { /* end of loop (careful with len==0) */
25746 			/* [ sep ToObject(this) len sep str0 ... str(count-1) ] */
25747 			DUK_DDD(DUK_DDDPRINT("mid/final join, count=%ld, idx=%ld, len=%ld",
25748 			                     (long) count, (long) idx, (long) len));
25749 			duk_join(thr, (duk_idx_t) count);  /* -> [ sep ToObject(this) len str ] */
25750 			duk_dup_0(thr);                    /* -> [ sep ToObject(this) len str sep ] */
25751 			duk_insert(thr, -2);               /* -> [ sep ToObject(this) len sep str ] */
25752 			count = 1;
25753 		}
25754 		if (idx >= len) {
25755 			/* if true, the stack already contains the final result */
25756 			break;
25757 		}
25758 
25759 		duk_get_prop_index(thr, 1, (duk_uarridx_t) idx);
25760 		if (duk_is_null_or_undefined(thr, -1)) {
25761 			duk_pop_nodecref_unsafe(thr);
25762 			duk_push_hstring_empty(thr);
25763 		} else {
25764 			if (to_locale_string) {
25765 				duk_to_object(thr, -1);
25766 				duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_TO_LOCALE_STRING);
25767 				duk_insert(thr, -2);  /* -> [ ... toLocaleString ToObject(val) ] */
25768 				duk_call_method(thr, 0);
25769 			}
25770 			duk_to_string(thr, -1);
25771 		}
25772 
25773 		count++;
25774 		idx++;
25775 	}
25776 
25777 	/* [ sep ToObject(this) len sep result ] */
25778 
25779 	return 1;
25780 }
25781 
25782 /*
25783  *  pop(), push()
25784  */
25785 
25786 #if defined(DUK_USE_ARRAY_FASTPATH)
duk__array_pop_fastpath(duk_hthread * thr,duk_harray * h_arr)25787 DUK_LOCAL duk_ret_t duk__array_pop_fastpath(duk_hthread *thr, duk_harray *h_arr) {
25788 	duk_tval *tv_arraypart;
25789 	duk_tval *tv_val;
25790 	duk_uint32_t len;
25791 
25792 	tv_arraypart = DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) h_arr);
25793 	len = h_arr->length;
25794 	if (len <= 0) {
25795 		/* nop, return undefined */
25796 		return 0;
25797 	}
25798 
25799 	len--;
25800 	h_arr->length = len;
25801 
25802 	/* Fast path doesn't check for an index property inherited from
25803 	 * Array.prototype.  This is quite often acceptable; if not,
25804 	 * disable fast path.
25805 	 */
25806 	DUK_ASSERT_VS_SPACE(thr);
25807 	tv_val = tv_arraypart + len;
25808 	if (DUK_TVAL_IS_UNUSED(tv_val)) {
25809 		/* No net refcount change.  Value stack already has
25810 		 * 'undefined' based on value stack init policy.
25811 		 */
25812 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));
25813 		DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv_val));
25814 	} else {
25815 		/* No net refcount change. */
25816 		DUK_TVAL_SET_TVAL(thr->valstack_top, tv_val);
25817 		DUK_TVAL_SET_UNUSED(tv_val);
25818 	}
25819 	thr->valstack_top++;
25820 
25821 	/* XXX: there's no shrink check in the fast path now */
25822 
25823 	return 1;
25824 }
25825 #endif  /* DUK_USE_ARRAY_FASTPATH */
25826 
duk_bi_array_prototype_pop(duk_hthread * thr)25827 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_pop(duk_hthread *thr) {
25828 	duk_uint32_t len;
25829 	duk_uint32_t idx;
25830 #if defined(DUK_USE_ARRAY_FASTPATH)
25831 	duk_harray *h_arr;
25832 #endif
25833 
25834 	DUK_ASSERT_TOP(thr, 0);
25835 
25836 #if defined(DUK_USE_ARRAY_FASTPATH)
25837 	h_arr = duk__arraypart_fastpath_this(thr);
25838 	if (h_arr) {
25839 		return duk__array_pop_fastpath(thr, h_arr);
25840 	}
25841 #endif
25842 
25843 	/* XXX: Merge fastpath check into a related call (push this, coerce length, etc)? */
25844 
25845 	len = duk__push_this_obj_len_u32(thr);
25846 	if (len == 0) {
25847 		duk_push_int(thr, 0);
25848 		duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
25849 		return 0;
25850 	}
25851 	idx = len - 1;
25852 
25853 	duk_get_prop_index(thr, 0, (duk_uarridx_t) idx);
25854 	duk_del_prop_index(thr, 0, (duk_uarridx_t) idx);
25855 	duk_push_u32(thr, idx);
25856 	duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
25857 	return 1;
25858 }
25859 
25860 #if defined(DUK_USE_ARRAY_FASTPATH)
duk__array_push_fastpath(duk_hthread * thr,duk_harray * h_arr)25861 DUK_LOCAL duk_ret_t duk__array_push_fastpath(duk_hthread *thr, duk_harray *h_arr) {
25862 	duk_tval *tv_arraypart;
25863 	duk_tval *tv_src;
25864 	duk_tval *tv_dst;
25865 	duk_uint32_t len;
25866 	duk_idx_t i, n;
25867 
25868 	len = h_arr->length;
25869 	tv_arraypart = DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) h_arr);
25870 
25871 	n = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
25872 	DUK_ASSERT(n >= 0);
25873 	DUK_ASSERT((duk_uint32_t) n <= DUK_UINT32_MAX);
25874 	if (DUK_UNLIKELY(len + (duk_uint32_t) n < len)) {
25875 		DUK_D(DUK_DPRINT("Array.prototype.push() would go beyond 32-bit length, throw"));
25876 		DUK_DCERROR_RANGE_INVALID_LENGTH(thr);  /* != 0 return value returned as is by caller */
25877 	}
25878 	if (len + (duk_uint32_t) n > DUK_HOBJECT_GET_ASIZE((duk_hobject *) h_arr)) {
25879 		/* Array part would need to be extended.  Rely on slow path
25880 		 * for now.
25881 		 *
25882 		 * XXX: Rework hobject code a bit and add extend support.
25883 		 */
25884 		return 0;
25885 	}
25886 
25887 	tv_src = thr->valstack_bottom;
25888 	tv_dst = tv_arraypart + len;
25889 	for (i = 0; i < n; i++) {
25890 		/* No net refcount change; reset value stack values to
25891 		 * undefined to satisfy value stack init policy.
25892 		 */
25893 		DUK_TVAL_SET_TVAL(tv_dst, tv_src);
25894 		DUK_TVAL_SET_UNDEFINED(tv_src);
25895 		tv_src++;
25896 		tv_dst++;
25897 	}
25898 	thr->valstack_top = thr->valstack_bottom;
25899 	len += (duk_uint32_t) n;
25900 	h_arr->length = len;
25901 
25902 	DUK_ASSERT((duk_uint_t) len == len);
25903 	duk_push_uint(thr, (duk_uint_t) len);
25904 	return 1;
25905 }
25906 #endif  /* DUK_USE_ARRAY_FASTPATH */
25907 
duk_bi_array_prototype_push(duk_hthread * thr)25908 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_push(duk_hthread *thr) {
25909 	/* Note: 'this' is not necessarily an Array object.  The push()
25910 	 * algorithm is supposed to work for other kinds of objects too,
25911 	 * so the algorithm has e.g. an explicit update for the 'length'
25912 	 * property which is normally "magical" in arrays.
25913 	 */
25914 
25915 	duk_uint32_t len;
25916 	duk_idx_t i, n;
25917 #if defined(DUK_USE_ARRAY_FASTPATH)
25918 	duk_harray *h_arr;
25919 #endif
25920 
25921 #if defined(DUK_USE_ARRAY_FASTPATH)
25922 	h_arr = duk__arraypart_fastpath_this(thr);
25923 	if (h_arr) {
25924 		duk_ret_t rc;
25925 		rc = duk__array_push_fastpath(thr, h_arr);
25926 		if (rc != 0) {
25927 			return rc;
25928 		}
25929 		DUK_DD(DUK_DDPRINT("array push() fast path exited, resize case"));
25930 	}
25931 #endif
25932 
25933 	n = duk_get_top(thr);
25934 	len = duk__push_this_obj_len_u32(thr);
25935 
25936 	/* [ arg1 ... argN obj length ] */
25937 
25938 	/* Technically Array.prototype.push() can create an Array with length
25939 	 * longer than 2^32-1, i.e. outside the 32-bit range.  The final length
25940 	 * is *not* wrapped to 32 bits in the specification.
25941 	 *
25942 	 * This implementation tracks length with a uint32 because it's much
25943 	 * more practical.
25944 	 *
25945 	 * See: test-bi-array-push-maxlen.js.
25946 	 */
25947 
25948 	if (len + (duk_uint32_t) n < len) {
25949 		DUK_D(DUK_DPRINT("Array.prototype.push() would go beyond 32-bit length, throw"));
25950 		DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
25951 	}
25952 
25953 	for (i = 0; i < n; i++) {
25954 		duk_dup(thr, i);
25955 		duk_put_prop_index(thr, -3, (duk_uarridx_t) (len + (duk_uint32_t) i));
25956 	}
25957 	len += (duk_uint32_t) n;
25958 
25959 	duk_push_u32(thr, len);
25960 	duk_dup_top(thr);
25961 	duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_LENGTH);
25962 
25963 	/* [ arg1 ... argN obj length new_length ] */
25964 	return 1;
25965 }
25966 
25967 /*
25968  *  sort()
25969  *
25970  *  Currently qsort with random pivot.  This is now really, really slow,
25971  *  because there is no fast path for array parts.
25972  *
25973  *  Signed indices are used because qsort() leaves and degenerate cases
25974  *  may use a negative offset.
25975  */
25976 
duk__array_sort_compare(duk_hthread * thr,duk_int_t idx1,duk_int_t idx2)25977 DUK_LOCAL duk_small_int_t duk__array_sort_compare(duk_hthread *thr, duk_int_t idx1, duk_int_t idx2) {
25978 	duk_bool_t have1, have2;
25979 	duk_bool_t undef1, undef2;
25980 	duk_small_int_t ret;
25981 	duk_idx_t idx_obj = 1;  /* fixed offsets in valstack */
25982 	duk_idx_t idx_fn = 0;
25983 	duk_hstring *h1, *h2;
25984 
25985 	/* Fast exit if indices are identical.  This is valid for a non-existent property,
25986 	 * for an undefined value, and almost always for ToString() coerced comparison of
25987 	 * arbitrary values (corner cases where this is not the case include e.g. a an
25988 	 * object with varying ToString() coercion).
25989 	 *
25990 	 * The specification does not prohibit "caching" of values read from the array, so
25991 	 * assuming equality for comparing an index with itself falls into the category of
25992 	 * "caching".
25993 	 *
25994 	 * Also, compareFn may be inconsistent, so skipping a call to compareFn here may
25995 	 * have an effect on the final result.  The specification does not require any
25996 	 * specific behavior for inconsistent compare functions, so again, this fast path
25997 	 * is OK.
25998 	 */
25999 
26000 	if (idx1 == idx2) {
26001 		DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld -> indices identical, quick exit",
26002 		                     (long) idx1, (long) idx2));
26003 		return 0;
26004 	}
26005 
26006 	have1 = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) idx1);
26007 	have2 = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) idx2);
26008 
26009 	DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld, have1=%ld, have2=%ld, val1=%!T, val2=%!T",
26010 	                     (long) idx1, (long) idx2, (long) have1, (long) have2,
26011 	                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
26012 
26013 	if (have1) {
26014 		if (have2) {
26015 			;
26016 		} else {
26017 			ret = -1;
26018 			goto pop_ret;
26019 		}
26020 	} else {
26021 		if (have2) {
26022 			ret = 1;
26023 			goto pop_ret;
26024 		} else {
26025 			ret = 0;
26026 			goto pop_ret;
26027 		}
26028 	}
26029 
26030 	undef1 = duk_is_undefined(thr, -2);
26031 	undef2 = duk_is_undefined(thr, -1);
26032 	if (undef1) {
26033 		if (undef2) {
26034 			ret = 0;
26035 			goto pop_ret;
26036 		} else {
26037 			ret = 1;
26038 			goto pop_ret;
26039 		}
26040 	} else {
26041 		if (undef2) {
26042 			ret = -1;
26043 			goto pop_ret;
26044 		} else {
26045 			;
26046 		}
26047 	}
26048 
26049 	if (!duk_is_undefined(thr, idx_fn)) {
26050 		duk_double_t d;
26051 
26052 		/* No need to check callable; duk_call() will do that. */
26053 		duk_dup(thr, idx_fn);    /* -> [ ... x y fn ] */
26054 		duk_insert(thr, -3);     /* -> [ ... fn x y ] */
26055 		duk_call(thr, 2);        /* -> [ ... res ] */
26056 
26057 		/* ES5 is a bit vague about what to do if the return value is
26058 		 * not a number.  ES2015 provides a concrete description:
26059 		 * http://www.ecma-international.org/ecma-262/6.0/#sec-sortcompare.
26060 		 */
26061 
26062 		d = duk_to_number_m1(thr);
26063 		if (d < 0.0) {
26064 			ret = -1;
26065 		} else if (d > 0.0) {
26066 			ret = 1;
26067 		} else {
26068 			/* Because NaN compares to false, NaN is handled here
26069 			 * without an explicit check above.
26070 			 */
26071 			ret = 0;
26072 		}
26073 
26074 		duk_pop_nodecref_unsafe(thr);
26075 		DUK_DDD(DUK_DDDPRINT("-> result %ld (from comparefn, after coercion)", (long) ret));
26076 		return ret;
26077 	}
26078 
26079 	/* string compare is the default (a bit oddly) */
26080 
26081 	/* XXX: any special handling for plain array; causes repeated coercion now? */
26082 	h1 = duk_to_hstring(thr, -2);
26083 	h2 = duk_to_hstring_m1(thr);
26084 	DUK_ASSERT(h1 != NULL);
26085 	DUK_ASSERT(h2 != NULL);
26086 
26087 	ret = duk_js_string_compare(h1, h2);  /* retval is directly usable */
26088 	goto pop_ret;
26089 
26090  pop_ret:
26091 	duk_pop_2_unsafe(thr);
26092 	DUK_DDD(DUK_DDDPRINT("-> result %ld", (long) ret));
26093 	return ret;
26094 }
26095 
duk__array_sort_swap(duk_hthread * thr,duk_int_t l,duk_int_t r)26096 DUK_LOCAL void duk__array_sort_swap(duk_hthread *thr, duk_int_t l, duk_int_t r) {
26097 	duk_bool_t have_l, have_r;
26098 	duk_idx_t idx_obj = 1;  /* fixed offset in valstack */
26099 
26100 	if (l == r) {
26101 		return;
26102 	}
26103 
26104 	/* swap elements; deal with non-existent elements correctly */
26105 	have_l = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) l);
26106 	have_r = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) r);
26107 
26108 	if (have_r) {
26109 		/* right exists, [[Put]] regardless whether or not left exists */
26110 		duk_put_prop_index(thr, idx_obj, (duk_uarridx_t) l);
26111 	} else {
26112 		duk_del_prop_index(thr, idx_obj, (duk_uarridx_t) l);
26113 		duk_pop_undefined(thr);
26114 	}
26115 
26116 	if (have_l) {
26117 		duk_put_prop_index(thr, idx_obj, (duk_uarridx_t) r);
26118 	} else {
26119 		duk_del_prop_index(thr, idx_obj, (duk_uarridx_t) r);
26120 		duk_pop_undefined(thr);
26121 	}
26122 }
26123 
26124 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
26125 /* Debug print which visualizes the qsort partitioning process. */
duk__debuglog_qsort_state(duk_hthread * thr,duk_int_t lo,duk_int_t hi,duk_int_t pivot)26126 DUK_LOCAL void duk__debuglog_qsort_state(duk_hthread *thr, duk_int_t lo, duk_int_t hi, duk_int_t pivot) {
26127 	char buf[4096];
26128 	char *ptr = buf;
26129 	duk_int_t i, n;
26130 	n = (duk_int_t) duk_get_length(thr, 1);
26131 	if (n > 4000) {
26132 		n = 4000;
26133 	}
26134 	*ptr++ = '[';
26135 	for (i = 0; i < n; i++) {
26136 		if (i == pivot) {
26137 			*ptr++ = '|';
26138 		} else if (i == lo) {
26139 			*ptr++ = '<';
26140 		} else if (i == hi) {
26141 			*ptr++ = '>';
26142 		} else if (i >= lo && i <= hi) {
26143 			*ptr++ = '-';
26144 		} else {
26145 			*ptr++ = ' ';
26146 		}
26147 	}
26148 	*ptr++ = ']';
26149 	*ptr++ = '\0';
26150 
26151 	DUK_DDD(DUK_DDDPRINT("%s   (lo=%ld, hi=%ld, pivot=%ld)",
26152 	                     (const char *) buf, (long) lo, (long) hi, (long) pivot));
26153 }
26154 #endif
26155 
duk__array_qsort(duk_hthread * thr,duk_int_t lo,duk_int_t hi)26156 DUK_LOCAL void duk__array_qsort(duk_hthread *thr, duk_int_t lo, duk_int_t hi) {
26157 	duk_int_t p, l, r;
26158 
26159 	/* The lo/hi indices may be crossed and hi < 0 is possible at entry. */
26160 
26161 	DUK_DDD(DUK_DDDPRINT("duk__array_qsort: lo=%ld, hi=%ld, obj=%!T",
26162 	                     (long) lo, (long) hi, (duk_tval *) duk_get_tval(thr, 1)));
26163 
26164 	DUK_ASSERT_TOP(thr, 3);
26165 
26166 	/* In some cases it may be that lo > hi, or hi < 0; these
26167 	 * degenerate cases happen e.g. for empty arrays, and in
26168 	 * recursion leaves.
26169 	 */
26170 
26171 	/* trivial cases */
26172 	if (hi - lo < 1) {
26173 		DUK_DDD(DUK_DDDPRINT("degenerate case, return immediately"));
26174 		return;
26175 	}
26176 	DUK_ASSERT(hi > lo);
26177 	DUK_ASSERT(hi - lo + 1 >= 2);
26178 
26179 	/* randomized pivot selection */
26180 	p = lo + (duk_int_t) (DUK_UTIL_GET_RANDOM_DOUBLE(thr) * (duk_double_t) (hi - lo + 1));
26181 	DUK_ASSERT(p >= lo && p <= hi);
26182 	DUK_DDD(DUK_DDDPRINT("lo=%ld, hi=%ld, chose pivot p=%ld", (long) lo, (long) hi, (long) p));
26183 
26184 	/* move pivot out of the way */
26185 	duk__array_sort_swap(thr, p, lo);
26186 	p = lo;
26187 	DUK_DDD(DUK_DDDPRINT("pivot moved out of the way: %!T", (duk_tval *) duk_get_tval(thr, 1)));
26188 
26189 	l = lo + 1;
26190 	r = hi;
26191 	for (;;) {
26192 		/* find elements to swap */
26193 		for (;;) {
26194 			DUK_DDD(DUK_DDDPRINT("left scan: l=%ld, r=%ld, p=%ld",
26195 			                     (long) l, (long) r, (long) p));
26196 			if (l >= hi) {
26197 				break;
26198 			}
26199 			if (duk__array_sort_compare(thr, l, p) >= 0) {  /* !(l < p) */
26200 				break;
26201 			}
26202 			l++;
26203 		}
26204 		for (;;) {
26205 			DUK_DDD(DUK_DDDPRINT("right scan: l=%ld, r=%ld, p=%ld",
26206 			                     (long) l, (long) r, (long) p));
26207 			if (r <= lo) {
26208 				break;
26209 			}
26210 			if (duk__array_sort_compare(thr, p, r) >= 0) {  /* !(p < r) */
26211 				break;
26212 			}
26213 			r--;
26214 		}
26215 		if (l >= r) {
26216 			goto done;
26217 		}
26218 		DUK_ASSERT(l < r);
26219 
26220 		DUK_DDD(DUK_DDDPRINT("swap %ld and %ld", (long) l, (long) r));
26221 
26222 		duk__array_sort_swap(thr, l, r);
26223 
26224 		DUK_DDD(DUK_DDDPRINT("after swap: %!T", (duk_tval *) duk_get_tval(thr, 1)));
26225 		l++;
26226 		r--;
26227 	}
26228  done:
26229 	/* Note that 'l' and 'r' may cross, i.e. r < l */
26230 	DUK_ASSERT(l >= lo && l <= hi);
26231 	DUK_ASSERT(r >= lo && r <= hi);
26232 
26233 	/* XXX: there's no explicit recursion bound here now.  For the average
26234 	 * qsort recursion depth O(log n) that's not really necessary: e.g. for
26235 	 * 2**32 recursion depth would be about 32 which is OK.  However, qsort
26236 	 * worst case recursion depth is O(n) which may be a problem.
26237 	 */
26238 
26239 	/* move pivot to its final place */
26240 	DUK_DDD(DUK_DDDPRINT("before final pivot swap: %!T", (duk_tval *) duk_get_tval(thr, 1)));
26241 	duk__array_sort_swap(thr, lo, r);
26242 
26243 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
26244 	duk__debuglog_qsort_state(thr, lo, hi, r);
26245 #endif
26246 
26247 	DUK_DDD(DUK_DDDPRINT("recurse: pivot=%ld, obj=%!T", (long) r, (duk_tval *) duk_get_tval(thr, 1)));
26248 	duk__array_qsort(thr, lo, r - 1);
26249 	duk__array_qsort(thr, r + 1, hi);
26250 }
26251 
duk_bi_array_prototype_sort(duk_hthread * thr)26252 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_sort(duk_hthread *thr) {
26253 	duk_uint32_t len;
26254 
26255 	/* XXX: len >= 0x80000000 won't work below because a signed type
26256 	 * is needed by qsort.
26257 	 */
26258 	len = duk__push_this_obj_len_u32_limited(thr);
26259 
26260 	/* stack[0] = compareFn
26261 	 * stack[1] = ToObject(this)
26262 	 * stack[2] = ToUint32(length)
26263 	 */
26264 
26265 	if (len > 0) {
26266 		/* avoid degenerate cases, so that (len - 1) won't underflow */
26267 		duk__array_qsort(thr, (duk_int_t) 0, (duk_int_t) (len - 1));
26268 	}
26269 
26270 	DUK_ASSERT_TOP(thr, 3);
26271 	duk_pop_nodecref_unsafe(thr);
26272 	return 1;  /* return ToObject(this) */
26273 }
26274 
26275 /*
26276  *  splice()
26277  */
26278 
26279 /* XXX: this compiles to over 500 bytes now, even without special handling
26280  * for an array part.  Uses signed ints so does not handle full array range correctly.
26281  */
26282 
26283 /* XXX: can shift() / unshift() use the same helper?
26284  *   shift() is (close to?) <--> splice(0, 1)
26285  *   unshift is (close to?) <--> splice(0, 0, [items])?
26286  */
26287 
duk_bi_array_prototype_splice(duk_hthread * thr)26288 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_splice(duk_hthread *thr) {
26289 	duk_idx_t nargs;
26290 	duk_uint32_t len_u32;
26291 	duk_int_t len;
26292 	duk_bool_t have_delcount;
26293 	duk_int_t item_count;
26294 	duk_int_t act_start;
26295 	duk_int_t del_count;
26296 	duk_int_t i, n;
26297 
26298 	DUK_UNREF(have_delcount);
26299 
26300 	nargs = duk_get_top(thr);
26301 	if (nargs < 2) {
26302 		duk_set_top(thr, 2);
26303 		nargs = 2;
26304 		have_delcount = 0;
26305 	} else {
26306 		have_delcount = 1;
26307 	}
26308 
26309 	/* XXX: len >= 0x80000000 won't work below because we need to be
26310 	 * able to represent -len.
26311 	 */
26312 	len_u32 = duk__push_this_obj_len_u32_limited(thr);
26313 	len = (duk_int_t) len_u32;
26314 	DUK_ASSERT(len >= 0);
26315 
26316 	act_start = duk_to_int_clamped(thr, 0, -len, len);
26317 	if (act_start < 0) {
26318 		act_start = len + act_start;
26319 	}
26320 	DUK_ASSERT(act_start >= 0 && act_start <= len);
26321 
26322 #if defined(DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT)
26323 	if (have_delcount) {
26324 #endif
26325 		del_count = duk_to_int_clamped(thr, 1, 0, len - act_start);
26326 #if defined(DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT)
26327 	} else {
26328 		/* E5.1 standard behavior when deleteCount is not given would be
26329 		 * to treat it just like if 'undefined' was given, which coerces
26330 		 * ultimately to 0.  Real world behavior is to splice to the end
26331 		 * of array, see test-bi-array-proto-splice-no-delcount.js.
26332 		 */
26333 		del_count = len - act_start;
26334 	}
26335 #endif
26336 
26337 	DUK_ASSERT(nargs >= 2);
26338 	item_count = (duk_int_t) (nargs - 2);
26339 
26340 	DUK_ASSERT(del_count >= 0 && del_count <= len - act_start);
26341 	DUK_ASSERT(del_count + act_start <= len);
26342 
26343 	/* For now, restrict result array into 32-bit length range. */
26344 	if (((duk_double_t) len) - ((duk_double_t) del_count) + ((duk_double_t) item_count) > (duk_double_t) DUK_UINT32_MAX) {
26345 		DUK_D(DUK_DPRINT("Array.prototype.splice() would go beyond 32-bit length, throw"));
26346 		DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
26347 	}
26348 
26349 	duk_push_array(thr);
26350 
26351 	/* stack[0] = start
26352 	 * stack[1] = deleteCount
26353 	 * stack[2...nargs-1] = items
26354 	 * stack[nargs] = ToObject(this)               -3
26355 	 * stack[nargs+1] = ToUint32(length)           -2
26356 	 * stack[nargs+2] = result array               -1
26357 	 */
26358 
26359 	DUK_ASSERT_TOP(thr, nargs + 3);
26360 
26361 	/* Step 9: copy elements-to-be-deleted into the result array */
26362 
26363 	for (i = 0; i < del_count; i++) {
26364 		if (duk_get_prop_index(thr, -3, (duk_uarridx_t) (act_start + i))) {
26365 			duk_xdef_prop_index_wec(thr, -2, (duk_uarridx_t) i);  /* throw flag irrelevant (false in std alg) */
26366 		} else {
26367 			duk_pop_undefined(thr);
26368 		}
26369 	}
26370 	duk_push_u32(thr, (duk_uint32_t) del_count);
26371 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
26372 
26373 	/* Steps 12 and 13: reorganize elements to make room for itemCount elements */
26374 
26375 	if (item_count < del_count) {
26376 		/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 1
26377 		 * -> [ A B F G H ]          (conceptual intermediate step)
26378 		 * -> [ A B . F G H ]        (placeholder marked)
26379 		 *    [ A B C F G H ]        (actual result at this point, C will be replaced)
26380 		 */
26381 
26382 		DUK_ASSERT_TOP(thr, nargs + 3);
26383 
26384 		n = len - del_count;
26385 		for (i = act_start; i < n; i++) {
26386 			if (duk_get_prop_index(thr, -3, (duk_uarridx_t) (i + del_count))) {
26387 				duk_put_prop_index(thr, -4, (duk_uarridx_t) (i + item_count));
26388 			} else {
26389 				duk_pop_undefined(thr);
26390 				duk_del_prop_index(thr, -3, (duk_uarridx_t) (i + item_count));
26391 			}
26392 		}
26393 
26394 		DUK_ASSERT_TOP(thr, nargs + 3);
26395 
26396 		/* loop iterator init and limit changed from standard algorithm */
26397 		n = len - del_count + item_count;
26398 		for (i = len - 1; i >= n; i--) {
26399 			duk_del_prop_index(thr, -3, (duk_uarridx_t) i);
26400 		}
26401 
26402 		DUK_ASSERT_TOP(thr, nargs + 3);
26403 	} else if (item_count > del_count) {
26404 		/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 4
26405 		 * -> [ A B F G H ]          (conceptual intermediate step)
26406 		 * -> [ A B . . . . F G H ]  (placeholder marked)
26407 		 *    [ A B C D E F F G H ]  (actual result at this point)
26408 		 */
26409 
26410 		DUK_ASSERT_TOP(thr, nargs + 3);
26411 
26412 		/* loop iterator init and limit changed from standard algorithm */
26413 		for (i = len - del_count - 1; i >= act_start; i--) {
26414 			if (duk_get_prop_index(thr, -3, (duk_uarridx_t) (i + del_count))) {
26415 				duk_put_prop_index(thr, -4, (duk_uarridx_t) (i + item_count));
26416 			} else {
26417 				duk_pop_undefined(thr);
26418 				duk_del_prop_index(thr, -3, (duk_uarridx_t) (i + item_count));
26419 			}
26420 		}
26421 
26422 		DUK_ASSERT_TOP(thr, nargs + 3);
26423 	} else {
26424 		/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 3
26425 		 * -> [ A B F G H ]          (conceptual intermediate step)
26426 		 * -> [ A B . . . F G H ]    (placeholder marked)
26427 		 *    [ A B C D E F G H ]    (actual result at this point)
26428 		 */
26429 	}
26430 	DUK_ASSERT_TOP(thr, nargs + 3);
26431 
26432 	/* Step 15: insert itemCount elements into the hole made above */
26433 
26434 	for (i = 0; i < item_count; i++) {
26435 		duk_dup(thr, i + 2);  /* args start at index 2 */
26436 		duk_put_prop_index(thr, -4, (duk_uarridx_t) (act_start + i));
26437 	}
26438 
26439 	/* Step 16: update length; note that the final length may be above 32 bit range
26440 	 * (but we checked above that this isn't the case here)
26441 	 */
26442 
26443 	duk_push_u32(thr, (duk_uint32_t) (len - del_count + item_count));
26444 	duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_LENGTH);
26445 
26446 	/* result array is already at the top of stack */
26447 	DUK_ASSERT_TOP(thr, nargs + 3);
26448 	return 1;
26449 }
26450 
26451 /*
26452  *  reverse()
26453  */
26454 
duk_bi_array_prototype_reverse(duk_hthread * thr)26455 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reverse(duk_hthread *thr) {
26456 	duk_uint32_t len;
26457 	duk_uint32_t middle;
26458 	duk_uint32_t lower, upper;
26459 	duk_bool_t have_lower, have_upper;
26460 
26461 	len = duk__push_this_obj_len_u32(thr);
26462 	middle = len / 2;
26463 
26464 	/* If len <= 1, middle will be 0 and for-loop bails out
26465 	 * immediately (0 < 0 -> false).
26466 	 */
26467 
26468 	for (lower = 0; lower < middle; lower++) {
26469 		DUK_ASSERT(len >= 2);
26470 		DUK_ASSERT_TOP(thr, 2);
26471 
26472 		DUK_ASSERT(len >= lower + 1);
26473 		upper = len - lower - 1;
26474 
26475 		have_lower = duk_get_prop_index(thr, -2, (duk_uarridx_t) lower);
26476 		have_upper = duk_get_prop_index(thr, -3, (duk_uarridx_t) upper);
26477 
26478 		/* [ ToObject(this) ToUint32(length) lowerValue upperValue ] */
26479 
26480 		if (have_upper) {
26481 			duk_put_prop_index(thr, -4, (duk_uarridx_t) lower);
26482 		} else {
26483 			duk_del_prop_index(thr, -4, (duk_uarridx_t) lower);
26484 			duk_pop_undefined(thr);
26485 		}
26486 
26487 		if (have_lower) {
26488 			duk_put_prop_index(thr, -3, (duk_uarridx_t) upper);
26489 		} else {
26490 			duk_del_prop_index(thr, -3, (duk_uarridx_t) upper);
26491 			duk_pop_undefined(thr);
26492 		}
26493 
26494 		DUK_ASSERT_TOP(thr, 2);
26495 	}
26496 
26497 	DUK_ASSERT_TOP(thr, 2);
26498 	duk_pop_unsafe(thr);  /* -> [ ToObject(this) ] */
26499 	return 1;
26500 }
26501 
26502 /*
26503  *  slice()
26504  */
26505 
duk_bi_array_prototype_slice(duk_hthread * thr)26506 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_slice(duk_hthread *thr) {
26507 	duk_uint32_t len_u32;
26508 	duk_int_t len;
26509 	duk_int_t start, end;
26510 	duk_int_t i;
26511 	duk_uarridx_t idx;
26512 	duk_uint32_t res_length = 0;
26513 
26514 	/* XXX: len >= 0x80000000 won't work below because we need to be
26515 	 * able to represent -len.
26516 	 */
26517 	len_u32 = duk__push_this_obj_len_u32_limited(thr);
26518 	len = (duk_int_t) len_u32;
26519 	DUK_ASSERT(len >= 0);
26520 
26521 	duk_push_array(thr);
26522 
26523 	/* stack[0] = start
26524 	 * stack[1] = end
26525 	 * stack[2] = ToObject(this)
26526 	 * stack[3] = ToUint32(length)
26527 	 * stack[4] = result array
26528 	 */
26529 
26530 	start = duk_to_int_clamped(thr, 0, -len, len);
26531 	if (start < 0) {
26532 		start = len + start;
26533 	}
26534 	/* XXX: could duk_is_undefined() provide defaulting undefined to 'len'
26535 	 * (the upper limit)?
26536 	 */
26537 	if (duk_is_undefined(thr, 1)) {
26538 		end = len;
26539 	} else {
26540 		end = duk_to_int_clamped(thr, 1, -len, len);
26541 		if (end < 0) {
26542 			end = len + end;
26543 		}
26544 	}
26545 	DUK_ASSERT(start >= 0 && start <= len);
26546 	DUK_ASSERT(end >= 0 && end <= len);
26547 
26548 	idx = 0;
26549 	for (i = start; i < end; i++) {
26550 		DUK_ASSERT_TOP(thr, 5);
26551 		if (duk_get_prop_index(thr, 2, (duk_uarridx_t) i)) {
26552 			duk_xdef_prop_index_wec(thr, 4, idx);
26553 			res_length = idx + 1;
26554 		} else {
26555 			duk_pop_undefined(thr);
26556 		}
26557 		idx++;
26558 		DUK_ASSERT_TOP(thr, 5);
26559 	}
26560 
26561 	duk_push_u32(thr, res_length);
26562 	duk_xdef_prop_stridx_short(thr, 4, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
26563 
26564 	DUK_ASSERT_TOP(thr, 5);
26565 	return 1;
26566 }
26567 
26568 /*
26569  *  shift()
26570  */
26571 
duk_bi_array_prototype_shift(duk_hthread * thr)26572 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_shift(duk_hthread *thr) {
26573 	duk_uint32_t len;
26574 	duk_uint32_t i;
26575 
26576 	len = duk__push_this_obj_len_u32(thr);
26577 	if (len == 0) {
26578 		duk_push_int(thr, 0);
26579 		duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
26580 		return 0;
26581 	}
26582 
26583 	duk_get_prop_index(thr, 0, 0);
26584 
26585 	/* stack[0] = object (this)
26586 	 * stack[1] = ToUint32(length)
26587 	 * stack[2] = elem at index 0 (retval)
26588 	 */
26589 
26590 	for (i = 1; i < len; i++) {
26591 		DUK_ASSERT_TOP(thr, 3);
26592 		if (duk_get_prop_index(thr, 0, (duk_uarridx_t) i)) {
26593 			/* fromPresent = true */
26594 			duk_put_prop_index(thr, 0, (duk_uarridx_t) (i - 1));
26595 		} else {
26596 			/* fromPresent = false */
26597 			duk_del_prop_index(thr, 0, (duk_uarridx_t) (i - 1));
26598 			duk_pop_undefined(thr);
26599 		}
26600 	}
26601 	duk_del_prop_index(thr, 0, (duk_uarridx_t) (len - 1));
26602 
26603 	duk_push_u32(thr, (duk_uint32_t) (len - 1));
26604 	duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
26605 
26606 	DUK_ASSERT_TOP(thr, 3);
26607 	return 1;
26608 }
26609 
26610 /*
26611  *  unshift()
26612  */
26613 
duk_bi_array_prototype_unshift(duk_hthread * thr)26614 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_unshift(duk_hthread *thr) {
26615 	duk_idx_t nargs;
26616 	duk_uint32_t len;
26617 	duk_uint32_t i;
26618 
26619 	nargs = duk_get_top(thr);
26620 	len = duk__push_this_obj_len_u32(thr);
26621 
26622 	/* stack[0...nargs-1] = unshift args (vararg)
26623 	 * stack[nargs] = ToObject(this)
26624 	 * stack[nargs+1] = ToUint32(length)
26625 	 */
26626 
26627 	DUK_ASSERT_TOP(thr, nargs + 2);
26628 
26629 	/* Note: unshift() may operate on indices above unsigned 32-bit range
26630 	 * and the final length may be >= 2**32.  However, we restrict the
26631 	 * final result to 32-bit range for practicality.
26632 	 */
26633 
26634 	if (len + (duk_uint32_t) nargs < len) {
26635 		DUK_D(DUK_DPRINT("Array.prototype.unshift() would go beyond 32-bit length, throw"));
26636 		DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
26637 	}
26638 
26639 	i = len;
26640 	while (i > 0) {
26641 		DUK_ASSERT_TOP(thr, nargs + 2);
26642 		i--;
26643 		/* k+argCount-1; note that may be above 32-bit range */
26644 
26645 		if (duk_get_prop_index(thr, -2, (duk_uarridx_t) i)) {
26646 			/* fromPresent = true */
26647 			/* [ ... ToObject(this) ToUint32(length) val ] */
26648 			duk_put_prop_index(thr, -3, (duk_uarridx_t) (i + (duk_uint32_t) nargs));  /* -> [ ... ToObject(this) ToUint32(length) ] */
26649 		} else {
26650 			/* fromPresent = false */
26651 			/* [ ... ToObject(this) ToUint32(length) val ] */
26652 			duk_pop_undefined(thr);
26653 			duk_del_prop_index(thr, -2, (duk_uarridx_t) (i + (duk_uint32_t) nargs));  /* -> [ ... ToObject(this) ToUint32(length) ] */
26654 		}
26655 		DUK_ASSERT_TOP(thr, nargs + 2);
26656 	}
26657 
26658 	for (i = 0; i < (duk_uint32_t) nargs; i++) {
26659 		DUK_ASSERT_TOP(thr, nargs + 2);
26660 		duk_dup(thr, (duk_idx_t) i);  /* -> [ ... ToObject(this) ToUint32(length) arg[i] ] */
26661 		duk_put_prop_index(thr, -3, (duk_uarridx_t) i);
26662 		DUK_ASSERT_TOP(thr, nargs + 2);
26663 	}
26664 
26665 	DUK_ASSERT_TOP(thr, nargs + 2);
26666 	duk_push_u32(thr, len + (duk_uint32_t) nargs);
26667 	duk_dup_top(thr);  /* -> [ ... ToObject(this) ToUint32(length) final_len final_len ] */
26668 	duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_LENGTH);
26669 	return 1;
26670 }
26671 
26672 /*
26673  *  indexOf(), lastIndexOf()
26674  */
26675 
duk_bi_array_prototype_indexof_shared(duk_hthread * thr)26676 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_hthread *thr) {
26677 	duk_idx_t nargs;
26678 	duk_int_t i, len;
26679 	duk_int_t from_idx;
26680 	duk_small_int_t idx_step = duk_get_current_magic(thr);  /* idx_step is +1 for indexOf, -1 for lastIndexOf */
26681 
26682 	/* lastIndexOf() needs to be a vararg function because we must distinguish
26683 	 * between an undefined fromIndex and a "not given" fromIndex; indexOf() is
26684 	 * made vararg for symmetry although it doesn't strictly need to be.
26685 	 */
26686 
26687 	nargs = duk_get_top(thr);
26688 	duk_set_top(thr, 2);
26689 
26690 	/* XXX: must be able to represent -len */
26691 	len = (duk_int_t) duk__push_this_obj_len_u32_limited(thr);
26692 	if (len == 0) {
26693 		goto not_found;
26694 	}
26695 
26696 	/* Index clamping is a bit tricky, we must ensure that we'll only iterate
26697 	 * through elements that exist and that the specific requirements from E5.1
26698 	 * Sections 15.4.4.14 and 15.4.4.15 are fulfilled; especially:
26699 	 *
26700 	 *   - indexOf: clamp to [-len,len], negative handling -> [0,len],
26701 	 *     if clamped result is len, for-loop bails out immediately
26702 	 *
26703 	 *   - lastIndexOf: clamp to [-len-1, len-1], negative handling -> [-1, len-1],
26704 	 *     if clamped result is -1, for-loop bails out immediately
26705 	 *
26706 	 * If fromIndex is not given, ToInteger(undefined) = 0, which is correct
26707 	 * for indexOf() but incorrect for lastIndexOf().  Hence special handling,
26708 	 * and why lastIndexOf() needs to be a vararg function.
26709 	 */
26710 
26711 	if (nargs >= 2) {
26712 		/* indexOf: clamp fromIndex to [-len, len]
26713 		 * (if fromIndex == len, for-loop terminates directly)
26714 		 *
26715 		 * lastIndexOf: clamp fromIndex to [-len - 1, len - 1]
26716 		 * (if clamped to -len-1 -> fromIndex becomes -1, terminates for-loop directly)
26717 		 */
26718 		from_idx = duk_to_int_clamped(thr,
26719 		                              1,
26720 		                              (idx_step > 0 ? -len : -len - 1),
26721 		                              (idx_step > 0 ? len : len - 1));
26722 		if (from_idx < 0) {
26723 			/* for lastIndexOf, result may be -1 (mark immediate termination) */
26724 			from_idx = len + from_idx;
26725 		}
26726 	} else {
26727 		/* for indexOf, ToInteger(undefined) would be 0, i.e. correct, but
26728 		 * handle both indexOf and lastIndexOf specially here.
26729 		 */
26730 		if (idx_step > 0) {
26731 			from_idx = 0;
26732 		} else {
26733 			from_idx = len - 1;
26734 		}
26735 	}
26736 
26737 	/* stack[0] = searchElement
26738 	 * stack[1] = fromIndex
26739 	 * stack[2] = object
26740 	 * stack[3] = length (not needed, but not popped above)
26741 	 */
26742 
26743 	for (i = from_idx; i >= 0 && i < len; i += idx_step) {
26744 		DUK_ASSERT_TOP(thr, 4);
26745 
26746 		if (duk_get_prop_index(thr, 2, (duk_uarridx_t) i)) {
26747 			DUK_ASSERT_TOP(thr, 5);
26748 			if (duk_strict_equals(thr, 0, 4)) {
26749 				duk_push_int(thr, i);
26750 				return 1;
26751 			}
26752 		}
26753 
26754 		duk_pop_unsafe(thr);
26755 	}
26756 
26757  not_found:
26758 	duk_push_int(thr, -1);
26759 	return 1;
26760 }
26761 
26762 /*
26763  *  every(), some(), forEach(), map(), filter()
26764  */
26765 
26766 #define DUK__ITER_EVERY    0
26767 #define DUK__ITER_SOME     1
26768 #define DUK__ITER_FOREACH  2
26769 #define DUK__ITER_MAP      3
26770 #define DUK__ITER_FILTER   4
26771 
26772 /* XXX: This helper is a bit awkward because the handling for the different iteration
26773  * callers is quite different.  This now compiles to a bit less than 500 bytes, so with
26774  * 5 callers the net result is about 100 bytes / caller.
26775  */
26776 
duk_bi_array_prototype_iter_shared(duk_hthread * thr)26777 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_iter_shared(duk_hthread *thr) {
26778 	duk_uint32_t len;
26779 	duk_uint32_t i;
26780 	duk_uarridx_t k;
26781 	duk_bool_t bval;
26782 	duk_small_int_t iter_type = duk_get_current_magic(thr);
26783 	duk_uint32_t res_length = 0;
26784 
26785 	/* each call this helper serves has nargs==2 */
26786 	DUK_ASSERT_TOP(thr, 2);
26787 
26788 	len = duk__push_this_obj_len_u32(thr);
26789 	duk_require_callable(thr, 0);
26790 	/* if thisArg not supplied, behave as if undefined was supplied */
26791 
26792 	if (iter_type == DUK__ITER_MAP || iter_type == DUK__ITER_FILTER) {
26793 		duk_push_array(thr);
26794 	} else {
26795 		duk_push_undefined(thr);
26796 	}
26797 
26798 	/* stack[0] = callback
26799 	 * stack[1] = thisArg
26800 	 * stack[2] = object
26801 	 * stack[3] = ToUint32(length)  (unused, but avoid unnecessary pop)
26802 	 * stack[4] = result array (or undefined)
26803 	 */
26804 
26805 	k = 0;  /* result index for filter() */
26806 	for (i = 0; i < len; i++) {
26807 		DUK_ASSERT_TOP(thr, 5);
26808 
26809 		if (!duk_get_prop_index(thr, 2, (duk_uarridx_t) i)) {
26810 			/* For 'map' trailing missing elements don't invoke the
26811 			 * callback but count towards the result length.
26812 			 */
26813 			if (iter_type == DUK__ITER_MAP) {
26814 				res_length = i + 1;
26815 			}
26816 			duk_pop_undefined(thr);
26817 			continue;
26818 		}
26819 
26820 		/* The original value needs to be preserved for filter(), hence
26821 		 * this funny order.  We can't re-get the value because of side
26822 		 * effects.
26823 		 */
26824 
26825 		duk_dup_0(thr);
26826 		duk_dup_1(thr);
26827 		duk_dup_m3(thr);
26828 		duk_push_u32(thr, i);
26829 		duk_dup_2(thr);  /* [ ... val callback thisArg val i obj ] */
26830 		duk_call_method(thr, 3); /* -> [ ... val retval ] */
26831 
26832 		switch (iter_type) {
26833 		case DUK__ITER_EVERY:
26834 			bval = duk_to_boolean(thr, -1);
26835 			if (!bval) {
26836 				/* stack top contains 'false' */
26837 				return 1;
26838 			}
26839 			break;
26840 		case DUK__ITER_SOME:
26841 			bval = duk_to_boolean(thr, -1);
26842 			if (bval) {
26843 				/* stack top contains 'true' */
26844 				return 1;
26845 			}
26846 			break;
26847 		case DUK__ITER_FOREACH:
26848 			/* nop */
26849 			break;
26850 		case DUK__ITER_MAP:
26851 			duk_dup_top(thr);
26852 			duk_xdef_prop_index_wec(thr, 4, (duk_uarridx_t) i);  /* retval to result[i] */
26853 			res_length = i + 1;
26854 			break;
26855 		case DUK__ITER_FILTER:
26856 			bval = duk_to_boolean(thr, -1);
26857 			if (bval) {
26858 				duk_dup_m2(thr);  /* orig value */
26859 				duk_xdef_prop_index_wec(thr, 4, (duk_uarridx_t) k);
26860 				k++;
26861 				res_length = k;
26862 			}
26863 			break;
26864 		default:
26865 			DUK_UNREACHABLE();
26866 			break;
26867 		}
26868 		duk_pop_2_unsafe(thr);
26869 
26870 		DUK_ASSERT_TOP(thr, 5);
26871 	}
26872 
26873 	switch (iter_type) {
26874 	case DUK__ITER_EVERY:
26875 		duk_push_true(thr);
26876 		break;
26877 	case DUK__ITER_SOME:
26878 		duk_push_false(thr);
26879 		break;
26880 	case DUK__ITER_FOREACH:
26881 		duk_push_undefined(thr);
26882 		break;
26883 	case DUK__ITER_MAP:
26884 	case DUK__ITER_FILTER:
26885 		DUK_ASSERT_TOP(thr, 5);
26886 		DUK_ASSERT(duk_is_array(thr, -1));  /* topmost element is the result array already */
26887 		duk_push_u32(thr, res_length);
26888 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
26889 		break;
26890 	default:
26891 		DUK_UNREACHABLE();
26892 		break;
26893 	}
26894 
26895 	return 1;
26896 }
26897 
26898 /*
26899  *  reduce(), reduceRight()
26900  */
26901 
duk_bi_array_prototype_reduce_shared(duk_hthread * thr)26902 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_hthread *thr) {
26903 	duk_idx_t nargs;
26904 	duk_bool_t have_acc;
26905 	duk_uint32_t i, len;
26906 	duk_small_int_t idx_step = duk_get_current_magic(thr);  /* idx_step is +1 for reduce, -1 for reduceRight */
26907 
26908 	/* We're a varargs function because we need to detect whether
26909 	 * initialValue was given or not.
26910 	 */
26911 	nargs = duk_get_top(thr);
26912 	DUK_DDD(DUK_DDDPRINT("nargs=%ld", (long) nargs));
26913 
26914 	duk_set_top(thr, 2);
26915 	len = duk__push_this_obj_len_u32(thr);
26916 	duk_require_callable(thr, 0);
26917 
26918 	/* stack[0] = callback fn
26919 	 * stack[1] = initialValue
26920 	 * stack[2] = object (coerced this)
26921 	 * stack[3] = length (not needed, but not popped above)
26922 	 * stack[4] = accumulator
26923 	 */
26924 
26925 	have_acc = 0;
26926 	if (nargs >= 2) {
26927 		duk_dup_1(thr);
26928 		have_acc = 1;
26929 	}
26930 	DUK_DDD(DUK_DDDPRINT("have_acc=%ld, acc=%!T",
26931 	                     (long) have_acc, (duk_tval *) duk_get_tval(thr, 3)));
26932 
26933 	/* For len == 0, i is initialized to len - 1 which underflows.
26934 	 * The condition (i < len) will then exit the for-loop on the
26935 	 * first round which is correct.  Similarly, loop termination
26936 	 * happens by i underflowing.
26937 	 */
26938 
26939 	for (i = (idx_step >= 0 ? 0 : len - 1);
26940 	     i < len;  /* i >= 0 would always be true */
26941 	     i += (duk_uint32_t) idx_step) {
26942 		DUK_DDD(DUK_DDDPRINT("i=%ld, len=%ld, have_acc=%ld, top=%ld, acc=%!T",
26943 		                     (long) i, (long) len, (long) have_acc,
26944 		                     (long) duk_get_top(thr),
26945 		                     (duk_tval *) duk_get_tval(thr, 4)));
26946 
26947 		DUK_ASSERT((have_acc && duk_get_top(thr) == 5) ||
26948 		           (!have_acc && duk_get_top(thr) == 4));
26949 
26950 		if (!duk_has_prop_index(thr, 2, (duk_uarridx_t) i)) {
26951 			continue;
26952 		}
26953 
26954 		if (!have_acc) {
26955 			DUK_ASSERT_TOP(thr, 4);
26956 			duk_get_prop_index(thr, 2, (duk_uarridx_t) i);
26957 			have_acc = 1;
26958 			DUK_ASSERT_TOP(thr, 5);
26959 		} else {
26960 			DUK_ASSERT_TOP(thr, 5);
26961 			duk_dup_0(thr);
26962 			duk_dup(thr, 4);
26963 			duk_get_prop_index(thr, 2, (duk_uarridx_t) i);
26964 			duk_push_u32(thr, i);
26965 			duk_dup_2(thr);
26966 			DUK_DDD(DUK_DDDPRINT("calling reduce function: func=%!T, prev=%!T, curr=%!T, idx=%!T, obj=%!T",
26967 			                     (duk_tval *) duk_get_tval(thr, -5), (duk_tval *) duk_get_tval(thr, -4),
26968 			                     (duk_tval *) duk_get_tval(thr, -3), (duk_tval *) duk_get_tval(thr, -2),
26969 			                     (duk_tval *) duk_get_tval(thr, -1)));
26970 			duk_call(thr, 4);
26971 			DUK_DDD(DUK_DDDPRINT("-> result: %!T", (duk_tval *) duk_get_tval(thr, -1)));
26972 			duk_replace(thr, 4);
26973 			DUK_ASSERT_TOP(thr, 5);
26974 		}
26975 	}
26976 
26977 	if (!have_acc) {
26978 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
26979 	}
26980 
26981 	DUK_ASSERT_TOP(thr, 5);
26982 	return 1;
26983 }
26984 
26985 #endif  /* DUK_USE_ARRAY_BUILTIN */
26986 
26987 /* automatic undefs */
26988 #undef DUK__ARRAY_MID_JOIN_LIMIT
26989 #undef DUK__ITER_EVERY
26990 #undef DUK__ITER_FILTER
26991 #undef DUK__ITER_FOREACH
26992 #undef DUK__ITER_MAP
26993 #undef DUK__ITER_SOME
26994 /*
26995  *  Boolean built-ins
26996  */
26997 
26998 /* #include duk_internal.h -> already included */
26999 
27000 #if defined(DUK_USE_BOOLEAN_BUILTIN)
27001 
27002 /* Shared helper to provide toString() and valueOf().  Checks 'this', gets
27003  * the primitive value to stack top, and optionally coerces with ToString().
27004  */
duk_bi_boolean_prototype_tostring_shared(duk_hthread * thr)27005 DUK_INTERNAL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_hthread *thr) {
27006 	duk_tval *tv;
27007 	duk_hobject *h;
27008 	duk_small_int_t coerce_tostring = duk_get_current_magic(thr);
27009 
27010 	/* XXX: there is room to use a shared helper here, many built-ins
27011 	 * check the 'this' type, and if it's an object, check its class,
27012 	 * then get its internal value, etc.
27013 	 */
27014 
27015 	duk_push_this(thr);
27016 	tv = duk_get_tval(thr, -1);
27017 	DUK_ASSERT(tv != NULL);
27018 
27019 	if (DUK_TVAL_IS_BOOLEAN(tv)) {
27020 		goto type_ok;
27021 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
27022 		h = DUK_TVAL_GET_OBJECT(tv);
27023 		DUK_ASSERT(h != NULL);
27024 
27025 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_BOOLEAN) {
27026 			duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
27027 			DUK_ASSERT(duk_is_boolean(thr, -1));
27028 			goto type_ok;
27029 		}
27030 	}
27031 
27032 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
27033 	/* never here */
27034 
27035  type_ok:
27036 	if (coerce_tostring) {
27037 		duk_to_string(thr, -1);
27038 	}
27039 	return 1;
27040 }
27041 
duk_bi_boolean_constructor(duk_hthread * thr)27042 DUK_INTERNAL duk_ret_t duk_bi_boolean_constructor(duk_hthread *thr) {
27043 	duk_hobject *h_this;
27044 
27045 	duk_to_boolean(thr, 0);
27046 
27047 	if (duk_is_constructor_call(thr)) {
27048 		/* XXX: helper; rely on Boolean.prototype as being non-writable, non-configurable */
27049 		duk_push_this(thr);
27050 		h_this = duk_known_hobject(thr, -1);
27051 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_this) == thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE]);
27052 
27053 		DUK_HOBJECT_SET_CLASS_NUMBER(h_this, DUK_HOBJECT_CLASS_BOOLEAN);
27054 
27055 		duk_dup_0(thr);  /* -> [ val obj val ] */
27056 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);  /* XXX: proper flags? */
27057 	}  /* unbalanced stack */
27058 
27059 	return 1;
27060 }
27061 
27062 #endif  /* DUK_USE_BOOLEAN_BUILTIN */
27063 /*
27064  *  ES2015 TypedArray and Node.js Buffer built-ins
27065  */
27066 
27067 /* #include duk_internal.h -> already included */
27068 
27069 /*
27070  *  Helpers for buffer handling, enabled with DUK_USE_BUFFEROBJECT_SUPPORT.
27071  */
27072 
27073 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
27074 /* Map class number (minus DUK_HOBJECT_CLASS_BUFOBJ_MIN) to a bidx for the
27075  * default internal prototype.
27076  */
27077 static const duk_uint8_t duk__buffer_proto_from_classnum[] = {
27078 	DUK_BIDX_ARRAYBUFFER_PROTOTYPE,
27079 	DUK_BIDX_DATAVIEW_PROTOTYPE,
27080 	DUK_BIDX_INT8ARRAY_PROTOTYPE,
27081 	DUK_BIDX_UINT8ARRAY_PROTOTYPE,
27082 	DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE,
27083 	DUK_BIDX_INT16ARRAY_PROTOTYPE,
27084 	DUK_BIDX_UINT16ARRAY_PROTOTYPE,
27085 	DUK_BIDX_INT32ARRAY_PROTOTYPE,
27086 	DUK_BIDX_UINT32ARRAY_PROTOTYPE,
27087 	DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,
27088 	DUK_BIDX_FLOAT64ARRAY_PROTOTYPE
27089 };
27090 
27091 /* Map DUK_HBUFOBJ_ELEM_xxx to duk_hobject class number.
27092  * Sync with duk_hbufobj.h and duk_hobject.h.
27093  */
27094 static const duk_uint8_t duk__buffer_class_from_elemtype[9] = {
27095 	DUK_HOBJECT_CLASS_UINT8ARRAY,
27096 	DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY,
27097 	DUK_HOBJECT_CLASS_INT8ARRAY,
27098 	DUK_HOBJECT_CLASS_UINT16ARRAY,
27099 	DUK_HOBJECT_CLASS_INT16ARRAY,
27100 	DUK_HOBJECT_CLASS_UINT32ARRAY,
27101 	DUK_HOBJECT_CLASS_INT32ARRAY,
27102 	DUK_HOBJECT_CLASS_FLOAT32ARRAY,
27103 	DUK_HOBJECT_CLASS_FLOAT64ARRAY
27104 };
27105 
27106 /* Map DUK_HBUFOBJ_ELEM_xxx to prototype object built-in index.
27107  * Sync with duk_hbufobj.h.
27108  */
27109 static const duk_uint8_t duk__buffer_proto_from_elemtype[9] = {
27110 	DUK_BIDX_UINT8ARRAY_PROTOTYPE,
27111 	DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE,
27112 	DUK_BIDX_INT8ARRAY_PROTOTYPE,
27113 	DUK_BIDX_UINT16ARRAY_PROTOTYPE,
27114 	DUK_BIDX_INT16ARRAY_PROTOTYPE,
27115 	DUK_BIDX_UINT32ARRAY_PROTOTYPE,
27116 	DUK_BIDX_INT32ARRAY_PROTOTYPE,
27117 	DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,
27118 	DUK_BIDX_FLOAT64ARRAY_PROTOTYPE
27119 };
27120 
27121 /* Map DUK__FLD_xxx to byte size. */
27122 static const duk_uint8_t duk__buffer_nbytes_from_fldtype[6] = {
27123 	1,  /* DUK__FLD_8BIT */
27124 	2,  /* DUK__FLD_16BIT */
27125 	4,  /* DUK__FLD_32BIT */
27126 	4,  /* DUK__FLD_FLOAT */
27127 	8,  /* DUK__FLD_DOUBLE */
27128 	0   /* DUK__FLD_VARINT; not relevant here */
27129 };
27130 
27131 /* Bitfield for each DUK_HBUFOBJ_ELEM_xxx indicating which element types
27132  * are compatible with a blind byte copy for the TypedArray set() method (also
27133  * used for TypedArray constructor).  Array index is target buffer elem type,
27134  * bitfield indicates compatible source types.  The types must have same byte
27135  * size and they must be coercion compatible.
27136  */
27137 #if !defined(DUK_USE_PREFER_SIZE)
27138 static duk_uint16_t duk__buffer_elemtype_copy_compatible[9] = {
27139 	/* xxx -> DUK_HBUFOBJ_ELEM_UINT8 */
27140 	(1U << DUK_HBUFOBJ_ELEM_UINT8) |
27141 		(1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED) |
27142 		(1U << DUK_HBUFOBJ_ELEM_INT8),
27143 
27144 	/* xxx -> DUK_HBUFOBJ_ELEM_UINT8CLAMPED
27145 	 * Note: INT8 is -not- copy compatible, e.g. -1 would coerce to 0x00.
27146 	 */
27147 	(1U << DUK_HBUFOBJ_ELEM_UINT8) |
27148 		(1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED),
27149 
27150 	/* xxx -> DUK_HBUFOBJ_ELEM_INT8 */
27151 	(1U << DUK_HBUFOBJ_ELEM_UINT8) |
27152 		(1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED) |
27153 		(1U << DUK_HBUFOBJ_ELEM_INT8),
27154 
27155 	/* xxx -> DUK_HBUFOBJ_ELEM_UINT16 */
27156 	(1U << DUK_HBUFOBJ_ELEM_UINT16) |
27157 		(1U << DUK_HBUFOBJ_ELEM_INT16),
27158 
27159 	/* xxx -> DUK_HBUFOBJ_ELEM_INT16 */
27160 	(1U << DUK_HBUFOBJ_ELEM_UINT16) |
27161 		(1U << DUK_HBUFOBJ_ELEM_INT16),
27162 
27163 	/* xxx -> DUK_HBUFOBJ_ELEM_UINT32 */
27164 	(1U << DUK_HBUFOBJ_ELEM_UINT32) |
27165 		(1U << DUK_HBUFOBJ_ELEM_INT32),
27166 
27167 	/* xxx -> DUK_HBUFOBJ_ELEM_INT32 */
27168 	(1U << DUK_HBUFOBJ_ELEM_UINT32) |
27169 		(1U << DUK_HBUFOBJ_ELEM_INT32),
27170 
27171 	/* xxx -> DUK_HBUFOBJ_ELEM_FLOAT32 */
27172 	(1U << DUK_HBUFOBJ_ELEM_FLOAT32),
27173 
27174 	/* xxx -> DUK_HBUFOBJ_ELEM_FLOAT64 */
27175 	(1U << DUK_HBUFOBJ_ELEM_FLOAT64)
27176 };
27177 #endif  /* !DUK_USE_PREFER_SIZE */
27178 
duk__hbufobj_promote_this(duk_hthread * thr)27179 DUK_LOCAL duk_hbufobj *duk__hbufobj_promote_this(duk_hthread *thr) {
27180 	duk_tval *tv_dst;
27181 	duk_hbufobj *res;
27182 
27183 	duk_push_this(thr);
27184 	DUK_ASSERT(duk_is_buffer(thr, -1));
27185 	res = (duk_hbufobj *) duk_to_hobject(thr, -1);
27186 	DUK_HBUFOBJ_ASSERT_VALID(res);
27187 	DUK_DD(DUK_DDPRINT("promoted 'this' automatically to an ArrayBuffer: %!iT", duk_get_tval(thr, -1)));
27188 
27189 	tv_dst = duk_get_borrowed_this_tval(thr);
27190 	DUK_TVAL_SET_OBJECT_UPDREF(thr, tv_dst, (duk_hobject *) res);
27191 	duk_pop(thr);
27192 
27193 	return res;
27194 }
27195 
27196 #define DUK__BUFOBJ_FLAG_THROW    (1 << 0)
27197 #define DUK__BUFOBJ_FLAG_PROMOTE  (1 << 1)
27198 
27199 /* Shared helper.  When DUK__BUFOBJ_FLAG_PROMOTE is given, the return value is
27200  * always a duk_hbufobj *.  Without the flag the return value can also be a
27201  * plain buffer, and the caller must check for it using DUK_HEAPHDR_IS_BUFFER().
27202  */
duk__getrequire_bufobj_this(duk_hthread * thr,duk_small_uint_t flags)27203 DUK_LOCAL duk_heaphdr *duk__getrequire_bufobj_this(duk_hthread *thr, duk_small_uint_t flags) {
27204 	duk_tval *tv;
27205 	duk_hbufobj *h_this;
27206 
27207 	DUK_ASSERT(thr != NULL);
27208 
27209 	tv = duk_get_borrowed_this_tval(thr);
27210 	DUK_ASSERT(tv != NULL);
27211 
27212 	if (DUK_TVAL_IS_OBJECT(tv)) {
27213 		h_this = (duk_hbufobj *) DUK_TVAL_GET_OBJECT(tv);
27214 		DUK_ASSERT(h_this != NULL);
27215 		if (DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) h_this)) {
27216 			DUK_HBUFOBJ_ASSERT_VALID(h_this);
27217 			return (duk_heaphdr *) h_this;
27218 		}
27219 	} else if (DUK_TVAL_IS_BUFFER(tv)) {
27220 		if (flags & DUK__BUFOBJ_FLAG_PROMOTE) {
27221 			/* Promote a plain buffer to a Uint8Array.  This is very
27222 			 * inefficient but allows plain buffer to be used wherever an
27223 			 * Uint8Array is used with very small cost; hot path functions
27224 			 * like index read/write calls should provide direct buffer
27225 			 * support to avoid promotion.
27226 			 */
27227 			/* XXX: make this conditional to a flag if call sites need it? */
27228 			h_this = duk__hbufobj_promote_this(thr);
27229 			DUK_ASSERT(h_this != NULL);
27230 			DUK_HBUFOBJ_ASSERT_VALID(h_this);
27231 			return (duk_heaphdr *) h_this;
27232 		} else {
27233 			/* XXX: ugly, share return pointer for duk_hbuffer. */
27234 			return (duk_heaphdr *) DUK_TVAL_GET_BUFFER(tv);
27235 		}
27236 	}
27237 
27238 	if (flags & DUK__BUFOBJ_FLAG_THROW) {
27239 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_BUFFER);
27240 		DUK_WO_NORETURN(return NULL;);
27241 	}
27242 	return NULL;
27243 }
27244 
27245 /* Check that 'this' is a duk_hbufobj and return a pointer to it. */
duk__get_bufobj_this(duk_hthread * thr)27246 DUK_LOCAL duk_hbufobj *duk__get_bufobj_this(duk_hthread *thr) {
27247 	return (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_PROMOTE);
27248 }
27249 
27250 /* Check that 'this' is a duk_hbufobj and return a pointer to it
27251  * (NULL if not).
27252  */
duk__require_bufobj_this(duk_hthread * thr)27253 DUK_LOCAL duk_hbufobj *duk__require_bufobj_this(duk_hthread *thr) {
27254 	return (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW | DUK__BUFOBJ_FLAG_PROMOTE);
27255 }
27256 
27257 /* Check that value is a duk_hbufobj and return a pointer to it. */
duk__require_bufobj_value(duk_hthread * thr,duk_idx_t idx)27258 DUK_LOCAL duk_hbufobj *duk__require_bufobj_value(duk_hthread *thr, duk_idx_t idx) {
27259 	duk_tval *tv;
27260 	duk_hbufobj *h_obj;
27261 
27262 	/* Don't accept relative indices now. */
27263 	DUK_ASSERT(idx >= 0);
27264 
27265 	tv = duk_require_tval(thr, idx);
27266 	DUK_ASSERT(tv != NULL);
27267 	if (DUK_TVAL_IS_OBJECT(tv)) {
27268 		h_obj = (duk_hbufobj *) DUK_TVAL_GET_OBJECT(tv);
27269 		DUK_ASSERT(h_obj != NULL);
27270 		if (DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) h_obj)) {
27271 			DUK_HBUFOBJ_ASSERT_VALID(h_obj);
27272 			return h_obj;
27273 		}
27274 	} else if (DUK_TVAL_IS_BUFFER(tv)) {
27275 		h_obj = (duk_hbufobj *) duk_to_hobject(thr, idx);
27276 		DUK_ASSERT(h_obj != NULL);
27277 		DUK_HBUFOBJ_ASSERT_VALID(h_obj);
27278 		return h_obj;
27279 	}
27280 
27281 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_BUFFER);
27282 	DUK_WO_NORETURN(return NULL;);
27283 }
27284 
duk__set_bufobj_buffer(duk_hthread * thr,duk_hbufobj * h_bufobj,duk_hbuffer * h_val)27285 DUK_LOCAL void duk__set_bufobj_buffer(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_hbuffer *h_val) {
27286 	DUK_ASSERT(thr != NULL);
27287 	DUK_ASSERT(h_bufobj != NULL);
27288 	DUK_ASSERT(h_bufobj->buf == NULL);  /* no need to decref */
27289 	DUK_ASSERT(h_val != NULL);
27290 	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
27291 	DUK_UNREF(thr);
27292 
27293 	h_bufobj->buf = h_val;
27294 	DUK_HBUFFER_INCREF(thr, h_val);
27295 	h_bufobj->length = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_val);
27296 	DUK_ASSERT(h_bufobj->shift == 0);
27297 	DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFOBJ_ELEM_UINT8);
27298 	DUK_ASSERT(h_bufobj->is_typedarray == 0);
27299 
27300 	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
27301 }
27302 
27303 /* Shared offset/length coercion helper. */
duk__resolve_offset_opt_length(duk_hthread * thr,duk_hbufobj * h_bufarg,duk_idx_t idx_offset,duk_idx_t idx_length,duk_uint_t * out_offset,duk_uint_t * out_length,duk_bool_t throw_flag)27304 DUK_LOCAL void duk__resolve_offset_opt_length(duk_hthread *thr,
27305                                               duk_hbufobj *h_bufarg,
27306                                               duk_idx_t idx_offset,
27307                                               duk_idx_t idx_length,
27308                                               duk_uint_t *out_offset,
27309                                               duk_uint_t *out_length,
27310                                               duk_bool_t throw_flag) {
27311 	duk_int_t offset_signed;
27312 	duk_int_t length_signed;
27313 	duk_uint_t offset;
27314 	duk_uint_t length;
27315 
27316 	offset_signed = duk_to_int(thr, idx_offset);
27317 	if (offset_signed < 0) {
27318 		goto fail_range;
27319 	}
27320 	offset = (duk_uint_t) offset_signed;
27321 	if (offset > h_bufarg->length) {
27322 		goto fail_range;
27323 	}
27324 	DUK_ASSERT_DISABLE(offset >= 0);  /* unsigned */
27325 	DUK_ASSERT(offset <= h_bufarg->length);
27326 
27327 	if (duk_is_undefined(thr, idx_length)) {
27328 		DUK_ASSERT(h_bufarg->length >= offset);
27329 		length = h_bufarg->length - offset;  /* >= 0 */
27330 	} else {
27331 		length_signed = duk_to_int(thr, idx_length);
27332 		if (length_signed < 0) {
27333 			goto fail_range;
27334 		}
27335 		length = (duk_uint_t) length_signed;
27336 		DUK_ASSERT(h_bufarg->length >= offset);
27337 		if (length > h_bufarg->length - offset) {
27338 			/* Unlike for negative arguments, some call sites
27339 			 * want length to be clamped if it's positive.
27340 			 */
27341 			if (throw_flag) {
27342 				goto fail_range;
27343 			} else {
27344 				length = h_bufarg->length - offset;
27345 			}
27346 		}
27347 	}
27348 	DUK_ASSERT_DISABLE(length >= 0);  /* unsigned */
27349 	DUK_ASSERT(offset + length <= h_bufarg->length);
27350 
27351 	*out_offset = offset;
27352 	*out_length = length;
27353 	return;
27354 
27355  fail_range:
27356 	DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARGS);
27357 	DUK_WO_NORETURN(return;);
27358 }
27359 
27360 /* Shared lenient buffer length clamping helper.  No negative indices, no
27361  * element/byte shifting.
27362  */
duk__clamp_startend_nonegidx_noshift(duk_hthread * thr,duk_int_t buffer_length,duk_idx_t idx_start,duk_idx_t idx_end,duk_int_t * out_start_offset,duk_int_t * out_end_offset)27363 DUK_LOCAL void duk__clamp_startend_nonegidx_noshift(duk_hthread *thr,
27364                                                     duk_int_t buffer_length,
27365                                                     duk_idx_t idx_start,
27366                                                     duk_idx_t idx_end,
27367                                                     duk_int_t *out_start_offset,
27368                                                     duk_int_t *out_end_offset) {
27369 	duk_int_t start_offset;
27370 	duk_int_t end_offset;
27371 
27372 	DUK_ASSERT(out_start_offset != NULL);
27373 	DUK_ASSERT(out_end_offset != NULL);
27374 
27375 	/* undefined coerces to zero which is correct */
27376 	start_offset = duk_to_int_clamped(thr, idx_start, 0, buffer_length);
27377 	if (duk_is_undefined(thr, idx_end)) {
27378 		end_offset = buffer_length;
27379 	} else {
27380 		end_offset = duk_to_int_clamped(thr, idx_end, start_offset, buffer_length);
27381 	}
27382 
27383 	DUK_ASSERT(start_offset >= 0);
27384 	DUK_ASSERT(start_offset <= buffer_length);
27385 	DUK_ASSERT(end_offset >= 0);
27386 	DUK_ASSERT(end_offset <= buffer_length);
27387 	DUK_ASSERT(start_offset <= end_offset);
27388 
27389 	*out_start_offset = start_offset;
27390 	*out_end_offset = end_offset;
27391 }
27392 
27393 /* Shared lenient buffer length clamping helper.  Indices are treated as
27394  * element indices (though output values are byte offsets) which only
27395  * really matters for TypedArray views as other buffer object have a zero
27396  * shift.  Negative indices are counted from end of input slice; crossed
27397  * indices are clamped to zero length; and final indices are clamped
27398  * against input slice.  Used for e.g. ArrayBuffer slice().
27399  */
duk__clamp_startend_negidx_shifted(duk_hthread * thr,duk_int_t buffer_length,duk_uint8_t buffer_shift,duk_idx_t idx_start,duk_idx_t idx_end,duk_int_t * out_start_offset,duk_int_t * out_end_offset)27400 DUK_LOCAL void duk__clamp_startend_negidx_shifted(duk_hthread *thr,
27401                                                   duk_int_t buffer_length,
27402                                                   duk_uint8_t buffer_shift,
27403                                                   duk_idx_t idx_start,
27404                                                   duk_idx_t idx_end,
27405                                                   duk_int_t *out_start_offset,
27406                                                   duk_int_t *out_end_offset) {
27407 	duk_int_t start_offset;
27408 	duk_int_t end_offset;
27409 
27410 	DUK_ASSERT(out_start_offset != NULL);
27411 	DUK_ASSERT(out_end_offset != NULL);
27412 
27413 	buffer_length >>= buffer_shift;  /* as (full) elements */
27414 
27415 	/* Resolve start/end offset as element indices first; arguments
27416 	 * at idx_start/idx_end are element offsets.  Working with element
27417 	 * indices first also avoids potential for wrapping.
27418 	 */
27419 
27420 	start_offset = duk_to_int(thr, idx_start);
27421 	if (start_offset < 0) {
27422 		start_offset = buffer_length + start_offset;
27423 	}
27424 	if (duk_is_undefined(thr, idx_end)) {
27425 		end_offset = buffer_length;
27426 	} else {
27427 		end_offset = duk_to_int(thr, idx_end);
27428 		if (end_offset < 0) {
27429 			end_offset = buffer_length + end_offset;
27430 		}
27431 	}
27432 	/* Note: start_offset/end_offset can still be < 0 here. */
27433 
27434 	if (start_offset < 0) {
27435 		start_offset = 0;
27436 	} else if (start_offset > buffer_length) {
27437 		start_offset = buffer_length;
27438 	}
27439 	if (end_offset < start_offset) {
27440 		end_offset = start_offset;
27441 	} else if (end_offset > buffer_length) {
27442 		end_offset = buffer_length;
27443 	}
27444 	DUK_ASSERT(start_offset >= 0);
27445 	DUK_ASSERT(start_offset <= buffer_length);
27446 	DUK_ASSERT(end_offset >= 0);
27447 	DUK_ASSERT(end_offset <= buffer_length);
27448 	DUK_ASSERT(start_offset <= end_offset);
27449 
27450 	/* Convert indices to byte offsets. */
27451 	start_offset <<= buffer_shift;
27452 	end_offset <<= buffer_shift;
27453 
27454 	*out_start_offset = start_offset;
27455 	*out_end_offset = end_offset;
27456 }
27457 
duk_hbufobj_promote_plain(duk_hthread * thr,duk_idx_t idx)27458 DUK_INTERNAL void duk_hbufobj_promote_plain(duk_hthread *thr, duk_idx_t idx) {
27459 	if (duk_is_buffer(thr, idx)) {
27460 		duk_to_object(thr, idx);
27461 	}
27462 }
27463 
duk_hbufobj_push_uint8array_from_plain(duk_hthread * thr,duk_hbuffer * h_buf)27464 DUK_INTERNAL void duk_hbufobj_push_uint8array_from_plain(duk_hthread *thr, duk_hbuffer *h_buf) {
27465 	/* Push Uint8Array which will share the same underlying buffer as
27466 	 * the plain buffer argument.  Also create an ArrayBuffer with the
27467 	 * same backing for the result .buffer property.
27468 	 */
27469 
27470 	duk_push_hbuffer(thr, h_buf);
27471 	duk_push_buffer_object(thr, -1, 0, (duk_size_t) DUK_HBUFFER_GET_SIZE(h_buf), DUK_BUFOBJ_UINT8ARRAY);
27472 	duk_remove_m2(thr);
27473 
27474 #if 0
27475 	/* More verbose equivalent; maybe useful if e.g. .buffer is omitted. */
27476 	h_bufobj = duk_push_bufobj_raw(thr,
27477 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
27478 	                               DUK_HOBJECT_FLAG_BUFOBJ |
27479 	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_UINT8ARRAY),
27480 	                               DUK_BIDX_UINT8ARRAY_PROTOTYPE);
27481 	DUK_ASSERT(h_bufobj != NULL);
27482 	duk__set_bufobj_buffer(thr, h_bufobj, h_buf);
27483 	h_bufobj->is_typedarray = 1;
27484 	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
27485 
27486 	h_arrbuf = duk_push_bufobj_raw(thr,
27487 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
27488 	                               DUK_HOBJECT_FLAG_BUFOBJ |
27489 	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
27490 	                               DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
27491 	DUK_ASSERT(h_arrbuf != NULL);
27492 	duk__set_bufobj_buffer(thr, h_arrbuf, h_buf);
27493 	DUK_ASSERT(h_arrbuf->is_typedarray == 0);
27494 	DUK_HBUFOBJ_ASSERT_VALID(h_arrbuf);
27495 
27496 	DUK_ASSERT(h_bufobj->buf_prop == NULL);
27497 	h_bufobj->buf_prop = (duk_hobject *) h_arrbuf;
27498 	DUK_ASSERT(h_arrbuf != NULL);
27499 	DUK_HBUFOBJ_INCREF(thr, h_arrbuf);
27500 	duk_pop(thr);
27501 #endif
27502 }
27503 
27504 /* Indexed read helper for buffer objects, also called from outside this file. */
duk_hbufobj_push_validated_read(duk_hthread * thr,duk_hbufobj * h_bufobj,duk_uint8_t * p,duk_small_uint_t elem_size)27505 DUK_INTERNAL void duk_hbufobj_push_validated_read(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size) {
27506 	duk_double_union du;
27507 
27508 	DUK_ASSERT(elem_size > 0);
27509 	duk_memcpy((void *) du.uc, (const void *) p, (size_t) elem_size);
27510 
27511 	switch (h_bufobj->elem_type) {
27512 	case DUK_HBUFOBJ_ELEM_UINT8:
27513 	case DUK_HBUFOBJ_ELEM_UINT8CLAMPED:
27514 		duk_push_uint(thr, (duk_uint_t) du.uc[0]);
27515 		break;
27516 	case DUK_HBUFOBJ_ELEM_INT8:
27517 		duk_push_int(thr, (duk_int_t) (duk_int8_t) du.uc[0]);
27518 		break;
27519 	case DUK_HBUFOBJ_ELEM_UINT16:
27520 		duk_push_uint(thr, (duk_uint_t) du.us[0]);
27521 		break;
27522 	case DUK_HBUFOBJ_ELEM_INT16:
27523 		duk_push_int(thr, (duk_int_t) (duk_int16_t) du.us[0]);
27524 		break;
27525 	case DUK_HBUFOBJ_ELEM_UINT32:
27526 		duk_push_uint(thr, (duk_uint_t) du.ui[0]);
27527 		break;
27528 	case DUK_HBUFOBJ_ELEM_INT32:
27529 		duk_push_int(thr, (duk_int_t) (duk_int32_t) du.ui[0]);
27530 		break;
27531 	case DUK_HBUFOBJ_ELEM_FLOAT32:
27532 		duk_push_number(thr, (duk_double_t) du.f[0]);
27533 		break;
27534 	case DUK_HBUFOBJ_ELEM_FLOAT64:
27535 		duk_push_number(thr, (duk_double_t) du.d);
27536 		break;
27537 	default:
27538 		DUK_UNREACHABLE();
27539 	}
27540 }
27541 
27542 /* Indexed write helper for buffer objects, also called from outside this file. */
duk_hbufobj_validated_write(duk_hthread * thr,duk_hbufobj * h_bufobj,duk_uint8_t * p,duk_small_uint_t elem_size)27543 DUK_INTERNAL void duk_hbufobj_validated_write(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size) {
27544 	duk_double_union du;
27545 
27546 	/* NOTE! Caller must ensure that any side effects from the
27547 	 * coercions below are safe.  If that cannot be guaranteed
27548 	 * (which is normally the case), caller must coerce the
27549 	 * argument using duk_to_number() before any pointer
27550 	 * validations; the result of duk_to_number() always coerces
27551 	 * without side effects here.
27552 	 */
27553 
27554 	switch (h_bufobj->elem_type) {
27555 	case DUK_HBUFOBJ_ELEM_UINT8:
27556 		du.uc[0] = (duk_uint8_t) duk_to_uint32(thr, -1);
27557 		break;
27558 	case DUK_HBUFOBJ_ELEM_UINT8CLAMPED:
27559 		du.uc[0] = (duk_uint8_t) duk_to_uint8clamped(thr, -1);
27560 		break;
27561 	case DUK_HBUFOBJ_ELEM_INT8:
27562 		du.uc[0] = (duk_uint8_t) duk_to_int32(thr, -1);
27563 		break;
27564 	case DUK_HBUFOBJ_ELEM_UINT16:
27565 		du.us[0] = (duk_uint16_t) duk_to_uint32(thr, -1);
27566 		break;
27567 	case DUK_HBUFOBJ_ELEM_INT16:
27568 		du.us[0] = (duk_uint16_t) duk_to_int32(thr, -1);
27569 		break;
27570 	case DUK_HBUFOBJ_ELEM_UINT32:
27571 		du.ui[0] = (duk_uint32_t) duk_to_uint32(thr, -1);
27572 		break;
27573 	case DUK_HBUFOBJ_ELEM_INT32:
27574 		du.ui[0] = (duk_uint32_t) duk_to_int32(thr, -1);
27575 		break;
27576 	case DUK_HBUFOBJ_ELEM_FLOAT32:
27577 		/* A double-to-float cast is undefined behavior in C99 if
27578 		 * the cast is out-of-range, so use a helper.  Example:
27579 		 * runtime error: value -1e+100 is outside the range of representable values of type 'float'
27580 		 */
27581 		du.f[0] = duk_double_to_float_t(duk_to_number_m1(thr));
27582 		break;
27583 	case DUK_HBUFOBJ_ELEM_FLOAT64:
27584 		du.d = (duk_double_t) duk_to_number_m1(thr);
27585 		break;
27586 	default:
27587 		DUK_UNREACHABLE();
27588 	}
27589 
27590 	DUK_ASSERT(elem_size > 0);
27591 	duk_memcpy((void *) p, (const void *) du.uc, (size_t) elem_size);
27592 }
27593 
27594 /* Helper to create a fixed buffer from argument value at index 0.
27595  * Node.js and allocPlain() compatible.
27596  */
duk__hbufobj_fixed_from_argvalue(duk_hthread * thr)27597 DUK_LOCAL duk_hbuffer *duk__hbufobj_fixed_from_argvalue(duk_hthread *thr) {
27598 	duk_int_t len;
27599 	duk_int_t i;
27600 	duk_size_t buf_size;
27601 	duk_uint8_t *buf;
27602 
27603 	switch (duk_get_type(thr, 0)) {
27604 	case DUK_TYPE_NUMBER: {
27605 		len = duk_to_int_clamped(thr, 0, 0, DUK_INT_MAX);
27606 		(void) duk_push_fixed_buffer_zero(thr, (duk_size_t) len);
27607 		break;
27608 	}
27609 	case DUK_TYPE_BUFFER: { /* Treat like Uint8Array. */
27610 		goto slow_copy;
27611 	}
27612 	case DUK_TYPE_OBJECT: {
27613 		duk_hobject *h;
27614 		duk_hbufobj *h_bufobj;
27615 
27616 		/* For Node.js Buffers "Passing an ArrayBuffer returns a Buffer
27617 		 * that shares allocated memory with the given ArrayBuffer."
27618 		 * https://nodejs.org/api/buffer.html#buffer_buffer_from_buffer_alloc_and_buffer_allocunsafe
27619 		 */
27620 
27621 		h = duk_known_hobject(thr, 0);
27622 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAYBUFFER) {
27623 			DUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ(h));
27624 			h_bufobj = (duk_hbufobj *) h;
27625 			if (DUK_UNLIKELY(h_bufobj->buf == NULL)) {
27626 				DUK_ERROR_TYPE_INVALID_ARGS(thr);
27627 				DUK_WO_NORETURN(return NULL;);
27628 			}
27629 			if (DUK_UNLIKELY(h_bufobj->offset != 0 || h_bufobj->length != DUK_HBUFFER_GET_SIZE(h_bufobj->buf))) {
27630 				/* No support for ArrayBuffers with slice
27631 				 * offset/length.
27632 				 */
27633 				DUK_ERROR_TYPE_INVALID_ARGS(thr);
27634 				DUK_WO_NORETURN(return NULL;);
27635 			}
27636 			duk_push_hbuffer(thr, h_bufobj->buf);
27637 			return h_bufobj->buf;
27638 		}
27639 		goto slow_copy;
27640 	}
27641 	case DUK_TYPE_STRING: {
27642 		/* ignore encoding for now */
27643 		duk_require_hstring_notsymbol(thr, 0);
27644 		duk_dup_0(thr);
27645 		(void) duk_to_buffer(thr, -1, &buf_size);
27646 		break;
27647 	}
27648 	default:
27649 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
27650 		DUK_WO_NORETURN(return NULL;);
27651 	}
27652 
27653  done:
27654 	DUK_ASSERT(duk_is_buffer(thr, -1));
27655 	return duk_known_hbuffer(thr, -1);
27656 
27657  slow_copy:
27658 	/* XXX: fast path for typed arrays and other buffer objects? */
27659 
27660 	(void) duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
27661 	len = duk_to_int_clamped(thr, -1, 0, DUK_INT_MAX);
27662 	duk_pop(thr);
27663 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) len);  /* no zeroing, all indices get initialized */
27664 	for (i = 0; i < len; i++) {
27665 		/* XXX: fast path for array or buffer arguments? */
27666 		duk_get_prop_index(thr, 0, (duk_uarridx_t) i);
27667 		buf[i] = (duk_uint8_t) (duk_to_uint32(thr, -1) & 0xffU);
27668 		duk_pop(thr);
27669 	}
27670 	goto done;
27671 }
27672 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27673 
27674 /*
27675  *  Node.js Buffer constructor
27676  *
27677  *  Node.js Buffers are just Uint8Arrays with internal prototype set to
27678  *  Buffer.prototype so they're handled otherwise the same as Uint8Array.
27679  *  However, the constructor arguments are very different so a separate
27680  *  constructor entry point is used.
27681  */
27682 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_constructor(duk_hthread * thr)27683 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_hthread *thr) {
27684 	duk_hbuffer *h_buf;
27685 
27686 	h_buf = duk__hbufobj_fixed_from_argvalue(thr);
27687 	DUK_ASSERT(h_buf != NULL);
27688 
27689 	duk_push_buffer_object(thr,
27690 	                       -1,
27691 	                       0,
27692 	                       DUK_HBUFFER_FIXED_GET_SIZE((duk_hbuffer_fixed *) (void *) h_buf),
27693 	                       DUK_BUFOBJ_UINT8ARRAY);
27694 	duk_push_hobject_bidx(thr, DUK_BIDX_NODEJS_BUFFER_PROTOTYPE);
27695 	duk_set_prototype(thr, -2);
27696 
27697 	/* XXX: a more direct implementation */
27698 
27699 	return 1;
27700 }
27701 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27702 
27703 /*
27704  *  ArrayBuffer, DataView, and TypedArray constructors
27705  */
27706 
27707 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_arraybuffer_constructor(duk_hthread * thr)27708 DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_constructor(duk_hthread *thr) {
27709 	duk_hbufobj *h_bufobj;
27710 	duk_hbuffer *h_val;
27711 	duk_int_t len;
27712 
27713 	DUK_CTX_ASSERT_VALID(thr);
27714 
27715 	duk_require_constructor_call(thr);
27716 
27717 	len = duk_to_int(thr, 0);
27718 	if (len < 0) {
27719 		goto fail_length;
27720 	}
27721 	(void) duk_push_fixed_buffer_zero(thr, (duk_size_t) len);
27722 	h_val = (duk_hbuffer *) duk_known_hbuffer(thr, -1);
27723 
27724 	h_bufobj = duk_push_bufobj_raw(thr,
27725 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
27726 	                               DUK_HOBJECT_FLAG_BUFOBJ |
27727 	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
27728 	                               DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
27729 	DUK_ASSERT(h_bufobj != NULL);
27730 
27731 	duk__set_bufobj_buffer(thr, h_bufobj, h_val);
27732 	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
27733 
27734 	return 1;
27735 
27736  fail_length:
27737 	DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
27738 }
27739 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27740 
27741 
27742 /* Format of magic, bits:
27743  *   0...1: elem size shift (0-3)
27744  *   2...5: elem type (DUK_HBUFOBJ_ELEM_xxx)
27745  *
27746  * XXX: add prototype bidx explicitly to magic instead of using a mapping?
27747  */
27748 
27749 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_typedarray_constructor(duk_hthread * thr)27750 DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
27751 	duk_tval *tv;
27752 	duk_hobject *h_obj;
27753 	duk_hbufobj *h_bufobj = NULL;
27754 	duk_hbufobj *h_bufarg = NULL;
27755 	duk_hbuffer *h_val;
27756 	duk_small_uint_t magic;
27757 	duk_small_uint_t shift;
27758 	duk_small_uint_t elem_type;
27759 	duk_small_uint_t elem_size;
27760 	duk_small_uint_t class_num;
27761 	duk_small_uint_t proto_bidx;
27762 	duk_uint_t align_mask;
27763 	duk_uint_t elem_length;
27764 	duk_int_t elem_length_signed;
27765 	duk_uint_t byte_length;
27766 	duk_small_uint_t copy_mode;
27767 
27768 	/* XXX: The same copy helpers could be shared with at least some
27769 	 * buffer functions.
27770 	 */
27771 
27772 	duk_require_constructor_call(thr);
27773 
27774 	/* We could fit built-in index into magic but that'd make the magic
27775 	 * number dependent on built-in numbering (genbuiltins.py doesn't
27776 	 * handle that yet).  So map both class and prototype from the
27777 	 * element type.
27778 	 */
27779 	magic = (duk_small_uint_t) duk_get_current_magic(thr);
27780 	shift = magic & 0x03U;               /* bits 0...1: shift */
27781 	elem_type = (magic >> 2) & 0x0fU;    /* bits 2...5: type */
27782 	elem_size = 1U << shift;
27783 	align_mask = elem_size - 1;
27784 	DUK_ASSERT(elem_type < sizeof(duk__buffer_proto_from_elemtype) / sizeof(duk_uint8_t));
27785 	proto_bidx = duk__buffer_proto_from_elemtype[elem_type];
27786 	DUK_ASSERT(proto_bidx < DUK_NUM_BUILTINS);
27787 	DUK_ASSERT(elem_type < sizeof(duk__buffer_class_from_elemtype) / sizeof(duk_uint8_t));
27788 	class_num = duk__buffer_class_from_elemtype[elem_type];
27789 
27790 	DUK_DD(DUK_DDPRINT("typedarray constructor, magic=%d, shift=%d, elem_type=%d, "
27791 	                   "elem_size=%d, proto_bidx=%d, class_num=%d",
27792 	                   (int) magic, (int) shift, (int) elem_type, (int) elem_size,
27793 	                   (int) proto_bidx, (int) class_num));
27794 
27795 	/* Argument variants.  When the argument is an ArrayBuffer a view to
27796 	 * the same buffer is created; otherwise a new ArrayBuffer is always
27797 	 * created.
27798 	 */
27799 
27800 	/* XXX: initial iteration to treat a plain buffer like an ArrayBuffer:
27801 	 * coerce to an ArrayBuffer object and use that as .buffer.  The underlying
27802 	 * buffer will be the same but result .buffer !== inputPlainBuffer.
27803 	 */
27804 	duk_hbufobj_promote_plain(thr, 0);
27805 
27806 	tv = duk_get_tval(thr, 0);
27807 	DUK_ASSERT(tv != NULL);  /* arg count */
27808 	if (DUK_TVAL_IS_OBJECT(tv)) {
27809 		h_obj = DUK_TVAL_GET_OBJECT(tv);
27810 		DUK_ASSERT(h_obj != NULL);
27811 
27812 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_ARRAYBUFFER) {
27813 			/* ArrayBuffer: unlike any other argument variant, create
27814 			 * a view into the existing buffer.
27815 			 */
27816 
27817 			duk_int_t byte_offset_signed;
27818 			duk_uint_t byte_offset;
27819 
27820 			h_bufarg = (duk_hbufobj *) h_obj;
27821 
27822 			byte_offset_signed = duk_to_int(thr, 1);
27823 			if (byte_offset_signed < 0) {
27824 				goto fail_arguments;
27825 			}
27826 			byte_offset = (duk_uint_t) byte_offset_signed;
27827 			if (byte_offset > h_bufarg->length ||
27828 			    (byte_offset & align_mask) != 0) {
27829 				/* Must be >= 0 and multiple of element size. */
27830 				goto fail_arguments;
27831 			}
27832 			if (duk_is_undefined(thr, 2)) {
27833 				DUK_ASSERT(h_bufarg->length >= byte_offset);
27834 				byte_length = h_bufarg->length - byte_offset;
27835 				if ((byte_length & align_mask) != 0) {
27836 					/* Must be element size multiple from
27837 					 * start offset to end of buffer.
27838 					 */
27839 					goto fail_arguments;
27840 				}
27841 				elem_length = (byte_length >> shift);
27842 			} else {
27843 				elem_length_signed = duk_to_int(thr, 2);
27844 				if (elem_length_signed < 0) {
27845 					goto fail_arguments;
27846 				}
27847 				elem_length = (duk_uint_t) elem_length_signed;
27848 				byte_length = elem_length << shift;
27849 				if ((byte_length >> shift) != elem_length) {
27850 					/* Byte length would overflow. */
27851 					/* XXX: easier check with less code? */
27852 					goto fail_arguments;
27853 				}
27854 				DUK_ASSERT(h_bufarg->length >= byte_offset);
27855 				if (byte_length > h_bufarg->length - byte_offset) {
27856 					/* Not enough data. */
27857 					goto fail_arguments;
27858 				}
27859 			}
27860 			DUK_UNREF(elem_length);
27861 			DUK_ASSERT_DISABLE(byte_offset >= 0);
27862 			DUK_ASSERT(byte_offset <= h_bufarg->length);
27863 			DUK_ASSERT_DISABLE(byte_length >= 0);
27864 			DUK_ASSERT(byte_offset + byte_length <= h_bufarg->length);
27865 			DUK_ASSERT((elem_length << shift) == byte_length);
27866 
27867 			h_bufobj = duk_push_bufobj_raw(thr,
27868 			                               DUK_HOBJECT_FLAG_EXTENSIBLE |
27869 			                               DUK_HOBJECT_FLAG_BUFOBJ |
27870 			                               DUK_HOBJECT_CLASS_AS_FLAGS(class_num),
27871 			                               (duk_small_int_t) proto_bidx);
27872 			h_val = h_bufarg->buf;
27873 			if (h_val == NULL) {
27874 				DUK_DCERROR_TYPE_INVALID_ARGS(thr);
27875 			}
27876 			h_bufobj->buf = h_val;
27877 			DUK_HBUFFER_INCREF(thr, h_val);
27878 			h_bufobj->offset = h_bufarg->offset + byte_offset;
27879 			h_bufobj->length = byte_length;
27880 			h_bufobj->shift = (duk_uint8_t) shift;
27881 			h_bufobj->elem_type = (duk_uint8_t) elem_type;
27882 			h_bufobj->is_typedarray = 1;
27883 			DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
27884 
27885 			/* Set .buffer to the argument ArrayBuffer. */
27886 			DUK_ASSERT(h_bufobj->buf_prop == NULL);
27887 			h_bufobj->buf_prop = (duk_hobject *) h_bufarg;
27888 			DUK_ASSERT(h_bufarg != NULL);
27889 			DUK_HBUFOBJ_INCREF(thr, h_bufarg);
27890 			return 1;
27891 		} else if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
27892 			/* TypedArray (or other non-ArrayBuffer duk_hbufobj).
27893 			 * Conceptually same behavior as for an Array-like argument,
27894 			 * with a few fast paths.
27895 			 */
27896 
27897 			h_bufarg = (duk_hbufobj *) h_obj;
27898 			DUK_HBUFOBJ_ASSERT_VALID(h_bufarg);
27899 			elem_length_signed = (duk_int_t) (h_bufarg->length >> h_bufarg->shift);
27900 			if (h_bufarg->buf == NULL) {
27901 				DUK_DCERROR_TYPE_INVALID_ARGS(thr);
27902 			}
27903 
27904 			/* Select copy mode.  Must take into account element
27905 			 * compatibility and validity of the underlying source
27906 			 * buffer.
27907 			 */
27908 
27909 			DUK_DDD(DUK_DDDPRINT("selecting copy mode for bufobj arg, "
27910 			                     "src byte_length=%ld, src shift=%d, "
27911 			                     "src/dst elem_length=%ld; "
27912 			                     "dst shift=%d -> dst byte_length=%ld",
27913 			                     (long) h_bufarg->length, (int) h_bufarg->shift,
27914 			                     (long) elem_length_signed, (int) shift,
27915 			                     (long) (elem_length_signed << shift)));
27916 
27917 			copy_mode = 2;  /* default is explicit index read/write copy */
27918 #if !defined(DUK_USE_PREFER_SIZE)
27919 			/* With a size optimized build copy_mode 2 is enough.
27920 			 * Modes 0 and 1 are faster but conceptually the same.
27921 			 */
27922 			DUK_ASSERT(elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t));
27923 			if (DUK_HBUFOBJ_VALID_SLICE(h_bufarg)) {
27924 				if ((duk__buffer_elemtype_copy_compatible[elem_type] & (1 << h_bufarg->elem_type)) != 0) {
27925 					DUK_DDD(DUK_DDDPRINT("source/target are copy compatible, memcpy"));
27926 					DUK_ASSERT(shift == h_bufarg->shift);  /* byte sizes will match */
27927 					copy_mode = 0;
27928 				} else {
27929 					DUK_DDD(DUK_DDDPRINT("source/target not copy compatible but valid, fast copy"));
27930 					copy_mode = 1;
27931 				}
27932 			}
27933 #endif  /* !DUK_USE_PREFER_SIZE */
27934 		} else {
27935 			/* Array or Array-like */
27936 			elem_length_signed = (duk_int_t) duk_get_length(thr, 0);
27937 			copy_mode = 2;
27938 		}
27939 	} else {
27940 		/* Non-object argument is simply int coerced, matches
27941 		 * V8 behavior (except for "null", which we coerce to
27942 		 * 0 but V8 TypeErrors).
27943 		 */
27944 		elem_length_signed = duk_to_int(thr, 0);
27945 		copy_mode = 3;
27946 	}
27947 	if (elem_length_signed < 0) {
27948 		goto fail_arguments;
27949 	}
27950 	elem_length = (duk_uint_t) elem_length_signed;
27951 	byte_length = (duk_uint_t) (elem_length << shift);
27952 	if ((byte_length >> shift) != elem_length) {
27953 		/* Byte length would overflow. */
27954 		/* XXX: easier check with less code? */
27955 		goto fail_arguments;
27956 	}
27957 
27958 	DUK_DDD(DUK_DDDPRINT("elem_length=%ld, byte_length=%ld",
27959 	                     (long) elem_length, (long) byte_length));
27960 
27961 	/* ArrayBuffer argument is handled specially above; the rest of the
27962 	 * argument variants are handled by shared code below.
27963 	 *
27964 	 * ArrayBuffer in h_bufobj->buf_prop is intentionally left unset.
27965 	 * It will be automatically created by the .buffer accessor on
27966 	 * first access.
27967 	 */
27968 
27969 	/* Push the resulting view object on top of a plain fixed buffer. */
27970 	(void) duk_push_fixed_buffer(thr, byte_length);
27971 	h_val = duk_known_hbuffer(thr, -1);
27972 	DUK_ASSERT(h_val != NULL);
27973 
27974 	h_bufobj = duk_push_bufobj_raw(thr,
27975 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
27976 	                               DUK_HOBJECT_FLAG_BUFOBJ |
27977 	                               DUK_HOBJECT_CLASS_AS_FLAGS(class_num),
27978 	                               (duk_small_int_t) proto_bidx);
27979 
27980 	h_bufobj->buf = h_val;
27981 	DUK_HBUFFER_INCREF(thr, h_val);
27982 	DUK_ASSERT(h_bufobj->offset == 0);
27983 	h_bufobj->length = byte_length;
27984 	h_bufobj->shift = (duk_uint8_t) shift;
27985 	h_bufobj->elem_type = (duk_uint8_t) elem_type;
27986 	h_bufobj->is_typedarray = 1;
27987 	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
27988 
27989 	/* Copy values, the copy method depends on the arguments.
27990 	 *
27991 	 * Copy mode decision may depend on the validity of the underlying
27992 	 * buffer of the source argument; there must be no harmful side effects
27993 	 * from there to here for copy_mode to still be valid.
27994 	 */
27995 	DUK_DDD(DUK_DDDPRINT("copy mode: %d", (int) copy_mode));
27996 	switch (copy_mode) {
27997 		/* Copy modes 0 and 1 can be omitted in size optimized build,
27998 		 * copy mode 2 handles them (but more slowly).
27999 		 */
28000 #if !defined(DUK_USE_PREFER_SIZE)
28001 	case 0: {
28002 		/* Use byte copy. */
28003 
28004 		duk_uint8_t *p_src;
28005 		duk_uint8_t *p_dst;
28006 
28007 		DUK_ASSERT(h_bufobj != NULL);
28008 		DUK_ASSERT(h_bufobj->buf != NULL);
28009 		DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufobj));
28010 		DUK_ASSERT(h_bufarg != NULL);
28011 		DUK_ASSERT(h_bufarg->buf != NULL);
28012 		DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufarg));
28013 
28014 		p_dst = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj);
28015 		p_src = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);
28016 
28017 		DUK_DDD(DUK_DDDPRINT("using memcpy: p_src=%p, p_dst=%p, byte_length=%ld",
28018 		                     (void *) p_src, (void *) p_dst, (long) byte_length));
28019 
28020 		duk_memcpy_unsafe((void *) p_dst, (const void *) p_src, (size_t) byte_length);
28021 		break;
28022 	}
28023 	case 1: {
28024 		/* Copy values through direct validated reads and writes. */
28025 
28026 		duk_small_uint_t src_elem_size;
28027 		duk_small_uint_t dst_elem_size;
28028 		duk_uint8_t *p_src;
28029 		duk_uint8_t *p_src_end;
28030 		duk_uint8_t *p_dst;
28031 
28032 		DUK_ASSERT(h_bufobj != NULL);
28033 		DUK_ASSERT(h_bufobj->buf != NULL);
28034 		DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufobj));
28035 		DUK_ASSERT(h_bufarg != NULL);
28036 		DUK_ASSERT(h_bufarg->buf != NULL);
28037 		DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufarg));
28038 
28039 		src_elem_size = (duk_small_uint_t) (1U << h_bufarg->shift);
28040 		dst_elem_size = elem_size;
28041 
28042 		p_src = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);
28043 		p_dst = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj);
28044 		p_src_end = p_src + h_bufarg->length;
28045 
28046 		DUK_DDD(DUK_DDDPRINT("using fast copy: p_src=%p, p_src_end=%p, p_dst=%p, "
28047 		                     "src_elem_size=%d, dst_elem_size=%d",
28048 		                     (void *) p_src, (void *) p_src_end, (void *) p_dst,
28049 		                     (int) src_elem_size, (int) dst_elem_size));
28050 
28051 		while (p_src != p_src_end) {
28052 			DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: "
28053 			                     "p_src=%p, p_src_end=%p, p_dst=%p",
28054 			                     (void *) p_src, (void *) p_src_end, (void *) p_dst));
28055 			/* A validated read() is always a number, so it's write coercion
28056 			 * is always side effect free an won't invalidate pointers etc.
28057 			 */
28058 			duk_hbufobj_push_validated_read(thr, h_bufarg, p_src, src_elem_size);
28059 			duk_hbufobj_validated_write(thr, h_bufobj, p_dst, dst_elem_size);
28060 			duk_pop(thr);
28061 			p_src += src_elem_size;
28062 			p_dst += dst_elem_size;
28063 		}
28064 		break;
28065 	}
28066 #endif  /* !DUK_USE_PREFER_SIZE */
28067 	case 2: {
28068 		/* Copy values by index reads and writes.  Let virtual
28069 		 * property handling take care of coercion.
28070 		 */
28071 		duk_uint_t i;
28072 
28073 		DUK_DDD(DUK_DDDPRINT("using slow copy"));
28074 
28075 		for (i = 0; i < elem_length; i++) {
28076 			duk_get_prop_index(thr, 0, (duk_uarridx_t) i);
28077 			duk_put_prop_index(thr, -2, (duk_uarridx_t) i);
28078 		}
28079 		break;
28080 	}
28081 	default:
28082 	case 3: {
28083 		/* No copy, leave zero bytes in the buffer.  There's no
28084 		 * ambiguity with Float32/Float64 because zero bytes also
28085 		 * represent 0.0.
28086 		 */
28087 
28088 		DUK_DDD(DUK_DDDPRINT("using no copy"));
28089 		break;
28090 	}
28091 	}
28092 
28093 	return 1;
28094 
28095  fail_arguments:
28096 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
28097 }
28098 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28099 /* When bufferobject support is disabled, new Uint8Array() could still be
28100  * supported to create a plain fixed buffer.  Disabled for now.
28101  */
28102 #if 0
28103 DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
28104 	duk_int_t elem_length_signed;
28105 	duk_uint_t byte_length;
28106 
28107 	/* XXX: The same copy helpers could be shared with at least some
28108 	 * buffer functions.
28109 	 */
28110 
28111 	duk_require_constructor_call(thr);
28112 
28113 	elem_length_signed = duk_require_int(thr, 0);
28114 	if (elem_length_signed < 0) {
28115 		goto fail_arguments;
28116 	}
28117 	byte_length = (duk_uint_t) elem_length_signed;
28118 
28119 	(void) duk_push_fixed_buffer_zero(thr, (duk_size_t) byte_length);
28120 	return 1;
28121 
28122  fail_arguments:
28123 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
28124 }
28125 #endif  /* 0 */
28126 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28127 
28128 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_dataview_constructor(duk_hthread * thr)28129 DUK_INTERNAL duk_ret_t duk_bi_dataview_constructor(duk_hthread *thr) {
28130 	duk_hbufobj *h_bufarg;
28131 	duk_hbufobj *h_bufobj;
28132 	duk_hbuffer *h_val;
28133 	duk_uint_t offset;
28134 	duk_uint_t length;
28135 
28136 	duk_require_constructor_call(thr);
28137 
28138 	h_bufarg = duk__require_bufobj_value(thr, 0);
28139 	DUK_ASSERT(h_bufarg != NULL);
28140 	if (DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_bufarg) != DUK_HOBJECT_CLASS_ARRAYBUFFER) {
28141 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
28142 	}
28143 
28144 	duk__resolve_offset_opt_length(thr, h_bufarg, 1, 2, &offset, &length, 1 /*throw_flag*/);
28145 	DUK_ASSERT(offset <= h_bufarg->length);
28146 	DUK_ASSERT(offset + length <= h_bufarg->length);
28147 
28148 	h_bufobj = duk_push_bufobj_raw(thr,
28149 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
28150 	                               DUK_HOBJECT_FLAG_BUFOBJ |
28151 	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DATAVIEW),
28152 	                               DUK_BIDX_DATAVIEW_PROTOTYPE);
28153 
28154 	h_val = h_bufarg->buf;
28155 	if (h_val == NULL) {
28156 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
28157 	}
28158 	h_bufobj->buf = h_val;
28159 	DUK_HBUFFER_INCREF(thr, h_val);
28160 	h_bufobj->offset = h_bufarg->offset + offset;
28161 	h_bufobj->length = length;
28162 	DUK_ASSERT(h_bufobj->shift == 0);
28163 	DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFOBJ_ELEM_UINT8);
28164 	DUK_ASSERT(h_bufobj->is_typedarray == 0);
28165 
28166 	DUK_ASSERT(h_bufobj->buf_prop == NULL);
28167 	h_bufobj->buf_prop = (duk_hobject *) h_bufarg;
28168 	DUK_ASSERT(h_bufarg != NULL);
28169 	DUK_HBUFOBJ_INCREF(thr, h_bufarg);
28170 
28171 	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
28172 	return 1;
28173 }
28174 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28175 
28176 /*
28177  *  ArrayBuffer.isView()
28178  */
28179 
28180 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_arraybuffer_isview(duk_hthread * thr)28181 DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_isview(duk_hthread *thr) {
28182 	duk_hobject *h_obj;
28183 	duk_bool_t ret = 0;
28184 
28185 	if (duk_is_buffer(thr, 0)) {
28186 		ret = 1;
28187 	} else {
28188 		h_obj = duk_get_hobject(thr, 0);
28189 		if (h_obj != NULL && DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
28190 			/* DataView needs special casing: ArrayBuffer.isView() is
28191 			 * true, but ->is_typedarray is 0.
28192 			 */
28193 			ret = ((duk_hbufobj *) h_obj)->is_typedarray ||
28194 			      (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_DATAVIEW);
28195 		}
28196 	}
28197 	duk_push_boolean(thr, ret);
28198 	return 1;
28199 }
28200 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28201 
28202 /*
28203  *  Uint8Array.allocPlain()
28204  */
28205 
28206 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_uint8array_allocplain(duk_hthread * thr)28207 DUK_INTERNAL duk_ret_t duk_bi_uint8array_allocplain(duk_hthread *thr) {
28208 	duk__hbufobj_fixed_from_argvalue(thr);
28209 	return 1;
28210 }
28211 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28212 
28213 /*
28214  *  Uint8Array.plainOf()
28215  */
28216 
28217 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_uint8array_plainof(duk_hthread * thr)28218 DUK_INTERNAL duk_ret_t duk_bi_uint8array_plainof(duk_hthread *thr) {
28219 	duk_hbufobj *h_bufobj;
28220 
28221 #if !defined(DUK_USE_PREFER_SIZE)
28222 	/* Avoid churn if argument is already a plain buffer. */
28223 	if (duk_is_buffer(thr, 0)) {
28224 		return 1;
28225 	}
28226 #endif
28227 
28228 	/* Promotes plain buffers to ArrayBuffers, so for a plain buffer
28229 	 * argument we'll create a pointless temporary (but still work
28230 	 * correctly).
28231 	 */
28232 	h_bufobj = duk__require_bufobj_value(thr, 0);
28233 	if (h_bufobj->buf == NULL) {
28234 		duk_push_undefined(thr);
28235 	} else {
28236 		duk_push_hbuffer(thr, h_bufobj->buf);
28237 	}
28238 	return 1;
28239 }
28240 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28241 
28242 /*
28243  *  Node.js Buffer: toString([encoding], [start], [end])
28244  */
28245 
28246 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_tostring(duk_hthread * thr)28247 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_hthread *thr) {
28248 	duk_hbufobj *h_this;
28249 	duk_int_t start_offset, end_offset;
28250 	duk_uint8_t *buf_slice;
28251 	duk_size_t slice_length;
28252 
28253 	h_this = duk__get_bufobj_this(thr);
28254 	if (h_this == NULL) {
28255 		/* XXX: happens e.g. when evaluating: String(Buffer.prototype). */
28256 		duk_push_literal(thr, "[object Object]");
28257 		return 1;
28258 	}
28259 	DUK_HBUFOBJ_ASSERT_VALID(h_this);
28260 
28261 	/* Ignore encoding for now. */
28262 
28263 	duk__clamp_startend_nonegidx_noshift(thr,
28264 	                                     (duk_int_t) h_this->length,
28265 	                                     1 /*idx_start*/,
28266 	                                     2 /*idx_end*/,
28267 	                                     &start_offset,
28268 	                                     &end_offset);
28269 
28270 	slice_length = (duk_size_t) (end_offset - start_offset);
28271 	buf_slice = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, slice_length);  /* all bytes initialized below */
28272 	DUK_ASSERT(buf_slice != NULL);
28273 
28274 	/* Neutered or uncovered, TypeError. */
28275 	if (h_this->buf == NULL ||
28276 	    !DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, (duk_size_t) start_offset + slice_length)) {
28277 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
28278 	}
28279 
28280 	/* XXX: ideally we wouldn't make a copy but a view into the buffer for the
28281 	 * decoding process.  Or the decoding helper could be changed to accept
28282 	 * the slice info (a buffer pointer is NOT a good approach because guaranteeing
28283 	 * its stability is difficult).
28284 	 */
28285 
28286 	DUK_ASSERT(DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, (duk_size_t) start_offset + slice_length));
28287 	duk_memcpy_unsafe((void *) buf_slice,
28288 	                  (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
28289 	                  (size_t) slice_length);
28290 
28291 	/* Use the equivalent of: new TextEncoder().encode(this) to convert the
28292 	 * string.  Result will be valid UTF-8; non-CESU-8 inputs are currently
28293 	 * interpreted loosely.  Value stack convention is a bit odd for now.
28294 	 */
28295 	duk_replace(thr, 0);
28296 	duk_set_top(thr, 1);
28297 	return duk_textdecoder_decode_utf8_nodejs(thr);
28298 }
28299 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28300 
28301 /*
28302  *  Node.js Buffer.prototype: toJSON()
28303  */
28304 
28305 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_tojson(duk_hthread * thr)28306 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_hthread *thr) {
28307 	duk_hbufobj *h_this;
28308 	duk_uint8_t *buf;
28309 	duk_uint_t i, n;
28310 	duk_tval *tv;
28311 
28312 	h_this = duk__require_bufobj_this(thr);
28313 	DUK_ASSERT(h_this != NULL);
28314 
28315 	if (h_this->buf == NULL || !DUK_HBUFOBJ_VALID_SLICE(h_this)) {
28316 		/* Serialize uncovered backing buffer as a null; doesn't
28317 		 * really matter as long we're memory safe.
28318 		 */
28319 		duk_push_null(thr);
28320 		return 1;
28321 	}
28322 
28323 	duk_push_object(thr);
28324 	duk_push_hstring_stridx(thr, DUK_STRIDX_UC_BUFFER);
28325 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_TYPE);
28326 
28327 	/* XXX: uninitialized would be OK */
28328 	DUK_ASSERT_DISABLE((duk_size_t) h_this->length <= (duk_size_t) DUK_UINT32_MAX);
28329 	tv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) h_this->length);  /* XXX: needs revision with >4G buffers */
28330 	DUK_ASSERT(!duk_is_bare_object(thr, -1));
28331 
28332 	DUK_ASSERT(h_this->buf != NULL);
28333 	buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
28334 	for (i = 0, n = h_this->length; i < n; i++) {
28335 		DUK_TVAL_SET_U32(tv + i, (duk_uint32_t) buf[i]);  /* no need for decref or incref */
28336 	}
28337 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_DATA);
28338 
28339 	return 1;
28340 }
28341 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28342 
28343 /*
28344  *  Node.js Buffer.prototype.equals()
28345  *  Node.js Buffer.prototype.compare()
28346  *  Node.js Buffer.compare()
28347  */
28348 
28349 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_buffer_compare_shared(duk_hthread * thr)28350 DUK_INTERNAL duk_ret_t duk_bi_buffer_compare_shared(duk_hthread *thr) {
28351 	duk_small_uint_t magic;
28352 	duk_hbufobj *h_bufarg1;
28353 	duk_hbufobj *h_bufarg2;
28354 	duk_small_int_t comp_res;
28355 
28356 	/* XXX: keep support for plain buffers and non-Node.js buffers? */
28357 
28358 	magic = (duk_small_uint_t) duk_get_current_magic(thr);
28359 	if (magic & 0x02U) {
28360 		/* Static call style. */
28361 		h_bufarg1 = duk__require_bufobj_value(thr, 0);
28362 		h_bufarg2 = duk__require_bufobj_value(thr, 1);
28363 	} else {
28364 		h_bufarg1 = duk__require_bufobj_this(thr);
28365 		h_bufarg2 = duk__require_bufobj_value(thr, 0);
28366 	}
28367 	DUK_ASSERT(h_bufarg1 != NULL);
28368 	DUK_ASSERT(h_bufarg2 != NULL);
28369 
28370 	/* We want to compare the slice/view areas of the arguments.
28371 	 * If either slice/view is invalid (underlying buffer is shorter)
28372 	 * ensure equals() is false, but otherwise the only thing that
28373 	 * matters is to be memory safe.
28374 	 */
28375 
28376 	if (DUK_HBUFOBJ_VALID_SLICE(h_bufarg1) &&
28377 	    DUK_HBUFOBJ_VALID_SLICE(h_bufarg2)) {
28378 		comp_res = duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg1->buf) + h_bufarg1->offset,
28379 		                               (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg2->buf) + h_bufarg2->offset,
28380 		                               (duk_size_t) h_bufarg1->length,
28381 		                               (duk_size_t) h_bufarg2->length);
28382 	} else {
28383 		comp_res = -1;  /* either nonzero value is ok */
28384 	}
28385 
28386 	if (magic & 0x01U) {
28387 		/* compare: similar to string comparison but for buffer data. */
28388 		duk_push_int(thr, comp_res);
28389 	} else {
28390 		/* equals */
28391 		duk_push_boolean(thr, (comp_res == 0));
28392 	}
28393 
28394 	return 1;
28395 }
28396 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28397 
28398 /*
28399  *  Node.js Buffer.prototype.fill()
28400  */
28401 
28402 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_fill(duk_hthread * thr)28403 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_fill(duk_hthread *thr) {
28404 	duk_hbufobj *h_this;
28405 	const duk_uint8_t *fill_str_ptr;
28406 	duk_size_t fill_str_len;
28407 	duk_uint8_t fill_value;
28408 	duk_int_t fill_offset;
28409 	duk_int_t fill_end;
28410 	duk_size_t fill_length;
28411 	duk_uint8_t *p;
28412 
28413 	h_this = duk__require_bufobj_this(thr);
28414 	DUK_ASSERT(h_this != NULL);
28415 	if (h_this->buf == NULL) {
28416 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
28417 	}
28418 
28419 	/* [ value offset end ] */
28420 
28421 	if (duk_is_string_notsymbol(thr, 0)) {
28422 		fill_str_ptr = (const duk_uint8_t *) duk_get_lstring(thr, 0, &fill_str_len);
28423 		DUK_ASSERT(fill_str_ptr != NULL);
28424 	} else {
28425 		/* Symbols get ToNumber() coerced and cause TypeError. */
28426 		fill_value = (duk_uint8_t) duk_to_uint32(thr, 0);
28427 		fill_str_ptr = (const duk_uint8_t *) &fill_value;
28428 		fill_str_len = 1;
28429 	}
28430 
28431 	/* Fill offset handling is more lenient than in Node.js. */
28432 
28433 	duk__clamp_startend_nonegidx_noshift(thr,
28434 	                                     (duk_int_t) h_this->length,
28435 	                                     1 /*idx_start*/,
28436 	                                     2 /*idx_end*/,
28437 	                                     &fill_offset,
28438 	                                     &fill_end);
28439 
28440 	DUK_DDD(DUK_DDDPRINT("fill: fill_value=%02x, fill_offset=%ld, fill_end=%ld, view length=%ld",
28441 	                     (unsigned int) fill_value, (long) fill_offset, (long) fill_end, (long) h_this->length));
28442 
28443 	DUK_ASSERT(fill_end - fill_offset >= 0);
28444 	DUK_ASSERT(h_this->buf != NULL);
28445 
28446 	p = (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + fill_offset);
28447 	fill_length = (duk_size_t) (fill_end - fill_offset);
28448 	if (fill_str_len == 1) {
28449 		/* Handle single character fills as memset() even when
28450 		 * the fill data comes from a one-char argument.
28451 		 */
28452 		duk_memset_unsafe((void *) p, (int) fill_str_ptr[0], (size_t) fill_length);
28453 	} else if (fill_str_len > 1) {
28454 		duk_size_t i, n, t;
28455 
28456 		for (i = 0, n = (duk_size_t) (fill_end - fill_offset), t = 0; i < n; i++) {
28457 			p[i] = fill_str_ptr[t++];
28458 			if (t >= fill_str_len) {
28459 				t = 0;
28460 			}
28461 		}
28462 	} else {
28463 		DUK_DDD(DUK_DDDPRINT("zero size fill pattern, ignore silently"));
28464 	}
28465 
28466 	/* Return the Buffer to allow chaining: b.fill(0x11).fill(0x22, 3, 5).toString() */
28467 	duk_push_this(thr);
28468 	return 1;
28469 }
28470 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28471 
28472 /*
28473  *  Node.js Buffer.prototype.write(string, [offset], [length], [encoding])
28474  */
28475 
28476 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_write(duk_hthread * thr)28477 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_write(duk_hthread *thr) {
28478 	duk_hbufobj *h_this;
28479 	duk_uint_t offset;
28480 	duk_uint_t length;
28481 	const duk_uint8_t *str_data;
28482 	duk_size_t str_len;
28483 
28484 	/* XXX: very inefficient support for plain buffers */
28485 	h_this = duk__require_bufobj_this(thr);
28486 	DUK_ASSERT(h_this != NULL);
28487 
28488 	/* Argument must be a string, e.g. a buffer is not allowed. */
28489 	str_data = (const duk_uint8_t *) duk_require_lstring_notsymbol(thr, 0, &str_len);
28490 
28491 	duk__resolve_offset_opt_length(thr, h_this, 1, 2, &offset, &length, 0 /*throw_flag*/);
28492 	DUK_ASSERT(offset <= h_this->length);
28493 	DUK_ASSERT(offset + length <= h_this->length);
28494 
28495 	/* XXX: encoding is ignored now. */
28496 
28497 	if (length > str_len) {
28498 		length = (duk_uint_t) str_len;
28499 	}
28500 
28501 	if (DUK_HBUFOBJ_VALID_SLICE(h_this)) {
28502 		/* Cannot overlap. */
28503 		duk_memcpy_unsafe((void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + offset),
28504 		                  (const void *) str_data,
28505 		                  (size_t) length);
28506 	} else {
28507 		DUK_DDD(DUK_DDDPRINT("write() target buffer is not covered, silent ignore"));
28508 	}
28509 
28510 	duk_push_uint(thr, length);
28511 	return 1;
28512 }
28513 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28514 
28515 /*
28516  *  Node.js Buffer.prototype.copy()
28517  */
28518 
28519 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_copy(duk_hthread * thr)28520 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_copy(duk_hthread *thr) {
28521 	duk_hbufobj *h_this;
28522 	duk_hbufobj *h_bufarg;
28523 	duk_int_t source_length;
28524 	duk_int_t target_length;
28525 	duk_int_t target_start, source_start, source_end;
28526 	duk_uint_t target_ustart, source_ustart, source_uend;
28527 	duk_uint_t copy_size = 0;
28528 
28529 	/* [ targetBuffer targetStart sourceStart sourceEnd ] */
28530 
28531 	h_this = duk__require_bufobj_this(thr);
28532 	h_bufarg = duk__require_bufobj_value(thr, 0);
28533 	DUK_ASSERT(h_this != NULL);
28534 	DUK_ASSERT(h_bufarg != NULL);
28535 	source_length = (duk_int_t) h_this->length;
28536 	target_length = (duk_int_t) h_bufarg->length;
28537 
28538 	target_start = duk_to_int(thr, 1);
28539 	source_start = duk_to_int(thr, 2);
28540 	if (duk_is_undefined(thr, 3)) {
28541 		source_end = source_length;
28542 	} else {
28543 		source_end = duk_to_int(thr, 3);
28544 	}
28545 
28546 	DUK_DDD(DUK_DDDPRINT("checking copy args: target_start=%ld, target_length=%ld, "
28547 	                     "source_start=%ld, source_end=%ld, source_length=%ld",
28548 	                     (long) target_start, (long) h_bufarg->length,
28549 	                     (long) source_start, (long) source_end, (long) source_length));
28550 
28551 	/* This behavior mostly mimics Node.js now. */
28552 
28553 	if (source_start < 0 || source_end < 0 || target_start < 0) {
28554 		/* Negative offsets cause a RangeError. */
28555 		goto fail_bounds;
28556 	}
28557 	source_ustart = (duk_uint_t) source_start;
28558 	source_uend = (duk_uint_t) source_end;
28559 	target_ustart = (duk_uint_t) target_start;
28560 	if (source_ustart >= source_uend ||  /* crossed offsets or zero size */
28561 	    source_ustart >= (duk_uint_t) source_length ||  /* source out-of-bounds (but positive) */
28562 	    target_ustart >= (duk_uint_t) target_length) {  /* target out-of-bounds (but positive) */
28563 		goto silent_ignore;
28564 	}
28565 	if (source_uend >= (duk_uint_t) source_length) {
28566 		/* Source end clamped silently to available length. */
28567 		source_uend = (duk_uint_t) source_length;
28568 	}
28569 	copy_size = source_uend - source_ustart;
28570 	if (target_ustart + copy_size > (duk_uint_t) target_length) {
28571 		/* Clamp to target's end if too long.
28572 		 *
28573 		 * NOTE: there's no overflow possibility in the comparison;
28574 		 * both target_ustart and copy_size are >= 0 and based on
28575 		 * values in duk_int_t range.  Adding them as duk_uint_t
28576 		 * values is then guaranteed not to overflow.
28577 		 */
28578 		DUK_ASSERT(target_ustart + copy_size >= target_ustart);  /* no overflow */
28579 		DUK_ASSERT(target_ustart + copy_size >= copy_size);  /* no overflow */
28580 		copy_size = (duk_uint_t) target_length - target_ustart;
28581 	}
28582 
28583 	DUK_DDD(DUK_DDDPRINT("making copy: target_ustart=%lu source_ustart=%lu copy_size=%lu",
28584 	                     (unsigned long) target_ustart, (unsigned long) source_ustart,
28585 	                     (unsigned long) copy_size));
28586 
28587 	DUK_ASSERT(copy_size >= 1);
28588 	DUK_ASSERT(source_ustart <= (duk_uint_t) source_length);
28589 	DUK_ASSERT(source_ustart + copy_size <= (duk_uint_t) source_length);
28590 	DUK_ASSERT(target_ustart <= (duk_uint_t) target_length);
28591 	DUK_ASSERT(target_ustart + copy_size <= (duk_uint_t) target_length);
28592 
28593 	/* Ensure copy is covered by underlying buffers. */
28594 	DUK_ASSERT(h_bufarg->buf != NULL);  /* length check */
28595 	DUK_ASSERT(h_this->buf != NULL);    /* length check */
28596 	if (DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufarg, target_ustart + copy_size) &&
28597 	    DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, source_ustart + copy_size)) {
28598 		/* Must use memmove() because copy area may overlap (source and target
28599 		 * buffer may be the same, or from different slices.
28600 		 */
28601 		duk_memmove_unsafe((void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg) + target_ustart),
28602 		                   (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + source_ustart),
28603 		                   (size_t) copy_size);
28604 	} else {
28605 		DUK_DDD(DUK_DDDPRINT("buffer copy not covered by underlying buffer(s), ignoring"));
28606 	}
28607 
28608  silent_ignore:
28609 	/* Return value is like write(), number of bytes written.
28610 	 * The return value matters because of code like:
28611 	 * "off += buf.copy(...)".
28612          */
28613 	duk_push_uint(thr, copy_size);
28614 	return 1;
28615 
28616  fail_bounds:
28617 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
28618 }
28619 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28620 
28621 /*
28622  *  TypedArray.prototype.set()
28623  *
28624  *  TypedArray set() is pretty interesting to implement because:
28625  *
28626  *    - The source argument may be a plain array or a typedarray.  If the
28627  *      source is a TypedArray, values are decoded and re-encoded into the
28628  *      target (not as a plain byte copy).  This may happen even when the
28629  *      element byte size is the same, e.g. integer values may be re-encoded
28630  *      into floats.
28631  *
28632  *    - Source and target may refer to the same underlying buffer, so that
28633  *      the set() operation may overlap.  The specification requires that this
28634  *      must work as if a copy was made before the operation.  Note that this
28635  *      is NOT a simple memmove() situation because the source and target
28636  *      byte sizes may be different -- e.g. a 4-byte source (Int8Array) may
28637  *      expand to a 16-byte target (Uint32Array) so that the target overlaps
28638  *      the source both from beginning and the end (unlike in typical memmove).
28639  *
28640  *    - Even if 'buf' pointers of the source and target differ, there's no
28641  *      guarantee that their memory areas don't overlap.  This may be the
28642  *      case with external buffers.
28643  *
28644  *  Even so, it is nice to optimize for the common case:
28645  *
28646  *    - Source and target separate buffers or non-overlapping.
28647  *
28648  *    - Source and target have a compatible type so that a plain byte copy
28649  *      is possible.  Note that while e.g. uint8 and int8 are compatible
28650  *      (coercion one way or another doesn't change the byte representation),
28651  *      e.g. int8 and uint8clamped are NOT compatible when writing int8
28652  *      values into uint8clamped typedarray (-1 would clamp to 0 for instance).
28653  *
28654  *  See test-bi-typedarray-proto-set.js.
28655  */
28656 
28657 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_typedarray_set(duk_hthread * thr)28658 DUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_hthread *thr) {
28659 	duk_hbufobj *h_this;
28660 	duk_hobject *h_obj;
28661 	duk_uarridx_t i, n;
28662 	duk_int_t offset_signed;
28663 	duk_uint_t offset_elems;
28664 	duk_uint_t offset_bytes;
28665 
28666 	h_this = duk__require_bufobj_this(thr);
28667 	DUK_ASSERT(h_this != NULL);
28668 	DUK_HBUFOBJ_ASSERT_VALID(h_this);
28669 
28670 	if (h_this->buf == NULL) {
28671 		DUK_DDD(DUK_DDDPRINT("source neutered, skip copy"));
28672 		return 0;
28673 	}
28674 
28675 	duk_hbufobj_promote_plain(thr, 0);
28676 	h_obj = duk_require_hobject(thr, 0);
28677 
28678 	/* XXX: V8 throws a TypeError for negative values.  Would it
28679 	 * be more useful to interpret negative offsets here from the
28680 	 * end of the buffer too?
28681 	 */
28682 	offset_signed = duk_to_int(thr, 1);
28683 	if (offset_signed < 0) {
28684 		/* For some reason this is a TypeError (at least in V8). */
28685 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
28686 	}
28687 	offset_elems = (duk_uint_t) offset_signed;
28688 	offset_bytes = offset_elems << h_this->shift;
28689 	if ((offset_bytes >> h_this->shift) != offset_elems) {
28690 		/* Byte length would overflow. */
28691 		/* XXX: easier check with less code? */
28692 		goto fail_args;
28693 	}
28694 	if (offset_bytes > h_this->length) {
28695 		/* Equality may be OK but >length not.  Checking
28696 		 * this explicitly avoids some overflow cases
28697 		 * below.
28698 		 */
28699 		goto fail_args;
28700 	}
28701 	DUK_ASSERT(offset_bytes <= h_this->length);
28702 
28703 	/* Fast path: source is a TypedArray (or any bufobj). */
28704 
28705 	if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
28706 		duk_hbufobj *h_bufarg;
28707 #if !defined(DUK_USE_PREFER_SIZE)
28708 		duk_uint16_t comp_mask;
28709 #endif
28710 		duk_small_int_t no_overlap = 0;
28711 		duk_uint_t src_length;
28712 		duk_uint_t dst_length;
28713 		duk_uint_t dst_length_elems;
28714 		duk_uint8_t *p_src_base;
28715 		duk_uint8_t *p_src_end;
28716 		duk_uint8_t *p_src;
28717 		duk_uint8_t *p_dst_base;
28718 		duk_uint8_t *p_dst;
28719 		duk_small_uint_t src_elem_size;
28720 		duk_small_uint_t dst_elem_size;
28721 
28722 		h_bufarg = (duk_hbufobj *) h_obj;
28723 		DUK_HBUFOBJ_ASSERT_VALID(h_bufarg);
28724 
28725 		if (h_bufarg->buf == NULL) {
28726 			DUK_DDD(DUK_DDDPRINT("target neutered, skip copy"));
28727 			return 0;
28728 		}
28729 
28730 		/* Nominal size check. */
28731 		src_length = h_bufarg->length;  /* bytes in source */
28732 		dst_length_elems = (src_length >> h_bufarg->shift);  /* elems in source and dest */
28733 		dst_length = dst_length_elems << h_this->shift;  /* bytes in dest */
28734 		if ((dst_length >> h_this->shift) != dst_length_elems) {
28735 			/* Byte length would overflow. */
28736 			/* XXX: easier check with less code? */
28737 			goto fail_args;
28738 		}
28739 		DUK_DDD(DUK_DDDPRINT("nominal size check: src_length=%ld, dst_length=%ld",
28740 		                     (long) src_length, (long) dst_length));
28741 		DUK_ASSERT(offset_bytes <= h_this->length);
28742 		if (dst_length > h_this->length - offset_bytes) {
28743 			/* Overflow not an issue because subtraction is used on the right
28744 			 * side and guaranteed to be >= 0.
28745 			 */
28746 			DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length"));
28747 			goto fail_args;
28748 		}
28749 		if (!DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, offset_bytes + dst_length)) {
28750 			DUK_DDD(DUK_DDDPRINT("copy not covered by underlying target buffer, ignore"));
28751 			return 0;
28752 		}
28753 
28754 		p_src_base = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);
28755 		p_dst_base = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + offset_bytes;
28756 
28757 		/* Check actual underlying buffers for validity and that they
28758 		 * cover the copy.  No side effects are allowed after the check
28759 		 * so that the validity status doesn't change.
28760 		 */
28761 		if (!DUK_HBUFOBJ_VALID_SLICE(h_this) ||
28762 		    !DUK_HBUFOBJ_VALID_SLICE(h_bufarg)) {
28763 			/* The condition could be more narrow and check for the
28764 			 * copy area only, but there's no need for fine grained
28765 			 * behavior when the underlying buffer is misconfigured.
28766 			 */
28767 			DUK_DDD(DUK_DDDPRINT("source and/or target not covered by underlying buffer, skip copy"));
28768 			return 0;
28769 		}
28770 
28771 		/* We want to do a straight memory copy if possible: this is
28772 		 * an important operation because .set() is the TypedArray
28773 		 * way to copy chunks of memory.  However, because set()
28774 		 * conceptually works in terms of elements, not all views are
28775 		 * compatible with direct byte copying.
28776 		 *
28777 		 * If we do manage a direct copy, the "overlap issue" handled
28778 		 * below can just be solved using memmove() because the source
28779 		 * and destination element sizes are necessarily equal.
28780 		 */
28781 
28782 #if !defined(DUK_USE_PREFER_SIZE)
28783 		DUK_ASSERT(h_this->elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t));
28784 		comp_mask = duk__buffer_elemtype_copy_compatible[h_this->elem_type];
28785 		if (comp_mask & (1 << h_bufarg->elem_type)) {
28786 			DUK_ASSERT(src_length == dst_length);
28787 
28788 			DUK_DDD(DUK_DDDPRINT("fast path: able to use memmove() because views are compatible"));
28789 			duk_memmove_unsafe((void *) p_dst_base, (const void *) p_src_base, (size_t) dst_length);
28790 			return 0;
28791 		}
28792 		DUK_DDD(DUK_DDDPRINT("fast path: views are not compatible with a byte copy, copy by item"));
28793 #endif  /* !DUK_USE_PREFER_SIZE */
28794 
28795 		/* We want to avoid making a copy to process set() but that's
28796 		 * not always possible: the source and the target may overlap
28797 		 * and because element sizes are different, the overlap cannot
28798 		 * always be handled with a memmove() or choosing the copy
28799 		 * direction in a certain way.  For example, if source type is
28800 		 * uint8 and target type is uint32, the target area may exceed
28801 		 * the source area from both ends!
28802 		 *
28803 		 * Note that because external buffers may point to the same
28804 		 * memory areas, we must ultimately make this check using
28805 		 * pointers.
28806 		 *
28807 		 * NOTE: careful with side effects: any side effect may cause
28808 		 * a buffer resize (or external buffer pointer/length update)!
28809 		 */
28810 
28811 		DUK_DDD(DUK_DDDPRINT("overlap check: p_src_base=%p, src_length=%ld, "
28812 		                     "p_dst_base=%p, dst_length=%ld",
28813 		                     (void *) p_src_base, (long) src_length,
28814 		                     (void *) p_dst_base, (long) dst_length));
28815 
28816 		if (p_src_base >= p_dst_base + dst_length ||  /* source starts after dest ends */
28817 		    p_src_base + src_length <= p_dst_base) {   /* source ends before dest starts */
28818 			no_overlap = 1;
28819 		}
28820 
28821 		if (!no_overlap) {
28822 			/* There's overlap: the desired end result is that
28823 			 * conceptually a copy is made to avoid "trampling"
28824 			 * of source data by destination writes.  We make
28825 			 * an actual temporary copy to handle this case.
28826 			 */
28827 			duk_uint8_t *p_src_copy;
28828 
28829 			DUK_DDD(DUK_DDDPRINT("there is overlap, make a copy of the source"));
28830 			p_src_copy = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, src_length);
28831 			DUK_ASSERT(p_src_copy != NULL);
28832 			duk_memcpy_unsafe((void *) p_src_copy, (const void *) p_src_base, (size_t) src_length);
28833 
28834 			p_src_base = p_src_copy;  /* use p_src_base from now on */
28835 		}
28836 		/* Value stack intentionally mixed size here. */
28837 
28838 		DUK_DDD(DUK_DDDPRINT("after overlap check: p_src_base=%p, src_length=%ld, "
28839 		                     "p_dst_base=%p, dst_length=%ld, valstack top=%ld",
28840 		                     (void *) p_src_base, (long) src_length,
28841 		                     (void *) p_dst_base, (long) dst_length,
28842 		                     (long) duk_get_top(thr)));
28843 
28844 		/* Ready to make the copy.  We must proceed element by element
28845 		 * and must avoid any side effects that might cause the buffer
28846 		 * validity check above to become invalid.
28847 		 *
28848 		 * Although we work through the value stack here, only plain
28849 		 * numbers are handled which should be side effect safe.
28850 		 */
28851 
28852 		src_elem_size = (duk_small_uint_t) (1U << h_bufarg->shift);
28853 		dst_elem_size = (duk_small_uint_t) (1U << h_this->shift);
28854 		p_src = p_src_base;
28855 		p_dst = p_dst_base;
28856 		p_src_end = p_src_base + src_length;
28857 
28858 		while (p_src != p_src_end) {
28859 			DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: "
28860 			                     "p_src=%p, p_src_end=%p, p_dst=%p",
28861 			                     (void *) p_src, (void *) p_src_end, (void *) p_dst));
28862 			/* A validated read() is always a number, so it's write coercion
28863 			 * is always side effect free an won't invalidate pointers etc.
28864 			 */
28865 			duk_hbufobj_push_validated_read(thr, h_bufarg, p_src, src_elem_size);
28866 			duk_hbufobj_validated_write(thr, h_this, p_dst, dst_elem_size);
28867 			duk_pop(thr);
28868 			p_src += src_elem_size;
28869 			p_dst += dst_elem_size;
28870 		}
28871 
28872 		return 0;
28873 	} else {
28874 		/* Slow path: quite slow, but we save space by using the property code
28875 		 * to write coerce target values.  We don't need to worry about overlap
28876 		 * here because the source is not a TypedArray.
28877 		 *
28878 		 * We could use the bufobj write coercion helper but since the
28879 		 * property read may have arbitrary side effects, full validity checks
28880 		 * would be needed for every element anyway.
28881 		 */
28882 
28883 		n = (duk_uarridx_t) duk_get_length(thr, 0);
28884 		DUK_ASSERT(offset_bytes <= h_this->length);
28885 		if ((n << h_this->shift) > h_this->length - offset_bytes) {
28886 			/* Overflow not an issue because subtraction is used on the right
28887 			 * side and guaranteed to be >= 0.
28888 			 */
28889 			DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length"));
28890 			goto fail_args;
28891 		}
28892 
28893 		/* There's no need to check for buffer validity status for the
28894 		 * target here: the property access code will do that for each
28895 		 * element.  Moreover, if we did check the validity here, side
28896 		 * effects from reading the source argument might invalidate
28897 		 * the results anyway.
28898 		 */
28899 
28900 		DUK_ASSERT_TOP(thr, 2);
28901 		duk_push_this(thr);
28902 
28903 		for (i = 0; i < n; i++) {
28904 			duk_get_prop_index(thr, 0, i);
28905 			duk_put_prop_index(thr, 2, offset_elems + i);
28906 		}
28907 	}
28908 
28909 	return 0;
28910 
28911  fail_args:
28912 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
28913 }
28914 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28915 
28916 /*
28917  *  Node.js Buffer.prototype.slice([start], [end])
28918  *  ArrayBuffer.prototype.slice(begin, [end])
28919  *  TypedArray.prototype.subarray(begin, [end])
28920  *
28921  *  The API calls are almost identical; negative indices are counted from end
28922  *  of buffer, and final indices are clamped (allowing crossed indices).  Main
28923  *  differences:
28924  *
28925  *    - Copy/view behavior; Node.js .slice() and TypedArray .subarray() create
28926  *      views, ArrayBuffer .slice() creates a copy
28927  *
28928  *    - Resulting object has a different class and prototype depending on the
28929  *      call (or 'this' argument)
28930  *
28931  *    - TypedArray .subarray() arguments are element indices, not byte offsets
28932  *
28933  *    - Plain buffer argument creates a plain buffer slice
28934  */
28935 
28936 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk__arraybuffer_plain_slice(duk_hthread * thr,duk_hbuffer * h_val)28937 DUK_LOCAL void duk__arraybuffer_plain_slice(duk_hthread *thr, duk_hbuffer *h_val) {
28938 	duk_int_t start_offset, end_offset;
28939 	duk_uint_t slice_length;
28940 	duk_uint8_t *p_copy;
28941 	duk_size_t copy_length;
28942 
28943 	duk__clamp_startend_negidx_shifted(thr,
28944 	                                   (duk_int_t) DUK_HBUFFER_GET_SIZE(h_val),
28945 	                                   0 /*buffer_shift*/,
28946 	                                   0 /*idx_start*/,
28947 	                                   1 /*idx_end*/,
28948 	                                   &start_offset,
28949 	                                   &end_offset);
28950 	DUK_ASSERT(end_offset <= (duk_int_t) DUK_HBUFFER_GET_SIZE(h_val));
28951 	DUK_ASSERT(start_offset >= 0);
28952 	DUK_ASSERT(end_offset >= start_offset);
28953 	slice_length = (duk_uint_t) (end_offset - start_offset);
28954 
28955 	p_copy = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) slice_length);
28956 	DUK_ASSERT(p_copy != NULL);
28957 	copy_length = slice_length;
28958 
28959 	duk_memcpy_unsafe((void *) p_copy,
28960 	                  (const void *) ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_val) + start_offset),
28961 	                  copy_length);
28962 }
28963 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
28964 
28965 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
28966 /* Shared helper for slice/subarray operation.
28967  * Magic: 0x01=isView, 0x02=copy, 0x04=Node.js Buffer special handling.
28968  */
duk_bi_buffer_slice_shared(duk_hthread * thr)28969 DUK_INTERNAL duk_ret_t duk_bi_buffer_slice_shared(duk_hthread *thr) {
28970 	duk_small_int_t magic;
28971 	duk_small_uint_t res_class_num;
28972 	duk_small_int_t res_proto_bidx;
28973 	duk_hbufobj *h_this;
28974 	duk_hbufobj *h_bufobj;
28975 	duk_hbuffer *h_val;
28976 	duk_int_t start_offset, end_offset;
28977 	duk_uint_t slice_length;
28978 	duk_tval *tv;
28979 
28980 	/* [ start end ] */
28981 
28982 	magic = duk_get_current_magic(thr);
28983 
28984 	tv = duk_get_borrowed_this_tval(thr);
28985 	DUK_ASSERT(tv != NULL);
28986 
28987 	if (DUK_TVAL_IS_BUFFER(tv)) {
28988 		/* For plain buffers return a plain buffer slice. */
28989 		h_val = DUK_TVAL_GET_BUFFER(tv);
28990 		DUK_ASSERT(h_val != NULL);
28991 
28992 		if (magic & 0x02) {
28993 			/* Make copy: ArrayBuffer.prototype.slice() uses this. */
28994 			duk__arraybuffer_plain_slice(thr, h_val);
28995 			return 1;
28996 		} else {
28997 			/* View into existing buffer: cannot be done if the
28998 			 * result is a plain buffer because there's no slice
28999 			 * info.  So return an ArrayBuffer instance; coerce
29000 			 * the 'this' binding into an object and behave as if
29001 			 * the original call was for an Object-coerced plain
29002 			 * buffer (handled automatically by duk__require_bufobj_this()).
29003 			 */
29004 
29005 			DUK_DDD(DUK_DDDPRINT("slice() doesn't handle view into plain buffer, coerce 'this' to ArrayBuffer object"));
29006 			/* fall through */
29007 		}
29008 	}
29009 	tv = NULL;  /* No longer valid nor needed. */
29010 
29011 	h_this = duk__require_bufobj_this(thr);
29012 
29013 	/* Slice offsets are element (not byte) offsets, which only matters
29014 	 * for TypedArray views, Node.js Buffer and ArrayBuffer have shift
29015 	 * zero so byte and element offsets are the same.  Negative indices
29016 	 * are counted from end of slice, crossed indices are allowed (and
29017 	 * result in zero length result), and final values are clamped
29018 	 * against the current slice.  There's intentionally no check
29019 	 * against the underlying buffer here.
29020 	 */
29021 
29022 	duk__clamp_startend_negidx_shifted(thr,
29023 	                                   (duk_int_t) h_this->length,
29024 	                                   (duk_uint8_t) h_this->shift,
29025 	                                   0 /*idx_start*/,
29026 	                                   1 /*idx_end*/,
29027 	                                   &start_offset,
29028 	                                   &end_offset);
29029 	DUK_ASSERT(end_offset >= start_offset);
29030 	DUK_ASSERT(start_offset >= 0);
29031 	DUK_ASSERT(end_offset >= 0);
29032 	slice_length = (duk_uint_t) (end_offset - start_offset);
29033 
29034 	/* The resulting buffer object gets the same class and prototype as
29035 	 * the buffer in 'this', e.g. if the input is a Uint8Array the
29036 	 * result is a Uint8Array; if the input is a Float32Array, the
29037 	 * result is a Float32Array.  The result internal prototype should
29038 	 * be the default prototype for the class (e.g. initial value of
29039 	 * Uint8Array.prototype), not copied from the argument (Duktape 1.x
29040 	 * did that).
29041 	 *
29042 	 * Node.js Buffers have special handling: they're Uint8Arrays as far
29043 	 * as the internal class is concerned, so the new Buffer should also
29044 	 * be an Uint8Array but inherit from Buffer.prototype.
29045 	 */
29046 	res_class_num = DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_this);
29047 	DUK_ASSERT(res_class_num >= DUK_HOBJECT_CLASS_BUFOBJ_MIN);  /* type check guarantees */
29048 	DUK_ASSERT(res_class_num <= DUK_HOBJECT_CLASS_BUFOBJ_MAX);
29049 	res_proto_bidx = duk__buffer_proto_from_classnum[res_class_num - DUK_HOBJECT_CLASS_BUFOBJ_MIN];
29050 	if (magic & 0x04) {
29051 		res_proto_bidx = DUK_BIDX_NODEJS_BUFFER_PROTOTYPE;
29052 	}
29053 	h_bufobj = duk_push_bufobj_raw(thr,
29054 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
29055 	                               DUK_HOBJECT_FLAG_BUFOBJ |
29056 	                               DUK_HOBJECT_CLASS_AS_FLAGS(res_class_num),
29057 	                               res_proto_bidx);
29058 	DUK_ASSERT(h_bufobj != NULL);
29059 
29060 	DUK_ASSERT(h_bufobj->length == 0);
29061 	h_bufobj->shift = h_this->shift;  /* inherit */
29062 	h_bufobj->elem_type = h_this->elem_type;  /* inherit */
29063 	h_bufobj->is_typedarray = magic & 0x01;
29064 	DUK_ASSERT(h_bufobj->is_typedarray == 0 || h_bufobj->is_typedarray == 1);
29065 
29066 	h_val = h_this->buf;
29067 	if (h_val == NULL) {
29068 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
29069 	}
29070 
29071 	if (magic & 0x02) {
29072 		/* non-zero: make copy */
29073 		duk_uint8_t *p_copy;
29074 		duk_size_t copy_length;
29075 
29076 		p_copy = (duk_uint8_t *) duk_push_fixed_buffer_zero(thr, (duk_size_t) slice_length);  /* must be zeroed, not all bytes always copied */
29077 		DUK_ASSERT(p_copy != NULL);
29078 
29079 		/* Copy slice, respecting underlying buffer limits; remainder
29080 		 * is left as zero.
29081 		 */
29082 		copy_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, slice_length);
29083 		duk_memcpy_unsafe((void *) p_copy,
29084 		                  (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
29085 		                  copy_length);
29086 
29087 		h_val = duk_known_hbuffer(thr, -1);
29088 
29089 		h_bufobj->buf = h_val;
29090 		DUK_HBUFFER_INCREF(thr, h_val);
29091 		h_bufobj->length = slice_length;
29092 		DUK_ASSERT(h_bufobj->offset == 0);
29093 
29094 		duk_pop(thr);  /* reachable so pop OK */
29095 	} else {
29096 		h_bufobj->buf = h_val;
29097 		DUK_HBUFFER_INCREF(thr, h_val);
29098 		h_bufobj->length = slice_length;
29099 		h_bufobj->offset = h_this->offset + (duk_uint_t) start_offset;
29100 
29101 		/* Copy the .buffer property, needed for TypedArray.prototype.subarray().
29102 		 *
29103 		 * XXX: limit copy only for TypedArray classes specifically?
29104 		 */
29105 
29106 		DUK_ASSERT(h_bufobj->buf_prop == NULL);
29107 		h_bufobj->buf_prop = h_this->buf_prop;  /* may be NULL */
29108 		DUK_HOBJECT_INCREF_ALLOWNULL(thr, (duk_hobject *) h_bufobj->buf_prop);
29109 	}
29110 	/* unbalanced stack on purpose */
29111 
29112 	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
29113 	return 1;
29114 }
29115 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29116 
29117 /*
29118  *  Node.js Buffer.isEncoding()
29119  */
29120 
29121 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_is_encoding(duk_hthread * thr)29122 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_hthread *thr) {
29123 	const char *encoding;
29124 
29125 	/* only accept lowercase 'utf8' now. */
29126 
29127 	encoding = duk_to_string(thr, 0);
29128 	DUK_ASSERT(duk_is_string(thr, 0));  /* guaranteed by duk_to_string() */
29129 	duk_push_boolean(thr, DUK_STRCMP(encoding, "utf8") == 0);
29130 	return 1;
29131 }
29132 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29133 
29134 /*
29135  *  Node.js Buffer.isBuffer()
29136  */
29137 
29138 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_is_buffer(duk_hthread * thr)29139 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_hthread *thr) {
29140 	duk_hobject *h;
29141 	duk_hobject *h_proto;
29142 	duk_bool_t ret = 0;
29143 
29144 	DUK_ASSERT(duk_get_top(thr) >= 1);  /* nargs */
29145 	h = duk_get_hobject(thr, 0);
29146 	if (h != NULL) {
29147 		h_proto = thr->builtins[DUK_BIDX_NODEJS_BUFFER_PROTOTYPE];
29148 		DUK_ASSERT(h_proto != NULL);
29149 
29150 		h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
29151 		if (h != NULL) {
29152 			ret = duk_hobject_prototype_chain_contains(thr, h, h_proto, 0 /*ignore_loop*/);
29153 		}
29154 	}
29155 
29156 	duk_push_boolean(thr, ret);
29157 	return 1;
29158 }
29159 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29160 
29161 /*
29162  *  Node.js Buffer.byteLength()
29163  */
29164 
29165 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_byte_length(duk_hthread * thr)29166 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_hthread *thr) {
29167 	const char *str;
29168 	duk_size_t len;
29169 
29170 	/* At the moment Buffer(<str>) will just use the string bytes as
29171 	 * is (ignoring encoding), so we return the string length here
29172 	 * unconditionally.
29173 	 */
29174 
29175 	/* XXX: to be revised; Old Node.js behavior just coerces any buffer
29176 	 * values to string:
29177 	 * $ node
29178 	 * > Buffer.byteLength(new Uint32Array(10))
29179 	 * 20
29180 	 * > Buffer.byteLength(new Uint32Array(100))
29181 	 * 20
29182 	 * (The 20 comes from '[object Uint32Array]'.length
29183 	 */
29184 
29185 	str = duk_to_lstring(thr, 0, &len);
29186 	DUK_UNREF(str);
29187 	duk_push_size_t(thr, len);
29188 	return 1;
29189 }
29190 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29191 
29192 /*
29193  *  Node.js Buffer.concat()
29194  */
29195 
29196 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_concat(duk_hthread * thr)29197 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_concat(duk_hthread *thr) {
29198 	duk_hobject *h_arg;
29199 	duk_uint_t total_length;
29200 	duk_hbufobj *h_bufobj;
29201 	duk_hbufobj *h_bufres;
29202 	duk_hbuffer *h_val;
29203 	duk_uint_t i, n;
29204 	duk_uint8_t *p;
29205 	duk_size_t space_left;
29206 	duk_size_t copy_size;
29207 
29208 	/* Node.js accepts only actual Arrays. */
29209 	h_arg = duk_require_hobject(thr, 0);
29210 	if (DUK_HOBJECT_GET_CLASS_NUMBER(h_arg) != DUK_HOBJECT_CLASS_ARRAY) {
29211 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
29212 	}
29213 
29214 	/* Compute result length and validate argument buffers. */
29215 	n = (duk_uint_t) duk_get_length(thr, 0);
29216 	total_length = 0;
29217 	for (i = 0; i < n; i++) {
29218 		/* Neutered checks not necessary here: neutered buffers have
29219 		 * zero 'length' so we'll effectively skip them.
29220 		 */
29221 		DUK_ASSERT_TOP(thr, 2);  /* [ array totalLength ] */
29222 		duk_get_prop_index(thr, 0, (duk_uarridx_t) i);  /* -> [ array totalLength buf ] */
29223 		h_bufobj = duk__require_bufobj_value(thr, 2);
29224 		DUK_ASSERT(h_bufobj != NULL);
29225 		total_length += h_bufobj->length;
29226 		if (DUK_UNLIKELY(total_length < h_bufobj->length)) {
29227 			DUK_DCERROR_RANGE_INVALID_ARGS(thr);  /* Wrapped. */
29228 		}
29229 		duk_pop(thr);
29230 	}
29231 	/* In Node.js v0.12.1 a 1-element array is special and won't create a
29232 	 * copy, this was fixed later so an explicit check no longer needed.
29233 	 */
29234 
29235 	/* User totalLength overrides a computed length, but we'll check
29236 	 * every copy in the copy loop.  Note that duk_to_int() can
29237 	 * technically have arbitrary side effects so we need to recheck
29238 	 * the buffers in the copy loop.
29239 	 */
29240 	if (!duk_is_undefined(thr, 1) && n > 0) {
29241 		/* For n == 0, Node.js ignores totalLength argument and
29242 		 * returns a zero length buffer.
29243 		 */
29244 		duk_int_t total_length_signed;
29245 		total_length_signed = duk_to_int(thr, 1);
29246 		if (total_length_signed < 0) {
29247 			DUK_DCERROR_RANGE_INVALID_ARGS(thr);
29248 		}
29249 		total_length = (duk_uint_t) total_length_signed;
29250 	}
29251 
29252 	h_bufres = duk_push_bufobj_raw(thr,
29253 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
29254 	                               DUK_HOBJECT_FLAG_BUFOBJ |
29255 	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_UINT8ARRAY),
29256 	                               DUK_BIDX_NODEJS_BUFFER_PROTOTYPE);
29257 	DUK_ASSERT(h_bufres != NULL);
29258 
29259 	p = (duk_uint8_t *) duk_push_fixed_buffer_zero(thr, total_length);  /* must be zeroed, all bytes not necessarily written over */
29260 	DUK_ASSERT(p != NULL);
29261 	space_left = (duk_size_t) total_length;
29262 
29263 	for (i = 0; i < n; i++) {
29264 		DUK_ASSERT_TOP(thr, 4);  /* [ array totalLength bufres buf ] */
29265 
29266 		duk_get_prop_index(thr, 0, (duk_uarridx_t) i);
29267 		h_bufobj = duk__require_bufobj_value(thr, 4);
29268 		DUK_ASSERT(h_bufobj != NULL);
29269 
29270 		copy_size = h_bufobj->length;
29271 		if (copy_size > space_left) {
29272 			copy_size = space_left;
29273 		}
29274 
29275 		if (h_bufobj->buf != NULL &&
29276 		    DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
29277 			duk_memcpy_unsafe((void *) p,
29278 			                  (const void *) DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj),
29279 			                  copy_size);
29280 		} else {
29281 			/* Just skip, leaving zeroes in the result. */
29282 			;
29283 		}
29284 		p += copy_size;
29285 		space_left -= copy_size;
29286 
29287 		duk_pop(thr);
29288 	}
29289 
29290 	h_val = duk_known_hbuffer(thr, -1);
29291 
29292 	duk__set_bufobj_buffer(thr, h_bufres, h_val);
29293 	h_bufres->is_typedarray = 1;
29294 	DUK_HBUFOBJ_ASSERT_VALID(h_bufres);
29295 
29296 	duk_pop(thr);  /* pop plain buffer, now reachable through h_bufres */
29297 
29298 	return 1;  /* return h_bufres */
29299 }
29300 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29301 
29302 /*
29303  *  Shared readfield and writefield methods
29304  *
29305  *  The readfield/writefield methods need support for endianness and field
29306  *  types.  All offsets are byte based so no offset shifting is needed.
29307  */
29308 
29309 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
29310 /* Format of magic, bits:
29311  *   0...1: field type; 0=uint8, 1=uint16, 2=uint32, 3=float, 4=double, 5=unused, 6=unused, 7=unused
29312  *       3: endianness: 0=little, 1=big
29313  *       4: signed: 1=yes, 0=no
29314  *       5: typedarray: 1=yes, 0=no
29315  */
29316 #define  DUK__FLD_8BIT         0
29317 #define  DUK__FLD_16BIT        1
29318 #define  DUK__FLD_32BIT        2
29319 #define  DUK__FLD_FLOAT        3
29320 #define  DUK__FLD_DOUBLE       4
29321 #define  DUK__FLD_VARINT       5
29322 #define  DUK__FLD_BIGENDIAN    (1 << 3)
29323 #define  DUK__FLD_SIGNED       (1 << 4)
29324 #define  DUK__FLD_TYPEDARRAY   (1 << 5)
29325 
29326 /* XXX: split into separate functions for each field type? */
duk_bi_buffer_readfield(duk_hthread * thr)29327 DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_hthread *thr) {
29328 	duk_small_uint_t magic = (duk_small_uint_t) duk_get_current_magic(thr);
29329 	duk_small_uint_t magic_ftype;
29330 	duk_small_uint_t magic_bigendian;
29331 	duk_small_uint_t magic_signed;
29332 	duk_small_uint_t magic_typedarray;
29333 	duk_small_uint_t endswap;
29334 	duk_hbufobj *h_this;
29335 	duk_bool_t no_assert;
29336 	duk_int_t offset_signed;
29337 	duk_uint_t offset;
29338 	duk_uint_t buffer_length;
29339 	duk_uint_t check_length;
29340 	duk_uint8_t *buf;
29341 	duk_double_union du;
29342 
29343 	magic_ftype = magic & 0x0007U;
29344 	magic_bigendian = magic & 0x0008U;
29345 	magic_signed = magic & 0x0010U;
29346 	magic_typedarray = magic & 0x0020U;
29347 
29348 	h_this = duk__require_bufobj_this(thr);  /* XXX: very inefficient for plain buffers */
29349 	DUK_ASSERT(h_this != NULL);
29350 	buffer_length = h_this->length;
29351 
29352 	/* [ offset noAssert                 ], when ftype != DUK__FLD_VARINT */
29353 	/* [ offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */
29354 	/* [ offset littleEndian             ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */
29355 
29356 	/* Handle TypedArray vs. Node.js Buffer arg differences */
29357 	if (magic_typedarray) {
29358 		no_assert = 0;
29359 #if defined(DUK_USE_INTEGER_LE)
29360 		endswap = !duk_to_boolean(thr, 1);  /* 1=little endian */
29361 #else
29362 		endswap = duk_to_boolean(thr, 1);  /* 1=little endian */
29363 #endif
29364 	} else {
29365 		no_assert = duk_to_boolean(thr, (magic_ftype == DUK__FLD_VARINT) ? 2 : 1);
29366 #if defined(DUK_USE_INTEGER_LE)
29367 		endswap = magic_bigendian;
29368 #else
29369 		endswap = !magic_bigendian;
29370 #endif
29371 	}
29372 
29373 	/* Offset is coerced first to signed integer range and then to unsigned.
29374 	 * This ensures we can add a small byte length (1-8) to the offset in
29375 	 * bound checks and not wrap.
29376 	 */
29377 	offset_signed = duk_to_int(thr, 0);
29378 	offset = (duk_uint_t) offset_signed;
29379 	if (offset_signed < 0) {
29380 		goto fail_bounds;
29381 	}
29382 
29383 	DUK_DDD(DUK_DDDPRINT("readfield, buffer_length=%ld, offset=%ld, no_assert=%d, "
29384 	                     "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
29385 	                     "endswap=%u",
29386 	                     (long) buffer_length, (long) offset, (int) no_assert,
29387 	                     (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),
29388 	                     (int) (magic_signed >> 4), (int) endswap));
29389 
29390 	/* Update 'buffer_length' to be the effective, safe limit which
29391 	 * takes into account the underlying buffer.  This value will be
29392 	 * potentially invalidated by any side effect.
29393 	 */
29394 	check_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, buffer_length);
29395 	DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld",
29396 	                     (long) buffer_length, (long) check_length));
29397 
29398 	if (h_this->buf) {
29399 		buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
29400 	} else {
29401 		/* Neutered.  We could go into the switch-case safely with
29402 		 * buf == NULL because check_length == 0.  To avoid scanbuild
29403 		 * warnings, fail directly instead.
29404 		 */
29405 		DUK_ASSERT(check_length == 0);
29406 		goto fail_neutered;
29407 	}
29408 	DUK_ASSERT(buf != NULL);
29409 
29410 	switch (magic_ftype) {
29411 	case DUK__FLD_8BIT: {
29412 		duk_uint8_t tmp;
29413 		if (offset + 1U > check_length) {
29414 			goto fail_bounds;
29415 		}
29416 		tmp = buf[offset];
29417 		if (magic_signed) {
29418 			duk_push_int(thr, (duk_int_t) ((duk_int8_t) tmp));
29419 		} else {
29420 			duk_push_uint(thr, (duk_uint_t) tmp);
29421 		}
29422 		break;
29423 	}
29424 	case DUK__FLD_16BIT: {
29425 		duk_uint16_t tmp;
29426 		if (offset + 2U > check_length) {
29427 			goto fail_bounds;
29428 		}
29429 		duk_memcpy((void *) du.uc, (const void *) (buf + offset), 2);
29430 		tmp = du.us[0];
29431 		if (endswap) {
29432 			tmp = DUK_BSWAP16(tmp);
29433 		}
29434 		if (magic_signed) {
29435 			duk_push_int(thr, (duk_int_t) ((duk_int16_t) tmp));
29436 		} else {
29437 			duk_push_uint(thr, (duk_uint_t) tmp);
29438 		}
29439 		break;
29440 	}
29441 	case DUK__FLD_32BIT: {
29442 		duk_uint32_t tmp;
29443 		if (offset + 4U > check_length) {
29444 			goto fail_bounds;
29445 		}
29446 		duk_memcpy((void *) du.uc, (const void *) (buf + offset), 4);
29447 		tmp = du.ui[0];
29448 		if (endswap) {
29449 			tmp = DUK_BSWAP32(tmp);
29450 		}
29451 		if (magic_signed) {
29452 			duk_push_int(thr, (duk_int_t) ((duk_int32_t) tmp));
29453 		} else {
29454 			duk_push_uint(thr, (duk_uint_t) tmp);
29455 		}
29456 		break;
29457 	}
29458 	case DUK__FLD_FLOAT: {
29459 		duk_uint32_t tmp;
29460 		if (offset + 4U > check_length) {
29461 			goto fail_bounds;
29462 		}
29463 		duk_memcpy((void *) du.uc, (const void *) (buf + offset), 4);
29464 		if (endswap) {
29465 			tmp = du.ui[0];
29466 			tmp = DUK_BSWAP32(tmp);
29467 			du.ui[0] = tmp;
29468 		}
29469 		duk_push_number(thr, (duk_double_t) du.f[0]);
29470 		break;
29471 	}
29472 	case DUK__FLD_DOUBLE: {
29473 		if (offset + 8U > check_length) {
29474 			goto fail_bounds;
29475 		}
29476 		duk_memcpy((void *) du.uc, (const void *) (buf + offset), 8);
29477 		if (endswap) {
29478 			DUK_DBLUNION_BSWAP64(&du);
29479 		}
29480 		duk_push_number(thr, (duk_double_t) du.d);
29481 		break;
29482 	}
29483 	case DUK__FLD_VARINT: {
29484 		/* Node.js Buffer variable width integer field.  We don't really
29485 		 * care about speed here, so aim for shortest algorithm.
29486 		 */
29487 		duk_int_t field_bytelen;
29488 		duk_int_t i, i_step, i_end;
29489 #if defined(DUK_USE_64BIT_OPS)
29490 		duk_int64_t tmp;
29491 		duk_small_uint_t shift_tmp;
29492 #else
29493 		duk_double_t tmp;
29494 		duk_small_int_t highbyte;
29495 #endif
29496 		const duk_uint8_t *p;
29497 
29498 		field_bytelen = duk_get_int(thr, 1);  /* avoid side effects! */
29499 		if (field_bytelen < 1 || field_bytelen > 6) {
29500 			goto fail_field_length;
29501 		}
29502 		if (offset + (duk_uint_t) field_bytelen > check_length) {
29503 			goto fail_bounds;
29504 		}
29505 		p = (const duk_uint8_t *) (buf + offset);
29506 
29507 		/* Slow gathering of value using either 64-bit arithmetic
29508 		 * or IEEE doubles if 64-bit types not available.  Handling
29509 		 * of negative numbers is a bit non-obvious in both cases.
29510 		 */
29511 
29512 		if (magic_bigendian) {
29513 			/* Gather in big endian */
29514 			i = 0;
29515 			i_step = 1;
29516 			i_end = field_bytelen;  /* one i_step over */
29517 		} else {
29518 			/* Gather in little endian */
29519 			i = field_bytelen - 1;
29520 			i_step = -1;
29521 			i_end = -1;  /* one i_step over */
29522 		}
29523 
29524 #if defined(DUK_USE_64BIT_OPS)
29525 		tmp = 0;
29526 		do {
29527 			DUK_ASSERT(i >= 0 && i < field_bytelen);
29528 			tmp = (tmp << 8) + (duk_int64_t) p[i];
29529 			i += i_step;
29530 		} while (i != i_end);
29531 
29532 		if (magic_signed) {
29533 			/* Shift to sign extend.  Left shift must be unsigned
29534 			 * to avoid undefined behavior; right shift must be
29535 			 * signed to sign extend properly.
29536 			 */
29537 			shift_tmp = (duk_small_uint_t) (64U - (duk_small_uint_t) field_bytelen * 8U);
29538 			tmp = (duk_int64_t) ((duk_uint64_t) tmp << shift_tmp) >> shift_tmp;
29539 		}
29540 
29541 		duk_push_i64(thr, tmp);
29542 #else
29543 		highbyte = p[i];
29544 		if (magic_signed && (highbyte & 0x80) != 0) {
29545 			/* 0xff => 255 - 256 = -1; 0x80 => 128 - 256 = -128 */
29546 			tmp = (duk_double_t) (highbyte - 256);
29547 		} else {
29548 			tmp = (duk_double_t) highbyte;
29549 		}
29550 		for (;;) {
29551 			i += i_step;
29552 			if (i == i_end) {
29553 				break;
29554 			}
29555 			DUK_ASSERT(i >= 0 && i < field_bytelen);
29556 			tmp = (tmp * 256.0) + (duk_double_t) p[i];
29557 		}
29558 
29559 		duk_push_number(thr, tmp);
29560 #endif
29561 		break;
29562 	}
29563 	default: {  /* should never happen but default here */
29564 		goto fail_bounds;
29565 	}
29566 	}
29567 
29568 	return 1;
29569 
29570  fail_neutered:
29571  fail_field_length:
29572  fail_bounds:
29573 	if (no_assert) {
29574 		/* Node.js return value for noAssert out-of-bounds reads is
29575 		 * usually (but not always) NaN.  Return NaN consistently.
29576 		 */
29577 		duk_push_nan(thr);
29578 		return 1;
29579 	}
29580 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
29581 }
29582 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29583 
29584 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
29585 /* XXX: split into separate functions for each field type? */
duk_bi_buffer_writefield(duk_hthread * thr)29586 DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_hthread *thr) {
29587 	duk_small_uint_t magic = (duk_small_uint_t) duk_get_current_magic(thr);
29588 	duk_small_uint_t magic_ftype;
29589 	duk_small_uint_t magic_bigendian;
29590 	duk_small_uint_t magic_signed;
29591 	duk_small_uint_t magic_typedarray;
29592 	duk_small_uint_t endswap;
29593 	duk_hbufobj *h_this;
29594 	duk_bool_t no_assert;
29595 	duk_int_t offset_signed;
29596 	duk_uint_t offset;
29597 	duk_uint_t buffer_length;
29598 	duk_uint_t check_length;
29599 	duk_uint8_t *buf;
29600 	duk_double_union du;
29601 	duk_int_t nbytes = 0;
29602 
29603 	magic_ftype = magic & 0x0007U;
29604 	magic_bigendian = magic & 0x0008U;
29605 	magic_signed = magic & 0x0010U;
29606 	magic_typedarray = magic & 0x0020U;
29607 	DUK_UNREF(magic_signed);
29608 
29609 	h_this = duk__require_bufobj_this(thr);  /* XXX: very inefficient for plain buffers */
29610 	DUK_ASSERT(h_this != NULL);
29611 	buffer_length = h_this->length;
29612 
29613 	/* [ value  offset noAssert                 ], when ftype != DUK__FLD_VARINT */
29614 	/* [ value  offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */
29615 	/* [ offset value  littleEndian             ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */
29616 
29617 	/* Handle TypedArray vs. Node.js Buffer arg differences */
29618 	if (magic_typedarray) {
29619 		no_assert = 0;
29620 #if defined(DUK_USE_INTEGER_LE)
29621 		endswap = !duk_to_boolean(thr, 2);  /* 1=little endian */
29622 #else
29623 		endswap = duk_to_boolean(thr, 2);  /* 1=little endian */
29624 #endif
29625 		duk_swap(thr, 0, 1);  /* offset/value order different from Node.js */
29626 	} else {
29627 		no_assert = duk_to_boolean(thr, (magic_ftype == DUK__FLD_VARINT) ? 3 : 2);
29628 #if defined(DUK_USE_INTEGER_LE)
29629 		endswap = magic_bigendian;
29630 #else
29631 		endswap = !magic_bigendian;
29632 #endif
29633 	}
29634 
29635 	/* Offset is coerced first to signed integer range and then to unsigned.
29636 	 * This ensures we can add a small byte length (1-8) to the offset in
29637 	 * bound checks and not wrap.
29638 	 */
29639 	offset_signed = duk_to_int(thr, 1);
29640 	offset = (duk_uint_t) offset_signed;
29641 
29642 	/* We need 'nbytes' even for a failed offset; return value must be
29643 	 * (offset + nbytes) even when write fails due to invalid offset.
29644 	 */
29645 	if (magic_ftype != DUK__FLD_VARINT) {
29646 		DUK_ASSERT(magic_ftype < (duk_small_uint_t) (sizeof(duk__buffer_nbytes_from_fldtype) / sizeof(duk_uint8_t)));
29647 		nbytes = duk__buffer_nbytes_from_fldtype[magic_ftype];
29648 	} else {
29649 		nbytes = duk_get_int(thr, 2);
29650 		if (nbytes < 1 || nbytes > 6) {
29651 			goto fail_field_length;
29652 		}
29653 	}
29654 	DUK_ASSERT(nbytes >= 1 && nbytes <= 8);
29655 
29656 	/* Now we can check offset validity. */
29657 	if (offset_signed < 0) {
29658 		goto fail_bounds;
29659 	}
29660 
29661 	DUK_DDD(DUK_DDDPRINT("writefield, value=%!T, buffer_length=%ld, offset=%ld, no_assert=%d, "
29662 	                     "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
29663 	                     "endswap=%u",
29664 	                     duk_get_tval(thr, 0), (long) buffer_length, (long) offset, (int) no_assert,
29665 	                     (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),
29666 	                     (int) (magic_signed >> 4), (int) endswap));
29667 
29668 	/* Coerce value to a number before computing check_length, so that
29669 	 * the field type specific coercion below can't have side effects
29670 	 * that would invalidate check_length.
29671 	 */
29672 	duk_to_number(thr, 0);
29673 
29674 	/* Update 'buffer_length' to be the effective, safe limit which
29675 	 * takes into account the underlying buffer.  This value will be
29676 	 * potentially invalidated by any side effect.
29677 	 */
29678 	check_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, buffer_length);
29679 	DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld",
29680 	                     (long) buffer_length, (long) check_length));
29681 
29682 	if (h_this->buf) {
29683 		buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
29684 	} else {
29685 		/* Neutered.  We could go into the switch-case safely with
29686 		 * buf == NULL because check_length == 0.  To avoid scanbuild
29687 		 * warnings, fail directly instead.
29688 		 */
29689 		DUK_ASSERT(check_length == 0);
29690 		goto fail_neutered;
29691 	}
29692 	DUK_ASSERT(buf != NULL);
29693 
29694 	switch (magic_ftype) {
29695 	case DUK__FLD_8BIT: {
29696 		if (offset + 1U > check_length) {
29697 			goto fail_bounds;
29698 		}
29699 		/* sign doesn't matter when writing */
29700 		buf[offset] = (duk_uint8_t) duk_to_uint32(thr, 0);
29701 		break;
29702 	}
29703 	case DUK__FLD_16BIT: {
29704 		duk_uint16_t tmp;
29705 		if (offset + 2U > check_length) {
29706 			goto fail_bounds;
29707 		}
29708 		tmp = (duk_uint16_t) duk_to_uint32(thr, 0);
29709 		if (endswap) {
29710 			tmp = DUK_BSWAP16(tmp);
29711 		}
29712 		du.us[0] = tmp;
29713 		/* sign doesn't matter when writing */
29714 		duk_memcpy((void *) (buf + offset), (const void *) du.uc, 2);
29715 		break;
29716 	}
29717 	case DUK__FLD_32BIT: {
29718 		duk_uint32_t tmp;
29719 		if (offset + 4U > check_length) {
29720 			goto fail_bounds;
29721 		}
29722 		tmp = (duk_uint32_t) duk_to_uint32(thr, 0);
29723 		if (endswap) {
29724 			tmp = DUK_BSWAP32(tmp);
29725 		}
29726 		du.ui[0] = tmp;
29727 		/* sign doesn't matter when writing */
29728 		duk_memcpy((void *) (buf + offset), (const void *) du.uc, 4);
29729 		break;
29730 	}
29731 	case DUK__FLD_FLOAT: {
29732 		duk_uint32_t tmp;
29733 		if (offset + 4U > check_length) {
29734 			goto fail_bounds;
29735 		}
29736 		du.f[0] = (duk_float_t) duk_to_number(thr, 0);
29737 		if (endswap) {
29738 			tmp = du.ui[0];
29739 			tmp = DUK_BSWAP32(tmp);
29740 			du.ui[0] = tmp;
29741 		}
29742 		/* sign doesn't matter when writing */
29743 		duk_memcpy((void *) (buf + offset), (const void *) du.uc, 4);
29744 		break;
29745 	}
29746 	case DUK__FLD_DOUBLE: {
29747 		if (offset + 8U > check_length) {
29748 			goto fail_bounds;
29749 		}
29750 		du.d = (duk_double_t) duk_to_number(thr, 0);
29751 		if (endswap) {
29752 			DUK_DBLUNION_BSWAP64(&du);
29753 		}
29754 		/* sign doesn't matter when writing */
29755 		duk_memcpy((void *) (buf + offset), (const void *) du.uc, 8);
29756 		break;
29757 	}
29758 	case DUK__FLD_VARINT: {
29759 		/* Node.js Buffer variable width integer field.  We don't really
29760 		 * care about speed here, so aim for shortest algorithm.
29761 		 */
29762 		duk_int_t field_bytelen;
29763 		duk_int_t i, i_step, i_end;
29764 #if defined(DUK_USE_64BIT_OPS)
29765 		duk_int64_t tmp;
29766 #else
29767 		duk_double_t tmp;
29768 #endif
29769 		duk_uint8_t *p;
29770 
29771 		field_bytelen = (duk_int_t) nbytes;
29772 		if (offset + (duk_uint_t) field_bytelen > check_length) {
29773 			goto fail_bounds;
29774 		}
29775 
29776 		/* Slow writing of value using either 64-bit arithmetic
29777 		 * or IEEE doubles if 64-bit types not available.  There's
29778 		 * no special sign handling when writing varints.
29779 		 */
29780 
29781 		if (magic_bigendian) {
29782 			/* Write in big endian */
29783 			i = field_bytelen;  /* one i_step added at top of loop */
29784 			i_step = -1;
29785 			i_end = 0;
29786 		} else {
29787 			/* Write in little endian */
29788 			i = -1;  /* one i_step added at top of loop */
29789 			i_step = 1;
29790 			i_end = field_bytelen - 1;
29791 		}
29792 
29793 		/* XXX: The duk_to_number() cast followed by integer coercion
29794 		 * is platform specific so NaN, +/- Infinity, and out-of-bounds
29795 		 * values result in platform specific output now.
29796 		 * See: test-bi-nodejs-buffer-proto-varint-special.js
29797 		 */
29798 
29799 #if defined(DUK_USE_64BIT_OPS)
29800 		tmp = (duk_int64_t) duk_to_number(thr, 0);
29801 		p = (duk_uint8_t *) (buf + offset);
29802 		do {
29803 			i += i_step;
29804 			DUK_ASSERT(i >= 0 && i < field_bytelen);
29805 			p[i] = (duk_uint8_t) (tmp & 0xff);
29806 			tmp = tmp >> 8;  /* unnecessary shift for last byte */
29807 		} while (i != i_end);
29808 #else
29809 		tmp = duk_to_number(thr, 0);
29810 		p = (duk_uint8_t *) (buf + offset);
29811 		do {
29812 			i += i_step;
29813 			tmp = DUK_FLOOR(tmp);
29814 			DUK_ASSERT(i >= 0 && i < field_bytelen);
29815 			p[i] = (duk_uint8_t) (DUK_FMOD(tmp, 256.0));
29816 			tmp = tmp / 256.0;  /* unnecessary div for last byte */
29817 		} while (i != i_end);
29818 #endif
29819 		break;
29820 	}
29821 	default: {  /* should never happen but default here */
29822 		goto fail_bounds;
29823 	}
29824 	}
29825 
29826 	/* Node.js Buffer: return offset + #bytes written (i.e. next
29827 	 * write offset).
29828 	 */
29829 	if (magic_typedarray) {
29830 		/* For TypedArrays 'undefined' return value is specified
29831 		 * by ES2015 (matches V8).
29832 		 */
29833 		return 0;
29834 	}
29835 	duk_push_uint(thr, offset + (duk_uint_t) nbytes);
29836 	return 1;
29837 
29838  fail_neutered:
29839  fail_field_length:
29840  fail_bounds:
29841 	if (no_assert) {
29842 		/* Node.js return value for failed writes is offset + #bytes
29843 		 * that would have been written.
29844 		 */
29845 		/* XXX: for negative input offsets, 'offset' will be a large
29846 		 * positive value so the result here is confusing.
29847 		 */
29848 		if (magic_typedarray) {
29849 			return 0;
29850 		}
29851 		duk_push_uint(thr, offset + (duk_uint_t) nbytes);
29852 		return 1;
29853 	}
29854 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
29855 }
29856 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29857 
29858 /*
29859  *  Accessors for .buffer, .byteLength, .byteOffset
29860  */
29861 
29862 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk__autospawn_arraybuffer(duk_hthread * thr,duk_hbuffer * h_buf)29863 DUK_LOCAL duk_hbufobj *duk__autospawn_arraybuffer(duk_hthread *thr, duk_hbuffer *h_buf) {
29864 	duk_hbufobj *h_res;
29865 
29866 	h_res = duk_push_bufobj_raw(thr,
29867 	                            DUK_HOBJECT_FLAG_EXTENSIBLE |
29868 	                            DUK_HOBJECT_FLAG_BUFOBJ |
29869 	                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
29870 	                            DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
29871 	DUK_ASSERT(h_res != NULL);
29872 	DUK_UNREF(h_res);
29873 
29874 	duk__set_bufobj_buffer(thr, h_res, h_buf);
29875 	DUK_HBUFOBJ_ASSERT_VALID(h_res);
29876 	DUK_ASSERT(h_res->buf_prop == NULL);
29877 	return h_res;
29878 }
29879 
duk_bi_typedarray_buffer_getter(duk_hthread * thr)29880 DUK_INTERNAL duk_ret_t duk_bi_typedarray_buffer_getter(duk_hthread *thr) {
29881 	duk_hbufobj *h_bufobj;
29882 
29883 	h_bufobj = (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW /*flags*/);
29884 	DUK_ASSERT(h_bufobj != NULL);
29885 	if (DUK_HEAPHDR_IS_BUFFER((duk_heaphdr *) h_bufobj)) {
29886 		DUK_DD(DUK_DDPRINT("autospawn ArrayBuffer for plain buffer"));
29887 		(void) duk__autospawn_arraybuffer(thr, (duk_hbuffer *) h_bufobj);
29888 		return 1;
29889 	} else {
29890 		if (h_bufobj->buf_prop == NULL &&
29891 		    DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_bufobj) != DUK_HOBJECT_CLASS_ARRAYBUFFER &&
29892 		    h_bufobj->buf != NULL) {
29893 			duk_hbufobj *h_arrbuf;
29894 
29895 			DUK_DD(DUK_DDPRINT("autospawn ArrayBuffer for typed array or DataView"));
29896 			h_arrbuf = duk__autospawn_arraybuffer(thr, h_bufobj->buf);
29897 
29898 			if (h_bufobj->buf_prop == NULL) {
29899 				/* Must recheck buf_prop, in case ArrayBuffer
29900 				 * alloc had a side effect which already filled
29901 				 * it!
29902 				 */
29903 
29904 				/* Set ArrayBuffer's .byteOffset and .byteLength based
29905 				 * on the view so that Arraybuffer[view.byteOffset]
29906 				 * matches view[0].
29907 				 */
29908 				h_arrbuf->offset = 0;
29909 				DUK_ASSERT(h_bufobj->offset + h_bufobj->length >= h_bufobj->offset);  /* Wrap check on creation. */
29910 				h_arrbuf->length = h_bufobj->offset + h_bufobj->length;
29911 				DUK_ASSERT(h_arrbuf->buf_prop == NULL);
29912 
29913 				DUK_ASSERT(h_bufobj->buf_prop == NULL);
29914 				h_bufobj->buf_prop = (duk_hobject *) h_arrbuf;
29915 				DUK_HBUFOBJ_INCREF(thr, h_arrbuf);  /* Now reachable and accounted for. */
29916 			}
29917 
29918 			/* Left on stack; pushed for the second time below (OK). */
29919 		}
29920 		if (h_bufobj->buf_prop) {
29921 			duk_push_hobject(thr, h_bufobj->buf_prop);
29922 			return 1;
29923 		}
29924 	}
29925 	return 0;
29926 }
29927 
duk_bi_typedarray_byteoffset_getter(duk_hthread * thr)29928 DUK_INTERNAL duk_ret_t duk_bi_typedarray_byteoffset_getter(duk_hthread *thr) {
29929 	duk_hbufobj *h_bufobj;
29930 
29931 	h_bufobj = (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW /*flags*/);
29932 	DUK_ASSERT(h_bufobj != NULL);
29933 	if (DUK_HEAPHDR_IS_BUFFER((duk_heaphdr *) h_bufobj)) {
29934 		duk_push_uint(thr, 0);
29935 	} else {
29936 		/* If neutered must return 0; offset is zeroed during
29937 		 * neutering.
29938 		 */
29939 		duk_push_uint(thr, h_bufobj->offset);
29940 	}
29941 	return 1;
29942 }
29943 
duk_bi_typedarray_bytelength_getter(duk_hthread * thr)29944 DUK_INTERNAL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_hthread *thr) {
29945 	duk_hbufobj *h_bufobj;
29946 
29947 	h_bufobj = (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW /*flags*/);
29948 	DUK_ASSERT(h_bufobj != NULL);
29949 	if (DUK_HEAPHDR_IS_BUFFER((duk_heaphdr *) h_bufobj)) {
29950 		duk_hbuffer *h_buf;
29951 
29952 		h_buf = (duk_hbuffer *) h_bufobj;
29953 		DUK_ASSERT(DUK_HBUFFER_GET_SIZE(h_buf) <= DUK_UINT_MAX);  /* Buffer limits. */
29954 		duk_push_uint(thr, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_buf));
29955 	} else {
29956 		/* If neutered must return 0; length is zeroed during
29957 		 * neutering.
29958 		 */
29959 		duk_push_uint(thr, h_bufobj->length);
29960 	}
29961 	return 1;
29962 }
29963 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29964 /* No .buffer getter without ArrayBuffer support. */
29965 #if 0
29966 DUK_INTERNAL duk_ret_t duk_bi_typedarray_buffer_getter(duk_hthread *thr) {
29967 	return 0;
29968 }
29969 #endif
29970 
duk_bi_typedarray_byteoffset_getter(duk_hthread * thr)29971 DUK_INTERNAL duk_ret_t duk_bi_typedarray_byteoffset_getter(duk_hthread *thr) {
29972 	duk_push_uint(thr, 0);
29973 	return 1;
29974 }
29975 
duk_bi_typedarray_bytelength_getter(duk_hthread * thr)29976 DUK_INTERNAL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_hthread *thr) {
29977 	duk_hbuffer *h_buf;
29978 
29979 	/* XXX: helper? */
29980 	duk_push_this(thr);
29981 	h_buf = duk_require_hbuffer(thr, -1);
29982 	duk_push_uint(thr, DUK_HBUFFER_GET_SIZE(h_buf));
29983 	return 1;
29984 }
29985 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29986 
29987 /* automatic undefs */
29988 #undef DUK__BUFOBJ_FLAG_PROMOTE
29989 #undef DUK__BUFOBJ_FLAG_THROW
29990 #undef DUK__FLD_16BIT
29991 #undef DUK__FLD_32BIT
29992 #undef DUK__FLD_8BIT
29993 #undef DUK__FLD_BIGENDIAN
29994 #undef DUK__FLD_DOUBLE
29995 #undef DUK__FLD_FLOAT
29996 #undef DUK__FLD_SIGNED
29997 #undef DUK__FLD_TYPEDARRAY
29998 #undef DUK__FLD_VARINT
29999 /*
30000  *  CBOR bindings.
30001  *
30002  *  http://cbor.io/
30003  *  https://tools.ietf.org/html/rfc7049
30004  */
30005 
30006 /* #include duk_internal.h -> already included */
30007 
30008 #if defined(DUK_USE_CBOR_SUPPORT)
30009 
30010 /* #define DUK_CBOR_STRESS */
30011 
30012 /* Default behavior for encoding strings: use CBOR text string if string
30013  * is UTF-8 compatible, otherwise use CBOR byte string.  These defines
30014  * can be used to force either type for all strings.  Using text strings
30015  * for non-UTF-8 data is technically invalid CBOR.
30016  */
30017 /* #define DUK_CBOR_TEXT_STRINGS */
30018 /* #define DUK_CBOR_BYTE_STRINGS */
30019 
30020 /* Misc. defines. */
30021 /* #define DUK_CBOR_PREFER_SIZE */
30022 /* #define DUK_CBOR_DOUBLE_AS_IS */
30023 /* #define DUK_CBOR_DECODE_FASTPATH */
30024 
30025 typedef struct {
30026 	duk_hthread *thr;
30027 	duk_uint8_t *ptr;
30028 	duk_uint8_t *buf;
30029 	duk_uint8_t *buf_end;
30030 	duk_size_t len;
30031 	duk_idx_t idx_buf;
30032 	duk_uint_t recursion_depth;
30033 	duk_uint_t recursion_limit;
30034 } duk_cbor_encode_context;
30035 
30036 typedef struct {
30037 	duk_hthread *thr;
30038 	const duk_uint8_t *buf;
30039 	duk_size_t off;
30040 	duk_size_t len;
30041 	duk_uint_t recursion_depth;
30042 	duk_uint_t recursion_limit;
30043 } duk_cbor_decode_context;
30044 
30045 DUK_LOCAL void duk__cbor_encode_value(duk_cbor_encode_context *enc_ctx);
30046 DUK_LOCAL void duk__cbor_decode_value(duk_cbor_decode_context *dec_ctx);
30047 
30048 /*
30049  *  Misc
30050  */
30051 
duk__cbor_double_to_uint32(double d)30052 DUK_LOCAL duk_uint32_t duk__cbor_double_to_uint32(double d) {
30053 	/* Out of range casts are undefined behavior, so caller must avoid. */
30054 	DUK_ASSERT(d >= 0.0 && d <= 4294967295.0);
30055 	return (duk_uint32_t) d;
30056 }
30057 
30058 /*
30059  *  Encoding
30060  */
30061 
duk__cbor_encode_error(duk_cbor_encode_context * enc_ctx)30062 DUK_LOCAL void duk__cbor_encode_error(duk_cbor_encode_context *enc_ctx) {
30063 	(void) duk_type_error(enc_ctx->thr, "cbor encode error");
30064 }
30065 
duk__cbor_encode_req_stack(duk_cbor_encode_context * enc_ctx)30066 DUK_LOCAL void duk__cbor_encode_req_stack(duk_cbor_encode_context *enc_ctx) {
30067 	duk_require_stack(enc_ctx->thr, 4);
30068 }
30069 
duk__cbor_encode_objarr_entry(duk_cbor_encode_context * enc_ctx)30070 DUK_LOCAL void duk__cbor_encode_objarr_entry(duk_cbor_encode_context *enc_ctx) {
30071 	duk_hthread *thr = enc_ctx->thr;
30072 
30073 	/* Native stack check in object/array recursion. */
30074 	duk_native_stack_check(thr);
30075 
30076 	/* When working with deeply recursive structures, this is important
30077 	 * to ensure there's no effective depth limit.
30078 	 */
30079 	duk__cbor_encode_req_stack(enc_ctx);
30080 
30081 	DUK_ASSERT(enc_ctx->recursion_depth <= enc_ctx->recursion_limit);
30082 	if (enc_ctx->recursion_depth >= enc_ctx->recursion_limit) {
30083 		DUK_ERROR_RANGE(thr, DUK_STR_ENC_RECLIMIT);
30084 		DUK_WO_NORETURN(return;);
30085 	}
30086 	enc_ctx->recursion_depth++;
30087 }
30088 
duk__cbor_encode_objarr_exit(duk_cbor_encode_context * enc_ctx)30089 DUK_LOCAL void duk__cbor_encode_objarr_exit(duk_cbor_encode_context *enc_ctx) {
30090 	DUK_ASSERT(enc_ctx->recursion_depth > 0);
30091 	enc_ctx->recursion_depth--;
30092 }
30093 
30094 /* Check that a size_t is in uint32 range to avoid out-of-range casts. */
duk__cbor_encode_sizet_uint32_check(duk_cbor_encode_context * enc_ctx,duk_size_t len)30095 DUK_LOCAL void duk__cbor_encode_sizet_uint32_check(duk_cbor_encode_context *enc_ctx, duk_size_t len) {
30096 	if (DUK_UNLIKELY(sizeof(duk_size_t) > sizeof(duk_uint32_t) && len > (duk_size_t) DUK_UINT32_MAX)) {
30097 		duk__cbor_encode_error(enc_ctx);
30098 	}
30099 }
30100 
duk__cbor_encode_ensure_slowpath(duk_cbor_encode_context * enc_ctx,duk_size_t len)30101 DUK_LOCAL DUK_NOINLINE void duk__cbor_encode_ensure_slowpath(duk_cbor_encode_context *enc_ctx, duk_size_t len) {
30102 	duk_size_t oldlen;
30103 	duk_size_t minlen;
30104 	duk_size_t newlen;
30105 	duk_uint8_t *p_new;
30106 	duk_size_t old_data_len;
30107 
30108 	DUK_ASSERT(enc_ctx->ptr >= enc_ctx->buf);
30109 	DUK_ASSERT(enc_ctx->buf_end >= enc_ctx->ptr);
30110 	DUK_ASSERT(enc_ctx->buf_end >= enc_ctx->buf);
30111 
30112 	/* Overflow check.
30113 	 *
30114 	 * Limit example: 0xffffffffUL / 2U = 0x7fffffffUL, we reject >= 0x80000000UL.
30115 	 */
30116 	oldlen = enc_ctx->len;
30117 	minlen = oldlen + len;
30118 	if (DUK_UNLIKELY(oldlen > DUK_SIZE_MAX / 2U || minlen < oldlen)) {
30119 		duk__cbor_encode_error(enc_ctx);
30120 	}
30121 
30122 #if defined(DUK_CBOR_STRESS)
30123 	newlen = oldlen + 1U;
30124 #else
30125 	newlen = oldlen * 2U;
30126 #endif
30127 	DUK_ASSERT(newlen >= oldlen);
30128 
30129 	if (minlen > newlen) {
30130 		newlen = minlen;
30131 	}
30132 	DUK_ASSERT(newlen >= oldlen);
30133 	DUK_ASSERT(newlen >= minlen);
30134 	DUK_ASSERT(newlen > 0U);
30135 
30136 	DUK_DD(DUK_DDPRINT("cbor encode buffer resized to %ld", (long) newlen));
30137 
30138 	p_new = (duk_uint8_t *) duk_resize_buffer(enc_ctx->thr, enc_ctx->idx_buf, newlen);
30139 	DUK_ASSERT(p_new != NULL);
30140 	old_data_len = (duk_size_t) (enc_ctx->ptr - enc_ctx->buf);
30141 	enc_ctx->buf = p_new;
30142 	enc_ctx->buf_end = p_new + newlen;
30143 	enc_ctx->ptr = p_new + old_data_len;
30144 	enc_ctx->len = newlen;
30145 }
30146 
duk__cbor_encode_ensure(duk_cbor_encode_context * enc_ctx,duk_size_t len)30147 DUK_LOCAL DUK_INLINE void duk__cbor_encode_ensure(duk_cbor_encode_context *enc_ctx, duk_size_t len) {
30148 	if (DUK_LIKELY((duk_size_t) (enc_ctx->buf_end - enc_ctx->ptr) >= len)) {
30149 		return;
30150 	}
30151 	duk__cbor_encode_ensure_slowpath(enc_ctx, len);
30152 }
30153 
duk__cbor_get_reserve(duk_cbor_encode_context * enc_ctx)30154 DUK_LOCAL duk_size_t duk__cbor_get_reserve(duk_cbor_encode_context *enc_ctx) {
30155 	DUK_ASSERT(enc_ctx->ptr >= enc_ctx->buf);
30156 	DUK_ASSERT(enc_ctx->ptr <= enc_ctx->buf_end);
30157 	return (duk_size_t) (enc_ctx->buf_end - enc_ctx->ptr);
30158 }
30159 
duk__cbor_encode_uint32(duk_cbor_encode_context * enc_ctx,duk_uint32_t u,duk_uint8_t base)30160 DUK_LOCAL void duk__cbor_encode_uint32(duk_cbor_encode_context *enc_ctx, duk_uint32_t u, duk_uint8_t base) {
30161 	duk_uint8_t *p;
30162 
30163 	/* Caller must ensure space. */
30164 	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 4);
30165 
30166 	p = enc_ctx->ptr;
30167 	if (DUK_LIKELY(u <= 23U)) {
30168 		*p++ = (duk_uint8_t) (base + (duk_uint8_t) u);
30169 	} else if (u <= 0xffUL) {
30170 		*p++ = base + 0x18U;
30171 		*p++ = (duk_uint8_t) u;
30172 	} else if (u <= 0xffffUL) {
30173 		*p++ = base + 0x19U;
30174 		DUK_RAW_WRITEINC_U16_BE(p, (duk_uint16_t) u);
30175 	} else {
30176 		*p++ = base + 0x1aU;
30177 		DUK_RAW_WRITEINC_U32_BE(p, u);
30178 	}
30179 	enc_ctx->ptr = p;
30180 }
30181 
30182 #if defined(DUK_CBOR_DOUBLE_AS_IS)
duk__cbor_encode_double(duk_cbor_encode_context * enc_ctx,double d)30183 DUK_LOCAL void duk__cbor_encode_double(duk_cbor_encode_context *enc_ctx, double d) {
30184 	duk_uint8_t *p;
30185 
30186 	/* Caller must ensure space. */
30187 	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
30188 
30189 	p = enc_ctx->ptr;
30190 	*p++ = 0xfbU;
30191 	DUK_RAW_WRITEINC_DOUBLE_BE(p, d);
30192 	p += 8;
30193 	enc_ctx->ptr = p;
30194 }
30195 #else  /* DUK_CBOR_DOUBLE_AS_IS */
duk__cbor_encode_double_fp(duk_cbor_encode_context * enc_ctx,double d)30196 DUK_LOCAL void duk__cbor_encode_double_fp(duk_cbor_encode_context *enc_ctx, double d) {
30197 	duk_double_union u;
30198 	duk_uint16_t u16;
30199 	duk_int16_t expt;
30200 	duk_uint8_t *p;
30201 
30202 	DUK_ASSERT(DUK_FPCLASSIFY(d) != DUK_FP_ZERO);
30203 
30204 	/* Caller must ensure space. */
30205 	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
30206 
30207 	/* Organize into little endian (no-op if platform is little endian). */
30208 	u.d = d;
30209 	duk_dblunion_host_to_little(&u);
30210 
30211 	/* Check if 'd' can represented as a normal half-float.
30212 	 * Denormal half-floats could also be used, but that check
30213 	 * isn't done now (denormal half-floats are decoded of course).
30214 	 * So just check exponent range and that at most 10 significant
30215 	 * bits (excluding implicit leading 1) are used in 'd'.
30216 	 */
30217 	u16 = (((duk_uint16_t) u.uc[7]) << 8) | ((duk_uint16_t) u.uc[6]);
30218 	expt = (duk_int16_t) ((u16 & 0x7ff0U) >> 4) - 1023;
30219 
30220 	if (expt >= -14 && expt <= 15) {
30221 		/* Half-float normal exponents (excl. denormals).
30222 		 *
30223 		 *          7        6        5        4        3        2        1        0  (LE index)
30224 		 * double: seeeeeee eeeemmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm
30225 		 * half:         seeeee mmmm mmmmmm00 00000000 00000000 00000000 00000000 00000000
30226 		 */
30227 		duk_bool_t use_half_float;
30228 
30229 		use_half_float =
30230 		    (u.uc[0] == 0 && u.uc[1] == 0 && u.uc[2] == 0 && u.uc[3] == 0 &&
30231 		     u.uc[4] == 0 && (u.uc[5] & 0x03U) == 0);
30232 
30233 		if (use_half_float) {
30234 			duk_uint32_t t;
30235 
30236 			expt += 15;
30237 			t = (duk_uint32_t) (u.uc[7] & 0x80U) << 8;
30238 			t += (duk_uint32_t) expt << 10;
30239 			t += ((duk_uint32_t) u.uc[6] & 0x0fU) << 6;
30240 			t += ((duk_uint32_t) u.uc[5]) >> 2;
30241 
30242 			/* seeeeemm mmmmmmmm */
30243 			p = enc_ctx->ptr;
30244 			*p++ = 0xf9U;
30245 			DUK_RAW_WRITEINC_U16_BE(p, (duk_uint16_t) t);
30246 			enc_ctx->ptr = p;
30247 			return;
30248 		}
30249 	}
30250 
30251 	/* Same check for plain float.  Also no denormal support here. */
30252 	if (expt >= -126 && expt <= 127) {
30253 		/* Float normal exponents (excl. denormals).
30254 		 *
30255 		 * double: seeeeeee eeeemmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm
30256 		 * float:     seeee eeeemmmm mmmmmmmm mmmmmmmm mmm00000 00000000 00000000 00000000
30257 		 */
30258 		duk_bool_t use_float;
30259 		duk_float_t d_float;
30260 
30261 		/* We could do this explicit mantissa check, but doing
30262 		 * a double-float-double cast is fine because we've
30263 		 * already verified that the exponent is in range so
30264 		 * that the narrower cast is not undefined behavior.
30265 		 */
30266 #if 0
30267 		use_float =
30268 		    (u.uc[0] == 0 && u.uc[1] == 0 && u.uc[2] == 0 && (u.uc[3] & 0xe0U) == 0);
30269 #endif
30270 		d_float = (duk_float_t) d;
30271 		use_float = duk_double_equals((duk_double_t) d_float, d);
30272 		if (use_float) {
30273 			p = enc_ctx->ptr;
30274 			*p++ = 0xfaU;
30275 			DUK_RAW_WRITEINC_FLOAT_BE(p, d_float);
30276 			enc_ctx->ptr = p;
30277 			return;
30278 		}
30279 	}
30280 
30281 	/* Special handling for NaN and Inf which we want to encode as
30282 	 * half-floats.  They share the same (maximum) exponent.
30283 	 */
30284 	if (expt == 1024) {
30285 		DUK_ASSERT(DUK_ISNAN(d) || DUK_ISINF(d));
30286 		p = enc_ctx->ptr;
30287 		*p++ = 0xf9U;
30288 		if (DUK_ISNAN(d)) {
30289 			/* Shortest NaN encoding is using a half-float.  Lose the
30290 			 * exact NaN bits in the process.  IEEE double would be
30291 			 * 7ff8 0000 0000 0000, i.e. a quiet NaN in most architectures
30292 			 * (https://en.wikipedia.org/wiki/NaN#Encoding).  The
30293 			 * equivalent half float is 7e00.
30294 			 */
30295 			*p++ = 0x7eU;
30296 		} else {
30297 			/* Shortest +/- Infinity encoding is using a half-float. */
30298 			if (DUK_SIGNBIT(d)) {
30299 				*p++ = 0xfcU;
30300 			} else {
30301 				*p++ = 0x7cU;
30302 			}
30303 		}
30304 		*p++ = 0x00U;
30305 		enc_ctx->ptr = p;
30306 		return;
30307 	}
30308 
30309 	/* Cannot use half-float or float, encode as full IEEE double. */
30310 	p = enc_ctx->ptr;
30311 	*p++ = 0xfbU;
30312 	DUK_RAW_WRITEINC_DOUBLE_BE(p, d);
30313 	enc_ctx->ptr = p;
30314 }
30315 
duk__cbor_encode_double(duk_cbor_encode_context * enc_ctx,double d)30316 DUK_LOCAL void duk__cbor_encode_double(duk_cbor_encode_context *enc_ctx, double d) {
30317 	duk_uint8_t *p;
30318 	double d_floor;
30319 
30320 	/* Integers and floating point values of all types are conceptually
30321 	 * equivalent in CBOR.  Try to always choose the shortest encoding
30322 	 * which is not always immediately obvious.  For example, NaN and Inf
30323 	 * can be most compactly represented as a half-float (assuming NaN
30324 	 * bits are not preserved), and 0x1'0000'0000 as a single precision
30325 	 * float.  Shortest forms in preference order (prefer integer over
30326 	 * float when equal length):
30327 	 *
30328 	 *   uint        1 byte    [0,23] (not -0)
30329 	 *   sint        1 byte    [-24,-1]
30330 	 *   uint+1      2 bytes   [24,255]
30331 	 *   sint+1      2 bytes   [-256,-25]
30332 	 *   uint+2      3 bytes   [256,65535]
30333 	 *   sint+2      3 bytes   [-65536,-257]
30334 	 *   half-float  3 bytes   -0, NaN, +/- Infinity, range [-65504,65504]
30335 	 *   uint+4      5 bytes   [65536,4294967295]
30336 	 *   sint+4      5 bytes   [-4294967296,-258]
30337 	 *   float       5 bytes   range [-(1 - 2^(-24)) * 2^128, (1 - 2^(-24)) * 2^128]
30338 	 *   uint+8      9 bytes   [4294967296,18446744073709551615]
30339 	 *   sint+8      9 bytes   [-18446744073709551616,-4294967297]
30340 	 *   double      9 bytes
30341 	 *
30342 	 * For whole numbers (compatible with integers):
30343 	 *   - 1-byte or 2-byte uint/sint representation is preferred for
30344 	 *     [-256,255].
30345 	 *   - 3-byte uint/sint is preferred for [-65536,65535].  Half floats
30346 	 *     are never preferred because they have the same length.
30347 	 *   - 5-byte uint/sint is preferred for [-4294967296,4294967295].
30348 	 *     Single precision floats are never preferred, and half-floats
30349 	 *     don't reach above the 3-byte uint/sint range so they're never
30350 	 *     preferred.
30351 	 *   - So, for all integers up to signed/unsigned 32-bit range the
30352 	 *     preferred encoding is always an integer uint/sint.
30353 	 *   - For integers above 32 bits the situation is more complicated.
30354 	 *     Half-floats are never useful for them because of their limited
30355 	 *     range, but IEEE single precision floats (5 bytes encoded) can
30356 	 *     represent some integers between the 32-bit and 64-bit ranges
30357 	 *     which require 9 bytes as a uint/sint.
30358 	 *
30359 	 * For floating point values not compatible with integers, the
30360 	 * preferred encoding is quite clear:
30361 	 *   - For +Inf/-Inf use half-float.
30362 	 *   - For NaN use a half-float, assuming NaN bits ("payload") is
30363 	 *     not worth preserving.  Duktape doesn't in general guarantee
30364 	 *     preservation of the NaN payload so using a half-float seems
30365 	 *     consistent with that.
30366 	 *   - For remaining values, prefer the shortest form which doesn't
30367 	 *     lose any precision.  For normal half-floats and single precision
30368 	 *     floats this is simple: just check exponent and mantissa bits
30369 	 *     using a fixed mask.  For denormal half-floats and single
30370 	 *     precision floats the check is a bit more complicated: a normal
30371 	 *     IEEE double can sometimes be represented as a denormal
30372 	 *     half-float or single precision float.
30373 	 *
30374 	 * https://en.wikipedia.org/wiki/Half-precision_floating-point_format#IEEE_754_half-precision_binary_floating-point_format:_binary16
30375 	 */
30376 
30377 	/* Caller must ensure space. */
30378 	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
30379 
30380 	/* Most important path is integers.  The floor() test will be true
30381 	 * for Inf too (but not NaN).
30382 	 */
30383 	d_floor = DUK_FLOOR(d);  /* identity if d is +/- 0.0, NaN, or +/- Infinity */
30384 	if (DUK_LIKELY(duk_double_equals(d_floor, d) != 0)) {
30385 		DUK_ASSERT(!DUK_ISNAN(d));  /* NaN == NaN compares false. */
30386 		if (DUK_SIGNBIT(d)) {
30387 			if (d >= -4294967296.0) {
30388 				d = -1.0 - d;
30389 				if (d >= 0.0) {
30390 					DUK_ASSERT(d >= 0.0);
30391 					duk__cbor_encode_uint32(enc_ctx, duk__cbor_double_to_uint32(d), 0x20U);
30392 					return;
30393 				}
30394 
30395 				/* Input was negative zero, d == -1.0 < 0.0.
30396 				 * Shortest -0 is using half-float.
30397 				 */
30398 				p = enc_ctx->ptr;
30399 				*p++ = 0xf9U;
30400 				*p++ = 0x80U;
30401 				*p++ = 0x00U;
30402 				enc_ctx->ptr = p;
30403 				return;
30404 			}
30405 		} else {
30406 			if (d <= 4294967295.0) {
30407 				/* Positive zero needs no special handling. */
30408 				DUK_ASSERT(d >= 0.0);
30409 				duk__cbor_encode_uint32(enc_ctx, duk__cbor_double_to_uint32(d), 0x00U);
30410 				return;
30411 			}
30412 		}
30413 	}
30414 
30415 	/* 64-bit integers are not supported at present.  So
30416 	 * we also don't need to deal with choosing between a
30417 	 * 64-bit uint/sint representation vs. IEEE double or
30418 	 * float.
30419 	 */
30420 
30421 	DUK_ASSERT(DUK_FPCLASSIFY(d) != DUK_FP_ZERO);
30422 	duk__cbor_encode_double_fp(enc_ctx, d);
30423 }
30424 #endif  /* DUK_CBOR_DOUBLE_AS_IS */
30425 
duk__cbor_encode_string_top(duk_cbor_encode_context * enc_ctx)30426 DUK_LOCAL void duk__cbor_encode_string_top(duk_cbor_encode_context *enc_ctx) {
30427 	const duk_uint8_t *str;
30428 	duk_size_t len;
30429 	duk_uint8_t *p;
30430 
30431 	/* CBOR differentiates between UTF-8 text strings and byte strings.
30432 	 * Text strings MUST be valid UTF-8, so not all Duktape strings can
30433 	 * be encoded as valid CBOR text strings.  Possible behaviors:
30434 	 *
30435 	 *   1. Use text string when input is valid UTF-8, otherwise use
30436 	 *      byte string (maybe tagged to indicate it was an extended
30437 	 *      UTF-8 string).
30438 	 *   2. Always use text strings, but sanitize input string so that
30439 	 *      invalid UTF-8 is replaced with U+FFFD for example.  Combine
30440 	 *      surrogates whenever possible.
30441 	 *   3. Always use byte strings.  This is simple and produces valid
30442 	 *      CBOR, but isn't ideal for interoperability.
30443 	 *   4. Always use text strings, even for invalid UTF-8 such as
30444 	 *      codepoints in the surrogate pair range.  This is simple but
30445 	 *      produces technically invalid CBOR for non-UTF-8 strings which
30446 	 *      may affect interoperability.
30447 	 *
30448 	 * Current default is 1; can be changed with defines.
30449 	 */
30450 
30451 	/* Caller must ensure space. */
30452 	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
30453 
30454 	str = (const duk_uint8_t *) duk_require_lstring(enc_ctx->thr, -1, &len);
30455 	if (duk_is_symbol(enc_ctx->thr, -1)) {
30456 		/* Symbols, encode as an empty table for now.  This matches
30457 		 * the behavior of cbor-js.
30458 		 *
30459 		 * XXX: Maybe encode String() coercion with a tag?
30460 		 * XXX: Option to keep enough information to recover
30461 		 * Symbols when decoding (this is not always desirable).
30462 		 */
30463 		p = enc_ctx->ptr;
30464 		*p++ = 0xa0U;
30465 		enc_ctx->ptr = p;
30466 		return;
30467 	}
30468 
30469 	duk__cbor_encode_sizet_uint32_check(enc_ctx, len);
30470 #if defined(DUK_CBOR_TEXT_STRINGS)
30471 	duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x60U);
30472 #elif defined(DUK_CBOR_BYTE_STRINGS)
30473 	duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x40U);
30474 #else
30475 	duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len,
30476 	                        (DUK_LIKELY(duk_unicode_is_utf8_compatible(str, len) != 0) ? 0x60U : 0x40U));
30477 #endif
30478 	duk__cbor_encode_ensure(enc_ctx, len);
30479 	p = enc_ctx->ptr;
30480 	duk_memcpy((void *) p, (const void *) str, len);
30481 	p += len;
30482 	enc_ctx->ptr = p;
30483 }
30484 
duk__cbor_encode_object(duk_cbor_encode_context * enc_ctx)30485 DUK_LOCAL void duk__cbor_encode_object(duk_cbor_encode_context *enc_ctx) {
30486 	duk_uint8_t *buf;
30487 	duk_size_t len;
30488 	duk_uint8_t *p;
30489 	duk_size_t i;
30490 	duk_size_t off_ib;
30491 	duk_uint32_t count;
30492 
30493 	/* Caller must ensure space. */
30494 	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
30495 
30496 	duk__cbor_encode_objarr_entry(enc_ctx);
30497 
30498 	/* XXX: Support for specific built-ins like Date and RegExp. */
30499 	if (duk_is_array(enc_ctx->thr, -1)) {
30500 		/* Shortest encoding for arrays >= 256 in length is actually
30501 		 * the indefinite length one (3 or more bytes vs. 2 bytes).
30502 		 * We still use the definite length version because it is
30503 		 * more decoding friendly.
30504 		 */
30505 		len = duk_get_length(enc_ctx->thr, -1);
30506 		duk__cbor_encode_sizet_uint32_check(enc_ctx, len);
30507 		duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x80U);
30508 		for (i = 0; i < len; i++) {
30509 			duk_get_prop_index(enc_ctx->thr, -1, (duk_uarridx_t) i);
30510 			duk__cbor_encode_value(enc_ctx);
30511 		}
30512 	} else if (duk_is_buffer_data(enc_ctx->thr, -1)) {
30513 		/* XXX: Tag buffer data?
30514 		 * XXX: Encode typed arrays as integer arrays rather
30515 		 * than buffer data as is?
30516 		 */
30517 		buf = (duk_uint8_t *) duk_require_buffer_data(enc_ctx->thr, -1, &len);
30518 		duk__cbor_encode_sizet_uint32_check(enc_ctx, len);
30519 		duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x40U);
30520 		duk__cbor_encode_ensure(enc_ctx, len);
30521 		p = enc_ctx->ptr;
30522 		duk_memcpy_unsafe((void *) p, (const void *) buf, len);
30523 		p += len;
30524 		enc_ctx->ptr = p;
30525 	} else {
30526 		/* We don't know the number of properties in advance
30527 		 * but would still like to encode at least small
30528 		 * objects without indefinite length.  Emit an
30529 		 * indefinite length byte initially, and if the final
30530 		 * property count is small enough to also fit in one
30531 		 * byte, backpatch it later.  Otherwise keep the
30532 		 * indefinite length.  This works well up to 23
30533 		 * properties which is practical and good enough.
30534 		 */
30535 		off_ib = (duk_size_t) (enc_ctx->ptr - enc_ctx->buf);  /* XXX: get_offset? */
30536 		count = 0U;
30537 		p = enc_ctx->ptr;
30538 		*p++ = 0xa0U + 0x1fU;  /* indefinite length */
30539 		enc_ctx->ptr = p;
30540 		duk_enum(enc_ctx->thr, -1, DUK_ENUM_OWN_PROPERTIES_ONLY);
30541 		while (duk_next(enc_ctx->thr, -1, 1 /*get_value*/)) {
30542 			duk_insert(enc_ctx->thr, -2);  /* [ ... key value ] -> [ ... value key ] */
30543 			duk__cbor_encode_value(enc_ctx);
30544 			duk__cbor_encode_value(enc_ctx);
30545 			count++;
30546 			if (count == 0U) {
30547 				duk__cbor_encode_error(enc_ctx);
30548 			}
30549 		}
30550 		duk_pop(enc_ctx->thr);
30551 		if (count <= 0x17U) {
30552 			DUK_ASSERT(off_ib < enc_ctx->len);
30553 			enc_ctx->buf[off_ib] = 0xa0U + (duk_uint8_t) count;
30554 		} else {
30555 			duk__cbor_encode_ensure(enc_ctx, 1);
30556 			p = enc_ctx->ptr;
30557 			*p++ = 0xffU;  /* break */
30558 			enc_ctx->ptr = p;
30559 		}
30560 	}
30561 
30562 	duk__cbor_encode_objarr_exit(enc_ctx);
30563 }
30564 
duk__cbor_encode_buffer(duk_cbor_encode_context * enc_ctx)30565 DUK_LOCAL void duk__cbor_encode_buffer(duk_cbor_encode_context *enc_ctx) {
30566 	duk_uint8_t *buf;
30567 	duk_size_t len;
30568 	duk_uint8_t *p;
30569 
30570 	/* Caller must ensure space. */
30571 	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
30572 
30573 	/* Tag buffer data? */
30574 	buf = (duk_uint8_t *) duk_require_buffer(enc_ctx->thr, -1, &len);
30575 	duk__cbor_encode_sizet_uint32_check(enc_ctx, len);
30576 	duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x40U);
30577 	duk__cbor_encode_ensure(enc_ctx, len);
30578 	p = enc_ctx->ptr;
30579 	duk_memcpy_unsafe((void *) p, (const void *) buf, len);
30580 	p += len;
30581 	enc_ctx->ptr = p;
30582 }
30583 
duk__cbor_encode_pointer(duk_cbor_encode_context * enc_ctx)30584 DUK_LOCAL void duk__cbor_encode_pointer(duk_cbor_encode_context *enc_ctx) {
30585 	/* Pointers (void *) are challenging to encode.  They can't
30586 	 * be relied to be even 64-bit integer compatible (there are
30587 	 * pointer models larger than that), nor can floats encode
30588 	 * them.  They could be encoded as strings (%p format) but
30589 	 * that's not portable.  They could be encoded as direct memory
30590 	 * representations.  Recovering pointers is non-portable in any
30591 	 * case but it would be nice to be able to detect and recover
30592 	 * compatible pointers.
30593 	 *
30594 	 * For now, encode as "(%p)" string, matching JX.  There doesn't
30595 	 * seem to be an appropriate tag, so pointers don't currently
30596 	 * survive a CBOR encode/decode roundtrip intact.
30597 	 */
30598 	const char *ptr;
30599 
30600 	ptr = duk_to_string(enc_ctx->thr, -1);
30601 	DUK_ASSERT(ptr != NULL);
30602 	duk_push_sprintf(enc_ctx->thr, "(%s)", ptr);
30603 	duk_remove(enc_ctx->thr, -2);
30604 	duk__cbor_encode_string_top(enc_ctx);
30605 }
30606 
duk__cbor_encode_lightfunc(duk_cbor_encode_context * enc_ctx)30607 DUK_LOCAL void duk__cbor_encode_lightfunc(duk_cbor_encode_context *enc_ctx) {
30608 	duk_uint8_t *p;
30609 
30610 	/* Caller must ensure space. */
30611 	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
30612 
30613 	/* For now encode as an empty object. */
30614 	p = enc_ctx->ptr;
30615 	*p++ = 0xa0U;
30616 	enc_ctx->ptr = p;
30617 }
30618 
duk__cbor_encode_value(duk_cbor_encode_context * enc_ctx)30619 DUK_LOCAL void duk__cbor_encode_value(duk_cbor_encode_context *enc_ctx) {
30620 	duk_uint8_t *p;
30621 
30622 	/* Encode/decode cycle currently loses some type information.
30623 	 * This can be improved by registering custom tags with IANA.
30624 	 */
30625 
30626 	/* Reserve space for up to 64-bit types (1 initial byte + 8
30627 	 * followup bytes).  This allows encoding of integers, floats,
30628 	 * string/buffer length fields, etc without separate checks
30629 	 * in each code path.
30630 	 */
30631 	duk__cbor_encode_ensure(enc_ctx, 1 + 8);
30632 
30633 	switch (duk_get_type(enc_ctx->thr, -1)) {
30634 	case DUK_TYPE_UNDEFINED: {
30635 		p = enc_ctx->ptr;
30636 		*p++ = 0xf7;
30637 		enc_ctx->ptr = p;
30638 		break;
30639 	}
30640 	case DUK_TYPE_NULL: {
30641 		p = enc_ctx->ptr;
30642 		*p++ = 0xf6;
30643 		enc_ctx->ptr = p;
30644 		break;
30645 	}
30646 	case DUK_TYPE_BOOLEAN: {
30647 		duk_uint8_t u8 = duk_get_boolean(enc_ctx->thr, -1) ? 0xf5U : 0xf4U;
30648 		p = enc_ctx->ptr;
30649 		*p++ = u8;
30650 		enc_ctx->ptr = p;
30651 		break;
30652 	}
30653 	case DUK_TYPE_NUMBER: {
30654 		duk__cbor_encode_double(enc_ctx, duk_get_number(enc_ctx->thr, -1));
30655 		break;
30656 	}
30657 	case DUK_TYPE_STRING: {
30658 		duk__cbor_encode_string_top(enc_ctx);
30659 		break;
30660 	}
30661 	case DUK_TYPE_OBJECT: {
30662 		duk__cbor_encode_object(enc_ctx);
30663 		break;
30664 	}
30665 	case DUK_TYPE_BUFFER: {
30666 		duk__cbor_encode_buffer(enc_ctx);
30667 		break;
30668 	}
30669 	case DUK_TYPE_POINTER: {
30670 		duk__cbor_encode_pointer(enc_ctx);
30671 		break;
30672 	}
30673 	case DUK_TYPE_LIGHTFUNC: {
30674 		duk__cbor_encode_lightfunc(enc_ctx);
30675 		break;
30676 	}
30677 	case DUK_TYPE_NONE:
30678 	default:
30679 		goto fail;
30680 	}
30681 
30682 	duk_pop(enc_ctx->thr);
30683 	return;
30684 
30685  fail:
30686 	duk__cbor_encode_error(enc_ctx);
30687 }
30688 
30689 /*
30690  *  Decoding
30691  */
30692 
duk__cbor_decode_error(duk_cbor_decode_context * dec_ctx)30693 DUK_LOCAL void duk__cbor_decode_error(duk_cbor_decode_context *dec_ctx) {
30694 	(void) duk_type_error(dec_ctx->thr, "cbor decode error");
30695 }
30696 
duk__cbor_decode_req_stack(duk_cbor_decode_context * dec_ctx)30697 DUK_LOCAL void duk__cbor_decode_req_stack(duk_cbor_decode_context *dec_ctx) {
30698 	duk_require_stack(dec_ctx->thr, 4);
30699 }
30700 
duk__cbor_decode_objarr_entry(duk_cbor_decode_context * dec_ctx)30701 DUK_LOCAL void duk__cbor_decode_objarr_entry(duk_cbor_decode_context *dec_ctx) {
30702 	duk_hthread *thr = dec_ctx->thr;
30703 
30704 	/* Native stack check in object/array recursion. */
30705 	duk_native_stack_check(thr);
30706 
30707 	duk__cbor_decode_req_stack(dec_ctx);
30708 
30709 	DUK_ASSERT(dec_ctx->recursion_depth <= dec_ctx->recursion_limit);
30710 	if (dec_ctx->recursion_depth >= dec_ctx->recursion_limit) {
30711 		DUK_ERROR_RANGE(thr, DUK_STR_DEC_RECLIMIT);
30712 		DUK_WO_NORETURN(return;);
30713 	}
30714 	dec_ctx->recursion_depth++;
30715 }
30716 
duk__cbor_decode_objarr_exit(duk_cbor_decode_context * dec_ctx)30717 DUK_LOCAL void duk__cbor_decode_objarr_exit(duk_cbor_decode_context *dec_ctx) {
30718 	DUK_ASSERT(dec_ctx->recursion_depth > 0);
30719 	dec_ctx->recursion_depth--;
30720 }
30721 
duk__cbor_decode_readbyte(duk_cbor_decode_context * dec_ctx)30722 DUK_LOCAL duk_uint8_t duk__cbor_decode_readbyte(duk_cbor_decode_context *dec_ctx) {
30723 	DUK_ASSERT(dec_ctx->off <= dec_ctx->len);
30724 	if (DUK_UNLIKELY(dec_ctx->len - dec_ctx->off < 1U)) {
30725 		duk__cbor_decode_error(dec_ctx);
30726 	}
30727 	return dec_ctx->buf[dec_ctx->off++];
30728 }
30729 
duk__cbor_decode_read_u16(duk_cbor_decode_context * dec_ctx)30730 DUK_LOCAL duk_uint16_t duk__cbor_decode_read_u16(duk_cbor_decode_context *dec_ctx) {
30731 	duk_uint16_t res;
30732 
30733 	DUK_ASSERT(dec_ctx->off <= dec_ctx->len);
30734 	if (DUK_UNLIKELY(dec_ctx->len - dec_ctx->off < 2U)) {
30735 		duk__cbor_decode_error(dec_ctx);
30736 	}
30737 	res = DUK_RAW_READ_U16_BE(dec_ctx->buf + dec_ctx->off);
30738 	dec_ctx->off += 2;
30739 	return res;
30740 }
30741 
duk__cbor_decode_read_u32(duk_cbor_decode_context * dec_ctx)30742 DUK_LOCAL duk_uint32_t duk__cbor_decode_read_u32(duk_cbor_decode_context *dec_ctx) {
30743 	duk_uint32_t res;
30744 
30745 	DUK_ASSERT(dec_ctx->off <= dec_ctx->len);
30746 	if (DUK_UNLIKELY(dec_ctx->len - dec_ctx->off < 4U)) {
30747 		duk__cbor_decode_error(dec_ctx);
30748 	}
30749 	res = DUK_RAW_READ_U32_BE(dec_ctx->buf + dec_ctx->off);
30750 	dec_ctx->off += 4;
30751 	return res;
30752 }
30753 
duk__cbor_decode_peekbyte(duk_cbor_decode_context * dec_ctx)30754 DUK_LOCAL duk_uint8_t duk__cbor_decode_peekbyte(duk_cbor_decode_context *dec_ctx) {
30755 	if (DUK_UNLIKELY(dec_ctx->off >= dec_ctx->len)) {
30756 		duk__cbor_decode_error(dec_ctx);
30757 	}
30758 	return dec_ctx->buf[dec_ctx->off];
30759 }
30760 
duk__cbor_decode_rewind(duk_cbor_decode_context * dec_ctx,duk_size_t len)30761 DUK_LOCAL void duk__cbor_decode_rewind(duk_cbor_decode_context *dec_ctx, duk_size_t len) {
30762 	DUK_ASSERT(len <= dec_ctx->off);  /* Caller must ensure. */
30763 	dec_ctx->off -= len;
30764 }
30765 
30766 #if 0
30767 DUK_LOCAL void duk__cbor_decode_ensure(duk_cbor_decode_context *dec_ctx, duk_size_t len) {
30768 	if (dec_ctx->off + len > dec_ctx->len) {
30769 		duk__cbor_decode_error(dec_ctx);
30770 	}
30771 }
30772 #endif
30773 
duk__cbor_decode_consume(duk_cbor_decode_context * dec_ctx,duk_size_t len)30774 DUK_LOCAL const duk_uint8_t *duk__cbor_decode_consume(duk_cbor_decode_context *dec_ctx, duk_size_t len) {
30775 	DUK_ASSERT(dec_ctx->off <= dec_ctx->len);
30776 	if (DUK_LIKELY(dec_ctx->len - dec_ctx->off >= len)) {
30777 		const duk_uint8_t *res = dec_ctx->buf + dec_ctx->off;
30778 		dec_ctx->off += len;
30779 		return res;
30780 	}
30781 
30782 	duk__cbor_decode_error(dec_ctx);  /* Not enough input. */
30783 	return NULL;
30784 }
30785 
duk__cbor_decode_checkbreak(duk_cbor_decode_context * dec_ctx)30786 DUK_LOCAL int duk__cbor_decode_checkbreak(duk_cbor_decode_context *dec_ctx) {
30787 	if (duk__cbor_decode_peekbyte(dec_ctx) == 0xffU) {
30788 		DUK_ASSERT(dec_ctx->off < dec_ctx->len);
30789 		dec_ctx->off++;
30790 #if 0
30791 		(void) duk__cbor_decode_readbyte(dec_ctx);
30792 #endif
30793 		return 1;
30794 	}
30795 	return 0;
30796 }
30797 
duk__cbor_decode_push_aival_int(duk_cbor_decode_context * dec_ctx,duk_uint8_t ib,duk_bool_t negative)30798 DUK_LOCAL void duk__cbor_decode_push_aival_int(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_bool_t negative) {
30799 	duk_uint8_t ai;
30800 	duk_uint32_t t, t1, t2;
30801 #if 0
30802 	duk_uint64_t t3;
30803 #endif
30804 	duk_double_t d1, d2;
30805 	duk_double_t d;
30806 
30807 	ai = ib & 0x1fU;
30808 	if (ai <= 0x17U) {
30809 		t = ai;
30810 		goto shared_exit;
30811 	}
30812 
30813 	switch (ai) {
30814 	case 0x18U:  /* 1 byte */
30815 		t = (duk_uint32_t) duk__cbor_decode_readbyte(dec_ctx);
30816 		goto shared_exit;
30817 	case 0x19U:  /* 2 byte */
30818 		t = (duk_uint32_t) duk__cbor_decode_read_u16(dec_ctx);
30819 		goto shared_exit;
30820 	case 0x1aU:  /* 4 byte */
30821 		t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
30822 		goto shared_exit;
30823 	case 0x1bU:  /* 8 byte */
30824 		/* For uint64 it's important to handle the -1.0 part before
30825 		 * casting to double: otherwise the adjustment might be lost
30826 		 * in the cast.  Uses: -1.0 - d <=> -(d + 1.0).
30827 		 */
30828 		t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
30829 		t2 = t;
30830 		t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
30831 		t1 = t;
30832 #if 0
30833 		t3 = (duk_uint64_t) t2 * DUK_U64_CONSTANT(0x100000000) + (duk_uint64_t) t1;
30834 		if (negative) {
30835 			if (t3 == DUK_UINT64_MAX) {
30836 				/* -(0xffff'ffff'ffff'ffffULL + 1) =
30837 				 * -0x1'0000'0000'0000'0000
30838 				 *
30839 				 * >>> -0x10000000000000000
30840 				 * -18446744073709551616L
30841 				 */
30842 				return -18446744073709551616.0;
30843 			} else {
30844 				return -((duk_double_t) (t3 + DUK_U64_CONSTANT(1)));
30845 			}
30846 		} else {
30847 			return (duk_double_t) t3;  /* XXX: cast helper */
30848 		}
30849 #endif
30850 #if 0
30851 		t3 = (duk_uint64_t) t2 * DUK_U64_CONSTANT(0x100000000) + (duk_uint64_t) t1;
30852 		if (negative) {
30853 			/* Simpler version: take advantage of the fact that
30854 			 * 0xffff'ffff'ffff'ffff and 0x1'0000'0000'0000'0000
30855 			 * both round to 0x1'0000'0000'0000'0000:
30856 			 * > (0xffffffffffffffff).toString(16)
30857 			 * '10000000000000000'
30858 			 * > (0x10000000000000000).toString(16)
30859 			 * '10000000000000000'
30860 			 *
30861 			 * For the DUK_UINT64_MAX case we just skip the +1
30862 			 * increment to avoid wrapping; the result still
30863 			 * comes out right for an IEEE double cast.
30864 			 */
30865 			if (t3 != DUK_UINT64_MAX) {
30866 				t3++;
30867 			}
30868 			return -((duk_double_t) t3);
30869 		} else {
30870 			return (duk_double_t) t3;  /* XXX: cast helper */
30871 		}
30872 #endif
30873 #if 1
30874 		/* Use two double parts, avoids dependency on 64-bit type.
30875 		 * Avoid precision loss carefully, especially when dealing
30876 		 * with the required +1 for negative values.
30877 		 *
30878 		 * No fastint check for this path at present.
30879 		 */
30880 		d1 = (duk_double_t) t1;  /* XXX: cast helpers */
30881 		d2 = (duk_double_t) t2 * 4294967296.0;
30882 		if (negative) {
30883 			d1 += 1.0;
30884 		}
30885 		d = d2 + d1;
30886 		if (negative) {
30887 			d = -d;
30888 		}
30889 #endif
30890 		/* XXX: a push and check for fastint API would be nice */
30891 		duk_push_number(dec_ctx->thr, d);
30892 		return;
30893 	}
30894 
30895 	duk__cbor_decode_error(dec_ctx);
30896 	return;
30897 
30898  shared_exit:
30899 	if (negative) {
30900 		/* XXX: a push and check for fastint API would be nice */
30901 		if ((duk_uint_t) t <= (duk_uint_t) -(DUK_INT_MIN + 1)) {
30902 			duk_push_int(dec_ctx->thr, -1 - ((duk_int_t) t));
30903 		} else {
30904 			duk_push_number(dec_ctx->thr, -1.0 - (duk_double_t) t);
30905 		}
30906 	} else {
30907 		duk_push_uint(dec_ctx->thr, (duk_uint_t) t);
30908 	}
30909 }
30910 
duk__cbor_decode_skip_aival_int(duk_cbor_decode_context * dec_ctx,duk_uint8_t ib)30911 DUK_LOCAL void duk__cbor_decode_skip_aival_int(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib) {
30912 	const duk_int8_t skips[32] = {
30913 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
30914 		0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 8, -1, -1, -1, -1
30915 	};
30916 	duk_uint8_t ai;
30917 	duk_int8_t skip;
30918 
30919 	ai = ib & 0x1fU;
30920 	skip = skips[ai];
30921 	if (DUK_UNLIKELY(skip < 0)) {
30922 		duk__cbor_decode_error(dec_ctx);
30923 	}
30924 	duk__cbor_decode_consume(dec_ctx, (duk_size_t) skip);
30925 	return;
30926 }
30927 
duk__cbor_decode_aival_uint32(duk_cbor_decode_context * dec_ctx,duk_uint8_t ib)30928 DUK_LOCAL duk_uint32_t duk__cbor_decode_aival_uint32(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib) {
30929 	duk_uint8_t ai;
30930 	duk_uint32_t t;
30931 
30932 	ai = ib & 0x1fU;
30933 	if (ai <= 0x17U) {
30934 		return (duk_uint32_t) ai;
30935 	}
30936 
30937 	switch (ai) {
30938 	case 0x18U:  /* 1 byte */
30939 		t = (duk_uint32_t) duk__cbor_decode_readbyte(dec_ctx);
30940 		return t;
30941 	case 0x19U:  /* 2 byte */
30942 		t = (duk_uint32_t) duk__cbor_decode_read_u16(dec_ctx);
30943 		return t;
30944 	case 0x1aU:  /* 4 byte */
30945 		t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
30946 		return t;
30947 	case 0x1bU:  /* 8 byte */
30948 		t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
30949 		if (t != 0U) {
30950 			break;
30951 		}
30952 		t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
30953 		return t;
30954 	}
30955 
30956 	duk__cbor_decode_error(dec_ctx);
30957 	return 0U;
30958 }
30959 
duk__cbor_decode_buffer(duk_cbor_decode_context * dec_ctx,duk_uint8_t expected_base)30960 DUK_LOCAL void duk__cbor_decode_buffer(duk_cbor_decode_context *dec_ctx, duk_uint8_t expected_base) {
30961 	duk_uint32_t len;
30962 	duk_uint8_t *buf;
30963 	const duk_uint8_t *inp;
30964 	duk_uint8_t ib;
30965 
30966 	ib = duk__cbor_decode_readbyte(dec_ctx);
30967 	if ((ib & 0xe0U) != expected_base) {
30968 		duk__cbor_decode_error(dec_ctx);
30969 	}
30970 	/* Indefinite format is rejected by the following on purpose. */
30971 	len = duk__cbor_decode_aival_uint32(dec_ctx, ib);
30972 	inp = duk__cbor_decode_consume(dec_ctx, len);
30973 	/* XXX: duk_push_fixed_buffer_with_data() would be a nice API addition. */
30974 	buf = (duk_uint8_t *) duk_push_fixed_buffer(dec_ctx->thr, (duk_size_t) len);
30975 	duk_memcpy((void *) buf, (const void *) inp, (size_t) len);
30976 }
30977 
duk__cbor_decode_join_buffers(duk_cbor_decode_context * dec_ctx,duk_idx_t count)30978 DUK_LOCAL void duk__cbor_decode_join_buffers(duk_cbor_decode_context *dec_ctx, duk_idx_t count) {
30979 	duk_size_t total_size = 0;
30980 	duk_idx_t top = duk_get_top(dec_ctx->thr);
30981 	duk_idx_t base = top - count;  /* count is >= 1 */
30982 	duk_idx_t idx;
30983 	duk_uint8_t *p = NULL;
30984 
30985 	DUK_ASSERT(count >= 1);
30986 	DUK_ASSERT(top >= count);
30987 
30988 	for (;;) {
30989 		/* First round: compute total size.
30990 		 * Second round: copy into place.
30991 		 */
30992 		for (idx = base; idx < top; idx++) {
30993 			duk_uint8_t *buf_data;
30994 			duk_size_t buf_size;
30995 
30996 			buf_data = (duk_uint8_t *) duk_require_buffer(dec_ctx->thr, idx, &buf_size);
30997 			if (p != NULL) {
30998 				duk_memcpy_unsafe((void *) p, (const void *) buf_data, buf_size);
30999 				p += buf_size;
31000 			} else {
31001 				total_size += buf_size;
31002 				if (DUK_UNLIKELY(total_size < buf_size)) {  /* Wrap check. */
31003 					duk__cbor_decode_error(dec_ctx);
31004 				}
31005 			}
31006 		}
31007 
31008 		if (p != NULL) {
31009 			break;
31010 		} else {
31011 			p = (duk_uint8_t *) duk_push_fixed_buffer(dec_ctx->thr, total_size);
31012 			DUK_ASSERT(p != NULL);
31013 		}
31014 	}
31015 
31016 	duk_replace(dec_ctx->thr, base);
31017 	duk_pop_n(dec_ctx->thr, count - 1);
31018 }
31019 
duk__cbor_decode_and_join_strbuf(duk_cbor_decode_context * dec_ctx,duk_uint8_t expected_base)31020 DUK_LOCAL void duk__cbor_decode_and_join_strbuf(duk_cbor_decode_context *dec_ctx, duk_uint8_t expected_base) {
31021 	duk_idx_t count = 0;
31022 	for (;;) {
31023 		if (duk__cbor_decode_checkbreak(dec_ctx)) {
31024 			break;
31025 		}
31026 		duk_require_stack(dec_ctx->thr, 1);
31027 		duk__cbor_decode_buffer(dec_ctx, expected_base);
31028 		count++;
31029 		if (DUK_UNLIKELY(count <= 0)) {  /* Wrap check. */
31030 			duk__cbor_decode_error(dec_ctx);
31031 		}
31032 	}
31033 	if (count == 0) {
31034 		(void) duk_push_fixed_buffer(dec_ctx->thr, 0);
31035 	} else if (count > 1) {
31036 		duk__cbor_decode_join_buffers(dec_ctx, count);
31037 	}
31038 }
31039 
duk__cbor_decode_half_float(duk_cbor_decode_context * dec_ctx)31040 DUK_LOCAL duk_double_t duk__cbor_decode_half_float(duk_cbor_decode_context *dec_ctx) {
31041 	duk_double_union u;
31042 	const duk_uint8_t *inp;
31043 	duk_int_t expt;
31044 	duk_uint_t u16;
31045 	duk_uint_t tmp;
31046 	duk_double_t res;
31047 
31048 	inp = duk__cbor_decode_consume(dec_ctx, 2);
31049 	u16 = ((duk_uint_t) inp[0] << 8) + (duk_uint_t) inp[1];
31050 	expt = (duk_int_t) ((u16 >> 10) & 0x1fU) - 15;
31051 
31052 	/* Reconstruct IEEE double into little endian order first, then convert
31053 	 * to host order.
31054 	 */
31055 
31056 	duk_memzero((void *) &u, sizeof(u));
31057 
31058 	if (expt == -15) {
31059 		/* Zero or denormal; but note that half float
31060 		 * denormals become double normals.
31061 		 */
31062 		if ((u16 & 0x03ffU) == 0) {
31063 			u.uc[7] = inp[0] & 0x80U;
31064 		} else {
31065 			/* Create denormal by first creating a double that
31066 			 * contains the denormal bits and a leading implicit
31067 			 * 1-bit.  Then subtract away the implicit 1-bit.
31068 			 *
31069 			 *    0.mmmmmmmmmm * 2^-14
31070 			 *    1.mmmmmmmmmm 0.... * 2^-14
31071 			 *   -1.0000000000 0.... * 2^-14
31072 			 *
31073 			 * Double exponent: -14 + 1023 = 0x3f1
31074 			 */
31075 			u.uc[7] = 0x3fU;
31076 			u.uc[6] = 0x10U + (duk_uint8_t) ((u16 >> 6) & 0x0fU);
31077 			u.uc[5] = (duk_uint8_t) ((u16 << 2) & 0xffU);  /* Mask is really 0xfcU */
31078 
31079 			duk_dblunion_little_to_host(&u);
31080 			res = u.d - 0.00006103515625;  /* 2^(-14) */
31081 			if (u16 & 0x8000U) {
31082 				res = -res;
31083 			}
31084 			return res;
31085 		}
31086 	} else if (expt == 16) {
31087 		/* +/- Inf or NaN. */
31088 		if ((u16 & 0x03ffU) == 0) {
31089 			u.uc[7] = (inp[0] & 0x80U) + 0x7fU;
31090 			u.uc[6] = 0xf0U;
31091 		} else {
31092 			/* Create a 'quiet NaN' with highest
31093 			 * bit set (there are some platforms
31094 			 * where the NaN payload convention is
31095 			 * the opposite).  Keep sign.
31096 			 */
31097 			u.uc[7] = (inp[0] & 0x80U) + 0x7fU;
31098 			u.uc[6] = 0xf8U;
31099 		}
31100 	} else {
31101 		/* Normal. */
31102 		tmp = (inp[0] & 0x80U) ? 0x80000000UL : 0UL;
31103 		tmp += (duk_uint_t) (expt + 1023) << 20;
31104 		tmp += (duk_uint_t) (inp[0] & 0x03U) << 18;
31105 		tmp += (duk_uint_t) (inp[1] & 0xffU) << 10;
31106 		u.uc[7] = (tmp >> 24) & 0xffU;
31107 		u.uc[6] = (tmp >> 16) & 0xffU;
31108 		u.uc[5] = (tmp >> 8) & 0xffU;
31109 		u.uc[4] = (tmp >> 0) & 0xffU;
31110 	}
31111 
31112 	duk_dblunion_little_to_host(&u);
31113 	return u.d;
31114 }
31115 
duk__cbor_decode_string(duk_cbor_decode_context * dec_ctx,duk_uint8_t ib,duk_uint8_t ai)31116 DUK_LOCAL void duk__cbor_decode_string(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_uint8_t ai) {
31117 	/* If the CBOR string data is not valid UTF-8 it is technically
31118 	 * invalid CBOR.  Possible behaviors at least:
31119 	 *
31120 	 *   1. Reject the input, i.e. throw TypeError.
31121 	 *
31122 	 *   2. Accept the input, but sanitize non-UTF-8 data into UTF-8
31123 	 *      using U+FFFD replacements.  Also it might make sense to
31124 	 *      decode non-BMP codepoints into surrogates for better
31125 	 *      ECMAScript compatibility.
31126 	 *
31127 	 *   3. Accept the input as a Duktape string (which are not always
31128 	 *      valid UTF-8), but reject any input that would create a
31129 	 *      Symbol representation.
31130 	 *
31131 	 * Current behavior is 3.
31132 	 */
31133 
31134 	if (ai == 0x1fU) {
31135 		duk_uint8_t *buf_data;
31136 		duk_size_t buf_size;
31137 
31138 		duk__cbor_decode_and_join_strbuf(dec_ctx, 0x60U);
31139 		buf_data = (duk_uint8_t *) duk_require_buffer(dec_ctx->thr, -1, &buf_size);
31140 		(void) duk_push_lstring(dec_ctx->thr, (const char *) buf_data, buf_size);
31141 		duk_remove(dec_ctx->thr, -2);
31142 	} else {
31143 		duk_uint32_t len;
31144 		const duk_uint8_t *inp;
31145 
31146 		len = duk__cbor_decode_aival_uint32(dec_ctx, ib);
31147 		inp = duk__cbor_decode_consume(dec_ctx, len);
31148 		(void) duk_push_lstring(dec_ctx->thr, (const char *) inp, (duk_size_t) len);
31149 	}
31150 	if (duk_is_symbol(dec_ctx->thr, -1)) {
31151 		/* Refuse to create Symbols when decoding. */
31152 		duk__cbor_decode_error(dec_ctx);
31153 	}
31154 
31155 	/* XXX: Here a Duktape API call to convert input -> utf-8 with
31156 	 * replacements would be nice.
31157 	 */
31158 }
31159 
duk__cbor_decode_array(duk_cbor_decode_context * dec_ctx,duk_uint8_t ib,duk_uint8_t ai)31160 DUK_LOCAL duk_bool_t duk__cbor_decode_array(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_uint8_t ai) {
31161 	duk_uint32_t idx, len;
31162 
31163 	duk__cbor_decode_objarr_entry(dec_ctx);
31164 
31165 	/* Support arrays up to 0xfffffffeU in length.  0xffffffff is
31166 	 * used as an indefinite length marker.
31167 	 */
31168 	if (ai == 0x1fU) {
31169 		len = 0xffffffffUL;
31170 	} else {
31171 		len = duk__cbor_decode_aival_uint32(dec_ctx, ib);
31172 		if (len == 0xffffffffUL) {
31173 			goto failure;
31174 		}
31175 	}
31176 
31177 	/* XXX: use bare array? */
31178 	duk_push_array(dec_ctx->thr);
31179 	for (idx = 0U; ;) {
31180 		if (len == 0xffffffffUL && duk__cbor_decode_checkbreak(dec_ctx)) {
31181 			break;
31182 		}
31183 		if (idx == len) {
31184 			if (ai == 0x1fU) {
31185 				goto failure;
31186 			}
31187 			break;
31188 		}
31189 		duk__cbor_decode_value(dec_ctx);
31190 		duk_put_prop_index(dec_ctx->thr, -2, (duk_uarridx_t) idx);
31191 		idx++;
31192 		if (idx == 0U) {
31193 			goto failure;  /* wrapped */
31194 		}
31195 	}
31196 
31197 #if 0
31198  success:
31199 #endif
31200 	duk__cbor_decode_objarr_exit(dec_ctx);
31201 	return 1;
31202 
31203  failure:
31204 	/* No need to unwind recursion checks, caller will throw. */
31205 	return 0;
31206 }
31207 
duk__cbor_decode_map(duk_cbor_decode_context * dec_ctx,duk_uint8_t ib,duk_uint8_t ai)31208 DUK_LOCAL duk_bool_t duk__cbor_decode_map(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_uint8_t ai) {
31209 	duk_uint32_t count;
31210 
31211 	duk__cbor_decode_objarr_entry(dec_ctx);
31212 
31213 	if (ai == 0x1fU) {
31214 		count = 0xffffffffUL;
31215 	} else {
31216 		count = duk__cbor_decode_aival_uint32(dec_ctx, ib);
31217 		if (count == 0xffffffffUL) {
31218 			goto failure;
31219 		}
31220 	}
31221 
31222 	/* XXX: use bare object? */
31223 	duk_push_object(dec_ctx->thr);
31224 	for (;;) {
31225 		if (count == 0xffffffffUL) {
31226 			if (duk__cbor_decode_checkbreak(dec_ctx)) {
31227 				break;
31228 			}
31229 		} else {
31230 			if (count == 0UL) {
31231 				break;
31232 			}
31233 			count--;
31234 		}
31235 
31236 		/* Non-string keys are coerced to strings,
31237 		 * possibly leading to overwriting previous
31238 		 * keys.  Last key of a certain coerced name
31239 		 * wins.  If key is an object, it will coerce
31240 		 * to '[object Object]' which is consistent
31241 		 * but potentially misleading.  One alternative
31242 		 * would be to skip non-string keys.
31243 		 */
31244 		duk__cbor_decode_value(dec_ctx);
31245 		duk__cbor_decode_value(dec_ctx);
31246 		duk_put_prop(dec_ctx->thr, -3);
31247 	}
31248 
31249 #if 0
31250  success:
31251 #endif
31252 	duk__cbor_decode_objarr_exit(dec_ctx);
31253 	return 1;
31254 
31255  failure:
31256 	/* No need to unwind recursion checks, caller will throw. */
31257 	return 0;
31258 }
31259 
duk__cbor_decode_float(duk_cbor_decode_context * dec_ctx)31260 DUK_LOCAL duk_double_t duk__cbor_decode_float(duk_cbor_decode_context *dec_ctx) {
31261 	duk_float_union u;
31262 	const duk_uint8_t *inp;
31263 	inp = duk__cbor_decode_consume(dec_ctx, 4);
31264 	duk_memcpy((void *) u.uc, (const void *) inp, 4);
31265 	duk_fltunion_big_to_host(&u);
31266 	return (duk_double_t) u.f;
31267 }
31268 
duk__cbor_decode_double(duk_cbor_decode_context * dec_ctx)31269 DUK_LOCAL duk_double_t duk__cbor_decode_double(duk_cbor_decode_context *dec_ctx) {
31270 	duk_double_union u;
31271 	const duk_uint8_t *inp;
31272 	inp = duk__cbor_decode_consume(dec_ctx, 8);
31273 	duk_memcpy((void *) u.uc, (const void *) inp, 8);
31274 	duk_dblunion_big_to_host(&u);
31275 	return u.d;
31276 }
31277 
31278 #if defined(DUK_CBOR_DECODE_FASTPATH)
31279 #define DUK__CBOR_AI  (ib & 0x1fU)
31280 
duk__cbor_decode_value(duk_cbor_decode_context * dec_ctx)31281 DUK_LOCAL void duk__cbor_decode_value(duk_cbor_decode_context *dec_ctx) {
31282 	duk_uint8_t ib;
31283 
31284 	/* Any paths potentially recursing back to duk__cbor_decode_value()
31285 	 * must perform a Duktape value stack growth check.  Avoid the check
31286 	 * here for simple paths like primitive values.
31287 	 */
31288 
31289  reread_initial_byte:
31290 	DUK_DDD(DUK_DDDPRINT("cbor decode off=%ld len=%ld", (long) dec_ctx->off, (long) dec_ctx->len));
31291 
31292 	ib = duk__cbor_decode_readbyte(dec_ctx);
31293 
31294 	/* Full initial byte switch, footprint cost over baseline is ~+1kB. */
31295 	/* XXX: Force full switch with no range check. */
31296 
31297 	switch (ib) {
31298 	case 0x00U: case 0x01U: case 0x02U: case 0x03U: case 0x04U: case 0x05U: case 0x06U: case 0x07U:
31299 	case 0x08U: case 0x09U: case 0x0aU: case 0x0bU: case 0x0cU: case 0x0dU: case 0x0eU: case 0x0fU:
31300 	case 0x10U: case 0x11U: case 0x12U: case 0x13U: case 0x14U: case 0x15U: case 0x16U: case 0x17U:
31301 		duk_push_uint(dec_ctx->thr, ib);
31302 		break;
31303 	case 0x18U: case 0x19U: case 0x1aU: case 0x1bU:
31304 		duk__cbor_decode_push_aival_int(dec_ctx, ib, 0 /*negative*/);
31305 		break;
31306 	case 0x1cU: case 0x1dU: case 0x1eU: case 0x1fU:
31307 		goto format_error;
31308 	case 0x20U: case 0x21U: case 0x22U: case 0x23U: case 0x24U: case 0x25U: case 0x26U: case 0x27U:
31309 	case 0x28U: case 0x29U: case 0x2aU: case 0x2bU: case 0x2cU: case 0x2dU: case 0x2eU: case 0x2fU:
31310 	case 0x30U: case 0x31U: case 0x32U: case 0x33U: case 0x34U: case 0x35U: case 0x36U: case 0x37U:
31311 		duk_push_int(dec_ctx->thr, -((duk_int_t) ((ib - 0x20U) + 1U)));
31312 		break;
31313 	case 0x38U: case 0x39U: case 0x3aU: case 0x3bU:
31314 		duk__cbor_decode_push_aival_int(dec_ctx, ib, 1 /*negative*/);
31315 		break;
31316 	case 0x3cU: case 0x3dU: case 0x3eU: case 0x3fU:
31317 		goto format_error;
31318 	case 0x40U: case 0x41U: case 0x42U: case 0x43U: case 0x44U: case 0x45U: case 0x46U: case 0x47U:
31319 	case 0x48U: case 0x49U: case 0x4aU: case 0x4bU: case 0x4cU: case 0x4dU: case 0x4eU: case 0x4fU:
31320 	case 0x50U: case 0x51U: case 0x52U: case 0x53U: case 0x54U: case 0x55U: case 0x56U: case 0x57U:
31321 		/* XXX: Avoid rewind, we know the length already. */
31322 		DUK_ASSERT(dec_ctx->off > 0U);
31323 		dec_ctx->off--;
31324 		duk__cbor_decode_buffer(dec_ctx, 0x40U);
31325 		break;
31326 	case 0x58U: case 0x59U: case 0x5aU: case 0x5bU:
31327 		/* XXX: Avoid rewind, decode length inline. */
31328 		DUK_ASSERT(dec_ctx->off > 0U);
31329 		dec_ctx->off--;
31330 		duk__cbor_decode_buffer(dec_ctx, 0x40U);
31331 		break;
31332 	case 0x5cU: case 0x5dU: case 0x5eU:
31333 		goto format_error;
31334 	case 0x5fU:
31335 		duk__cbor_decode_and_join_strbuf(dec_ctx, 0x40U);
31336 		break;
31337 	case 0x60U: case 0x61U: case 0x62U: case 0x63U: case 0x64U: case 0x65U: case 0x66U: case 0x67U:
31338 	case 0x68U: case 0x69U: case 0x6aU: case 0x6bU: case 0x6cU: case 0x6dU: case 0x6eU: case 0x6fU:
31339 	case 0x70U: case 0x71U: case 0x72U: case 0x73U: case 0x74U: case 0x75U: case 0x76U: case 0x77U:
31340 		/* XXX: Avoid double decode of length. */
31341 		duk__cbor_decode_string(dec_ctx, ib, DUK__CBOR_AI);
31342 		break;
31343 	case 0x78U: case 0x79U: case 0x7aU: case 0x7bU:
31344 		/* XXX: Avoid double decode of length. */
31345 		duk__cbor_decode_string(dec_ctx, ib, DUK__CBOR_AI);
31346 		break;
31347 	case 0x7cU: case 0x7dU: case 0x7eU:
31348 		goto format_error;
31349 	case 0x7fU:
31350 		duk__cbor_decode_string(dec_ctx, ib, DUK__CBOR_AI);
31351 		break;
31352 	case 0x80U: case 0x81U: case 0x82U: case 0x83U: case 0x84U: case 0x85U: case 0x86U: case 0x87U:
31353 	case 0x88U: case 0x89U: case 0x8aU: case 0x8bU: case 0x8cU: case 0x8dU: case 0x8eU: case 0x8fU:
31354 	case 0x90U: case 0x91U: case 0x92U: case 0x93U: case 0x94U: case 0x95U: case 0x96U: case 0x97U:
31355 		if (DUK_UNLIKELY(duk__cbor_decode_array(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
31356 			goto format_error;
31357 		}
31358 		break;
31359 	case 0x98U: case 0x99U: case 0x9aU: case 0x9bU:
31360 		if (DUK_UNLIKELY(duk__cbor_decode_array(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
31361 			goto format_error;
31362 		}
31363 		break;
31364 	case 0x9cU: case 0x9dU: case 0x9eU:
31365 		goto format_error;
31366 	case 0x9fU:
31367 		if (DUK_UNLIKELY(duk__cbor_decode_array(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
31368 			goto format_error;
31369 		}
31370 		break;
31371 	case 0xa0U: case 0xa1U: case 0xa2U: case 0xa3U: case 0xa4U: case 0xa5U: case 0xa6U: case 0xa7U:
31372 	case 0xa8U: case 0xa9U: case 0xaaU: case 0xabU: case 0xacU: case 0xadU: case 0xaeU: case 0xafU:
31373 	case 0xb0U: case 0xb1U: case 0xb2U: case 0xb3U: case 0xb4U: case 0xb5U: case 0xb6U: case 0xb7U:
31374 		if (DUK_UNLIKELY(duk__cbor_decode_map(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
31375 			goto format_error;
31376 		}
31377 		break;
31378 	case 0xb8U: case 0xb9U: case 0xbaU: case 0xbbU:
31379 		if (DUK_UNLIKELY(duk__cbor_decode_map(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
31380 			goto format_error;
31381 		}
31382 		break;
31383 	case 0xbcU: case 0xbdU: case 0xbeU:
31384 		goto format_error;
31385 	case 0xbfU:
31386 		if (DUK_UNLIKELY(duk__cbor_decode_map(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
31387 			goto format_error;
31388 		}
31389 		break;
31390 	case 0xc0U: case 0xc1U: case 0xc2U: case 0xc3U: case 0xc4U: case 0xc5U: case 0xc6U: case 0xc7U:
31391 	case 0xc8U: case 0xc9U: case 0xcaU: case 0xcbU: case 0xccU: case 0xcdU: case 0xceU: case 0xcfU:
31392 	case 0xd0U: case 0xd1U: case 0xd2U: case 0xd3U: case 0xd4U: case 0xd5U: case 0xd6U: case 0xd7U:
31393 		/* Tag 0-23: drop. */
31394 		goto reread_initial_byte;
31395 	case 0xd8U: case 0xd9U: case 0xdaU: case 0xdbU:
31396 		duk__cbor_decode_skip_aival_int(dec_ctx, ib);
31397 		goto reread_initial_byte;
31398 	case 0xdcU: case 0xddU: case 0xdeU: case 0xdfU:
31399 		goto format_error;
31400 	case 0xe0U:
31401 		goto format_error;
31402 	case 0xe1U:
31403 		goto format_error;
31404 	case 0xe2U:
31405 		goto format_error;
31406 	case 0xe3U:
31407 		goto format_error;
31408 	case 0xe4U:
31409 		goto format_error;
31410 	case 0xe5U:
31411 		goto format_error;
31412 	case 0xe6U:
31413 		goto format_error;
31414 	case 0xe7U:
31415 		goto format_error;
31416 	case 0xe8U:
31417 		goto format_error;
31418 	case 0xe9U:
31419 		goto format_error;
31420 	case 0xeaU:
31421 		goto format_error;
31422 	case 0xebU:
31423 		goto format_error;
31424 	case 0xecU:
31425 		goto format_error;
31426 	case 0xedU:
31427 		goto format_error;
31428 	case 0xeeU:
31429 		goto format_error;
31430 	case 0xefU:
31431 		goto format_error;
31432 	case 0xf0U:
31433 		goto format_error;
31434 	case 0xf1U:
31435 		goto format_error;
31436 	case 0xf2U:
31437 		goto format_error;
31438 	case 0xf3U:
31439 		goto format_error;
31440 	case 0xf4U:
31441 		duk_push_false(dec_ctx->thr);
31442 		break;
31443 	case 0xf5U:
31444 		duk_push_true(dec_ctx->thr);
31445 		break;
31446 	case 0xf6U:
31447 		duk_push_null(dec_ctx->thr);
31448 		break;
31449 	case 0xf7U:
31450 		duk_push_undefined(dec_ctx->thr);
31451 		break;
31452 	case 0xf8U:
31453 		/* Simple value 32-255, nothing defined yet, so reject. */
31454 		goto format_error;
31455 	case 0xf9U: {
31456 		duk_double_t d;
31457 		d = duk__cbor_decode_half_float(dec_ctx);
31458 		duk_push_number(dec_ctx->thr, d);
31459 		break;
31460 	}
31461 	case 0xfaU: {
31462 		duk_double_t d;
31463 		d = duk__cbor_decode_float(dec_ctx);
31464 		duk_push_number(dec_ctx->thr, d);
31465 		break;
31466 	}
31467 	case 0xfbU: {
31468 		duk_double_t d;
31469 		d = duk__cbor_decode_double(dec_ctx);
31470 		duk_push_number(dec_ctx->thr, d);
31471 		break;
31472 	}
31473 	case 0xfcU:
31474 	case 0xfdU:
31475 	case 0xfeU:
31476 	case 0xffU:
31477 		goto format_error;
31478 	}  /* end switch */
31479 
31480 	return;
31481 
31482  format_error:
31483 	duk__cbor_decode_error(dec_ctx);
31484 }
31485 #else  /* DUK_CBOR_DECODE_FASTPATH */
duk__cbor_decode_value(duk_cbor_decode_context * dec_ctx)31486 DUK_LOCAL void duk__cbor_decode_value(duk_cbor_decode_context *dec_ctx) {
31487 	duk_uint8_t ib, mt, ai;
31488 
31489 	/* Any paths potentially recursing back to duk__cbor_decode_value()
31490 	 * must perform a Duktape value stack growth check.  Avoid the check
31491 	 * here for simple paths like primitive values.
31492 	 */
31493 
31494  reread_initial_byte:
31495 	DUK_DDD(DUK_DDDPRINT("cbor decode off=%ld len=%ld", (long) dec_ctx->off, (long) dec_ctx->len));
31496 
31497 	ib = duk__cbor_decode_readbyte(dec_ctx);
31498 	mt = ib >> 5U;
31499 	ai = ib & 0x1fU;
31500 
31501 	/* Additional information in [24,27] = [0x18,0x1b] has relatively
31502 	 * uniform handling for all major types: read 1/2/4/8 additional
31503 	 * bytes.  For major type 7 the 1-byte value is a 'simple type', and
31504 	 * 2/4/8-byte values are floats.  For other major types the 1/2/4/8
31505 	 * byte values are integers.  The lengths are uniform, but the typing
31506 	 * is not.
31507 	 */
31508 
31509 	switch (mt) {
31510 	case 0U: {  /* unsigned integer */
31511 		duk__cbor_decode_push_aival_int(dec_ctx, ib, 0 /*negative*/);
31512 		break;
31513 	}
31514 	case 1U: {  /* negative integer */
31515 		duk__cbor_decode_push_aival_int(dec_ctx, ib, 1 /*negative*/);
31516 		break;
31517 	}
31518 	case 2U: {  /* byte string */
31519 		if (ai == 0x1fU) {
31520 			duk__cbor_decode_and_join_strbuf(dec_ctx, 0x40U);
31521 		} else {
31522 			duk__cbor_decode_rewind(dec_ctx, 1U);
31523 			duk__cbor_decode_buffer(dec_ctx, 0x40U);
31524 		}
31525 		break;
31526 	}
31527 	case 3U: {  /* text string */
31528 		duk__cbor_decode_string(dec_ctx, ib, ai);
31529 		break;
31530 	}
31531 	case 4U: {  /* array of data items */
31532 		if (DUK_UNLIKELY(duk__cbor_decode_array(dec_ctx, ib, ai) == 0)) {
31533 			goto format_error;
31534 		}
31535 		break;
31536 	}
31537 	case 5U: {  /* map of pairs of data items */
31538 		if (DUK_UNLIKELY(duk__cbor_decode_map(dec_ctx, ib, ai) == 0)) {
31539 			goto format_error;
31540 		}
31541 		break;
31542 	}
31543 	case 6U: {  /* semantic tagging */
31544 		/* Tags are ignored now, re-read initial byte.  A tagged
31545 		 * value may itself be tagged (an unlimited number of times)
31546 		 * so keep on peeling away tags.
31547 		 */
31548 		duk__cbor_decode_skip_aival_int(dec_ctx, ib);
31549 		goto reread_initial_byte;
31550 	}
31551 	case 7U: {  /* floating point numbers, simple data types, break; other */
31552 		switch (ai) {
31553 		case 0x14U: {
31554 			duk_push_false(dec_ctx->thr);
31555 			break;
31556 		}
31557 		case 0x15U: {
31558 			duk_push_true(dec_ctx->thr);
31559 			break;
31560 		}
31561 		case 0x16U: {
31562 			duk_push_null(dec_ctx->thr);
31563 			break;
31564 		}
31565 		case 0x17U: {
31566 			duk_push_undefined(dec_ctx->thr);
31567 			break;
31568 		}
31569 		case 0x18U: {  /* more simple values (1 byte) */
31570 			/* Simple value encoded in additional byte (none
31571 			 * are defined so far).  RFC 7049 states that the
31572 			 * follow-up byte must be 32-255 to minimize
31573 			 * confusion.  So, a non-shortest encoding like
31574 			 * f815 (= true, shortest encoding f5) must be
31575 			 * rejected.  cbor.me tester rejects f815, but
31576 			 * e.g. Python CBOR binding decodes it as true.
31577 			 */
31578 			goto format_error;
31579 		}
31580 		case 0x19U: {  /* half-float (2 bytes) */
31581 			duk_double_t d;
31582 			d = duk__cbor_decode_half_float(dec_ctx);
31583 			duk_push_number(dec_ctx->thr, d);
31584 			break;
31585 		}
31586 		case 0x1aU: {  /* float (4 bytes) */
31587 			duk_double_t d;
31588 			d = duk__cbor_decode_float(dec_ctx);
31589 			duk_push_number(dec_ctx->thr, d);
31590 			break;
31591 		}
31592 		case 0x1bU: {  /* double (8 bytes) */
31593 			duk_double_t d;
31594 			d = duk__cbor_decode_double(dec_ctx);
31595 			duk_push_number(dec_ctx->thr, d);
31596 			break;
31597 		}
31598 		case 0xffU:  /* unexpected break */
31599 		default: {
31600 			goto format_error;
31601 		}
31602 		}  /* end switch */
31603 		break;
31604 	}
31605 	default: {
31606 		goto format_error;  /* will never actually occur */
31607 	}
31608 	}  /* end switch */
31609 
31610 	return;
31611 
31612  format_error:
31613 	duk__cbor_decode_error(dec_ctx);
31614 }
31615 #endif  /* DUK_CBOR_DECODE_FASTPATH */
31616 
duk__cbor_encode(duk_hthread * thr,duk_idx_t idx,duk_uint_t encode_flags)31617 DUK_LOCAL void duk__cbor_encode(duk_hthread *thr, duk_idx_t idx, duk_uint_t encode_flags) {
31618 	duk_cbor_encode_context enc_ctx;
31619 	duk_uint8_t *buf;
31620 
31621 	DUK_UNREF(encode_flags);
31622 
31623 	idx = duk_require_normalize_index(thr, idx);
31624 
31625 	enc_ctx.thr = thr;
31626 	enc_ctx.idx_buf = duk_get_top(thr);
31627 
31628 	enc_ctx.len = 64;
31629 	buf = (duk_uint8_t *) duk_push_dynamic_buffer(thr, enc_ctx.len);
31630 	enc_ctx.ptr = buf;
31631 	enc_ctx.buf = buf;
31632 	enc_ctx.buf_end = buf + enc_ctx.len;
31633 
31634 	enc_ctx.recursion_depth = 0;
31635 	enc_ctx.recursion_limit = DUK_USE_CBOR_ENC_RECLIMIT;
31636 
31637 	duk_dup(thr, idx);
31638 	duk__cbor_encode_req_stack(&enc_ctx);
31639 	duk__cbor_encode_value(&enc_ctx);
31640 	DUK_ASSERT(enc_ctx.recursion_depth == 0);
31641 	duk_resize_buffer(enc_ctx.thr, enc_ctx.idx_buf, (duk_size_t) (enc_ctx.ptr - enc_ctx.buf));
31642 	duk_replace(thr, idx);
31643 }
31644 
duk__cbor_decode(duk_hthread * thr,duk_idx_t idx,duk_uint_t decode_flags)31645 DUK_LOCAL void duk__cbor_decode(duk_hthread *thr, duk_idx_t idx, duk_uint_t decode_flags) {
31646 	duk_cbor_decode_context dec_ctx;
31647 
31648 	DUK_UNREF(decode_flags);
31649 
31650 	/* Suppress compile warnings for functions only needed with e.g.
31651 	 * asserts enabled.
31652 	 */
31653 	DUK_UNREF(duk__cbor_get_reserve);
31654 
31655 	idx = duk_require_normalize_index(thr, idx);
31656 
31657 	dec_ctx.thr = thr;
31658 	dec_ctx.buf = (const duk_uint8_t *) duk_require_buffer_data(thr, idx, &dec_ctx.len);
31659 	dec_ctx.off = 0;
31660 	/* dec_ctx.len: set above */
31661 
31662 	dec_ctx.recursion_depth = 0;
31663 	dec_ctx.recursion_limit = DUK_USE_CBOR_DEC_RECLIMIT;
31664 
31665 	duk__cbor_decode_req_stack(&dec_ctx);
31666 	duk__cbor_decode_value(&dec_ctx);
31667 	DUK_ASSERT(dec_ctx.recursion_depth == 0);
31668 	if (dec_ctx.off != dec_ctx.len) {
31669 		(void) duk_type_error(thr, "trailing garbage");
31670 	}
31671 
31672 	duk_replace(thr, idx);
31673 }
31674 
31675 #else  /* DUK_USE_CBOR_SUPPORT */
31676 
duk__cbor_encode(duk_hthread * thr,duk_idx_t idx,duk_uint_t encode_flags)31677 DUK_LOCAL void duk__cbor_encode(duk_hthread *thr, duk_idx_t idx, duk_uint_t encode_flags) {
31678 	DUK_UNREF(idx);
31679 	DUK_UNREF(encode_flags);
31680 	DUK_ERROR_UNSUPPORTED(thr);
31681 }
31682 
duk__cbor_decode(duk_hthread * thr,duk_idx_t idx,duk_uint_t decode_flags)31683 DUK_LOCAL void duk__cbor_decode(duk_hthread *thr, duk_idx_t idx, duk_uint_t decode_flags) {
31684 	DUK_UNREF(idx);
31685 	DUK_UNREF(decode_flags);
31686 	DUK_ERROR_UNSUPPORTED(thr);
31687 }
31688 
31689 #endif  /* DUK_USE_CBOR_SUPPORT */
31690 
31691 /*
31692  *  Public APIs
31693  */
31694 
duk_cbor_encode(duk_hthread * thr,duk_idx_t idx,duk_uint_t encode_flags)31695 DUK_EXTERNAL void duk_cbor_encode(duk_hthread *thr, duk_idx_t idx, duk_uint_t encode_flags) {
31696 	DUK_ASSERT_API_ENTRY(thr);
31697 	duk__cbor_encode(thr, idx, encode_flags);
31698 }
duk_cbor_decode(duk_hthread * thr,duk_idx_t idx,duk_uint_t decode_flags)31699 DUK_EXTERNAL void duk_cbor_decode(duk_hthread *thr, duk_idx_t idx, duk_uint_t decode_flags) {
31700 	DUK_ASSERT_API_ENTRY(thr);
31701 	duk__cbor_decode(thr, idx, decode_flags);
31702 }
31703 
31704 #if defined(DUK_USE_CBOR_BUILTIN)
31705 #if defined(DUK_USE_CBOR_SUPPORT)
duk_bi_cbor_encode(duk_hthread * thr)31706 DUK_INTERNAL duk_ret_t duk_bi_cbor_encode(duk_hthread *thr) {
31707 	DUK_ASSERT_TOP(thr, 1);
31708 
31709 	duk__cbor_encode(thr, -1, 0 /*flags*/);
31710 
31711 	/* Produce an ArrayBuffer by first decoding into a plain buffer which
31712 	 * mimics a Uint8Array and gettings its .buffer property.
31713 	 */
31714 	/* XXX: shortcut */
31715 	(void) duk_get_prop_stridx(thr, -1, DUK_STRIDX_LC_BUFFER);
31716 	return 1;
31717 }
31718 
duk_bi_cbor_decode(duk_hthread * thr)31719 DUK_INTERNAL duk_ret_t duk_bi_cbor_decode(duk_hthread *thr) {
31720 	DUK_ASSERT_TOP(thr, 1);
31721 
31722 	duk__cbor_decode(thr, -1, 0 /*flags*/);
31723 	return 1;
31724 }
31725 #else  /* DUK_USE_CBOR_SUPPORT */
duk_bi_cbor_encode(duk_hthread * thr)31726 DUK_INTERNAL duk_ret_t duk_bi_cbor_encode(duk_hthread *thr) {
31727 	DUK_ERROR_UNSUPPORTED(thr);
31728 	DUK_WO_NORETURN(return 0;);
31729 }
duk_bi_cbor_decode(duk_hthread * thr)31730 DUK_INTERNAL duk_ret_t duk_bi_cbor_decode(duk_hthread *thr) {
31731 	DUK_ERROR_UNSUPPORTED(thr);
31732 	DUK_WO_NORETURN(return 0;);
31733 }
31734 #endif  /* DUK_USE_CBOR_SUPPORT */
31735 #endif  /* DUK_USE_CBOR_BUILTIN */
31736 
31737 /* automatic undefs */
31738 #undef DUK__CBOR_AI
31739 /*
31740  *  Date built-ins
31741  *
31742  *  Unlike most built-ins, Date has some platform dependencies for getting
31743  *  UTC time, converting between UTC and local time, and parsing and
31744  *  formatting time values.  These are all abstracted behind DUK_USE_xxx
31745  *  config options.  There are built-in platform specific providers for
31746  *  POSIX and Windows, but external providers can also be used.
31747  *
31748  *  See doc/datetime.rst.
31749  *
31750  */
31751 
31752 /* #include duk_internal.h -> already included */
31753 
31754 /* XXX: currently defines unnecessary symbols when DUK_USE_DATE_BUILTIN is disabled. */
31755 
31756 /*
31757  *  Forward declarations
31758  */
31759 
31760 DUK_LOCAL_DECL duk_double_t duk__push_this_get_timeval_tzoffset(duk_hthread *thr, duk_small_uint_t flags, duk_int_t *out_tzoffset);
31761 DUK_LOCAL_DECL duk_double_t duk__push_this_get_timeval(duk_hthread *thr, duk_small_uint_t flags);
31762 DUK_LOCAL_DECL void duk__twodigit_year_fixup(duk_hthread *thr, duk_idx_t idx_val);
31763 DUK_LOCAL_DECL duk_ret_t duk__set_this_timeval_from_dparts(duk_hthread *thr, duk_double_t *dparts, duk_small_uint_t flags);
31764 
31765 /*
31766  *  Other file level defines
31767  */
31768 
31769 /* Debug macro to print all parts and dparts (used manually because of debug level). */
31770 #define  DUK__DPRINT_PARTS_AND_DPARTS(parts,dparts)  do { \
31771 		DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld, dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \
31772 		                 (long) (parts)[0], (long) (parts)[1], \
31773 		                 (long) (parts)[2], (long) (parts)[3], \
31774 		                 (long) (parts)[4], (long) (parts)[5], \
31775 		                 (long) (parts)[6], (long) (parts)[7], \
31776 		                 (double) (dparts)[0], (double) (dparts)[1], \
31777 		                 (double) (dparts)[2], (double) (dparts)[3], \
31778 		                 (double) (dparts)[4], (double) (dparts)[5], \
31779 		                 (double) (dparts)[6], (double) (dparts)[7])); \
31780 	} while (0)
31781 #define  DUK__DPRINT_PARTS(parts)  do { \
31782 		DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld", \
31783 		                 (long) (parts)[0], (long) (parts)[1], \
31784 		                 (long) (parts)[2], (long) (parts)[3], \
31785 		                 (long) (parts)[4], (long) (parts)[5], \
31786 		                 (long) (parts)[6], (long) (parts)[7])); \
31787 	} while (0)
31788 #define  DUK__DPRINT_DPARTS(dparts)  do { \
31789 		DUK_D(DUK_DPRINT("dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \
31790 		                 (double) (dparts)[0], (double) (dparts)[1], \
31791 		                 (double) (dparts)[2], (double) (dparts)[3], \
31792 		                 (double) (dparts)[4], (double) (dparts)[5], \
31793 		                 (double) (dparts)[6], (double) (dparts)[7])); \
31794 	} while (0)
31795 
31796 /* Equivalent year for DST calculations outside [1970,2038[ range, see
31797  * E5 Section 15.9.1.8.  Equivalent year has the same leap-year-ness and
31798  * starts with the same weekday on Jan 1.
31799  * https://bugzilla.mozilla.org/show_bug.cgi?id=351066
31800  */
31801 #define DUK__YEAR(x) ((duk_uint8_t) ((x) - 1970))
31802 DUK_LOCAL duk_uint8_t duk__date_equivyear[14] = {
31803 #if 1
31804 	/* This is based on V8 EquivalentYear() algorithm (see util/genequivyear.py):
31805 	 * http://code.google.com/p/v8/source/browse/trunk/src/date.h#146
31806 	 */
31807 
31808 	/* non-leap year: sunday, monday, ... */
31809 	DUK__YEAR(2023), DUK__YEAR(2035), DUK__YEAR(2019), DUK__YEAR(2031),
31810 	DUK__YEAR(2015), DUK__YEAR(2027), DUK__YEAR(2011),
31811 
31812 	/* leap year: sunday, monday, ... */
31813 	DUK__YEAR(2012), DUK__YEAR(2024), DUK__YEAR(2008), DUK__YEAR(2020),
31814 	DUK__YEAR(2032), DUK__YEAR(2016), DUK__YEAR(2028)
31815 #endif
31816 
31817 #if 0
31818 	/* This is based on Rhino EquivalentYear() algorithm:
31819 	 * https://github.com/mozilla/rhino/blob/f99cc11d616f0cdda2c42bde72b3484df6182947/src/org/mozilla/javascript/NativeDate.java
31820 	 */
31821 
31822 	/* non-leap year: sunday, monday, ... */
31823 	DUK__YEAR(1978), DUK__YEAR(1973), DUK__YEAR(1985), DUK__YEAR(1986),
31824 	DUK__YEAR(1981), DUK__YEAR(1971), DUK__YEAR(1977),
31825 
31826 	/* leap year: sunday, monday, ... */
31827 	DUK__YEAR(1984), DUK__YEAR(1996), DUK__YEAR(1980), DUK__YEAR(1992),
31828 	DUK__YEAR(1976), DUK__YEAR(1988), DUK__YEAR(1972)
31829 #endif
31830 };
31831 
31832 /*
31833  *  ISO 8601 subset parser.
31834  */
31835 
31836 /* Parser part count. */
31837 #define DUK__NUM_ISO8601_PARSER_PARTS  9
31838 
31839 /* Parser part indices. */
31840 #define DUK__PI_YEAR         0
31841 #define DUK__PI_MONTH        1
31842 #define DUK__PI_DAY          2
31843 #define DUK__PI_HOUR         3
31844 #define DUK__PI_MINUTE       4
31845 #define DUK__PI_SECOND       5
31846 #define DUK__PI_MILLISECOND  6
31847 #define DUK__PI_TZHOUR       7
31848 #define DUK__PI_TZMINUTE     8
31849 
31850 /* Parser part masks. */
31851 #define DUK__PM_YEAR         (1 << DUK__PI_YEAR)
31852 #define DUK__PM_MONTH        (1 << DUK__PI_MONTH)
31853 #define DUK__PM_DAY          (1 << DUK__PI_DAY)
31854 #define DUK__PM_HOUR         (1 << DUK__PI_HOUR)
31855 #define DUK__PM_MINUTE       (1 << DUK__PI_MINUTE)
31856 #define DUK__PM_SECOND       (1 << DUK__PI_SECOND)
31857 #define DUK__PM_MILLISECOND  (1 << DUK__PI_MILLISECOND)
31858 #define DUK__PM_TZHOUR       (1 << DUK__PI_TZHOUR)
31859 #define DUK__PM_TZMINUTE     (1 << DUK__PI_TZMINUTE)
31860 
31861 /* Parser separator indices. */
31862 #define DUK__SI_PLUS         0
31863 #define DUK__SI_MINUS        1
31864 #define DUK__SI_T            2
31865 #define DUK__SI_SPACE        3
31866 #define DUK__SI_COLON        4
31867 #define DUK__SI_PERIOD       5
31868 #define DUK__SI_Z            6
31869 #define DUK__SI_NUL          7
31870 
31871 /* Parser separator masks. */
31872 #define DUK__SM_PLUS         (1 << DUK__SI_PLUS)
31873 #define DUK__SM_MINUS        (1 << DUK__SI_MINUS)
31874 #define DUK__SM_T            (1 << DUK__SI_T)
31875 #define DUK__SM_SPACE        (1 << DUK__SI_SPACE)
31876 #define DUK__SM_COLON        (1 << DUK__SI_COLON)
31877 #define DUK__SM_PERIOD       (1 << DUK__SI_PERIOD)
31878 #define DUK__SM_Z            (1 << DUK__SI_Z)
31879 #define DUK__SM_NUL          (1 << DUK__SI_NUL)
31880 
31881 /* Rule control flags. */
31882 #define DUK__CF_NEG          (1 << 0)  /* continue matching, set neg_tzoffset flag */
31883 #define DUK__CF_ACCEPT       (1 << 1)  /* accept string */
31884 #define DUK__CF_ACCEPT_NUL   (1 << 2)  /* accept string if next char is NUL (otherwise reject) */
31885 
31886 #define DUK__PACK_RULE(partmask,sepmask,nextpart,flags)  \
31887 	((duk_uint32_t) (partmask) + \
31888 	 (((duk_uint32_t) (sepmask)) << 9) + \
31889 	 (((duk_uint32_t) (nextpart)) << 17) + \
31890 	 (((duk_uint32_t) (flags)) << 21))
31891 
31892 #define DUK__UNPACK_RULE(rule,var_nextidx,var_flags)  do { \
31893 		(var_nextidx) = (duk_small_uint_t) (((rule) >> 17) & 0x0f); \
31894 		(var_flags) = (duk_small_uint_t) ((rule) >> 21); \
31895 	} while (0)
31896 
31897 #define DUK__RULE_MASK_PART_SEP  0x1ffffUL
31898 
31899 /* Matching separator index is used in the control table */
31900 DUK_LOCAL const duk_uint8_t duk__parse_iso8601_seps[] = {
31901 	DUK_ASC_PLUS /*0*/, DUK_ASC_MINUS /*1*/, DUK_ASC_UC_T /*2*/, DUK_ASC_SPACE /*3*/,
31902 	DUK_ASC_COLON /*4*/, DUK_ASC_PERIOD /*5*/, DUK_ASC_UC_Z /*6*/, DUK_ASC_NUL /*7*/
31903 };
31904 
31905 /* Rule table: first matching rule is used to determine what to do next. */
31906 DUK_LOCAL const duk_uint32_t duk__parse_iso8601_control[] = {
31907 	DUK__PACK_RULE(DUK__PM_YEAR, DUK__SM_MINUS, DUK__PI_MONTH, 0),
31908 	DUK__PACK_RULE(DUK__PM_MONTH, DUK__SM_MINUS, DUK__PI_DAY, 0),
31909 	DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY, DUK__SM_T | DUK__SM_SPACE, DUK__PI_HOUR, 0),
31910 	DUK__PACK_RULE(DUK__PM_HOUR, DUK__SM_COLON, DUK__PI_MINUTE, 0),
31911 	DUK__PACK_RULE(DUK__PM_MINUTE, DUK__SM_COLON, DUK__PI_SECOND, 0),
31912 	DUK__PACK_RULE(DUK__PM_SECOND, DUK__SM_PERIOD, DUK__PI_MILLISECOND, 0),
31913 	DUK__PACK_RULE(DUK__PM_TZHOUR, DUK__SM_COLON, DUK__PI_TZMINUTE, 0),
31914 	DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY | DUK__PM_HOUR /*Note1*/ | DUK__PM_MINUTE | DUK__PM_SECOND | DUK__PM_MILLISECOND, DUK__SM_PLUS, DUK__PI_TZHOUR, 0),
31915 	DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY | DUK__PM_HOUR /*Note1*/ | DUK__PM_MINUTE | DUK__PM_SECOND | DUK__PM_MILLISECOND, DUK__SM_MINUS, DUK__PI_TZHOUR, DUK__CF_NEG),
31916 	DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY | DUK__PM_HOUR /*Note1*/ | DUK__PM_MINUTE | DUK__PM_SECOND | DUK__PM_MILLISECOND, DUK__SM_Z, 0, DUK__CF_ACCEPT_NUL),
31917 	DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY | DUK__PM_HOUR /*Note1*/ | DUK__PM_MINUTE | DUK__PM_SECOND | DUK__PM_MILLISECOND | DUK__PM_TZHOUR /*Note2*/ | DUK__PM_TZMINUTE, DUK__SM_NUL, 0, DUK__CF_ACCEPT)
31918 
31919 	/* Note1: the specification doesn't require matching a time form with
31920 	 *        just hours ("HH"), but we accept it here, e.g. "2012-01-02T12Z".
31921 	 *
31922 	 * Note2: the specification doesn't require matching a timezone offset
31923 	 *        with just hours ("HH"), but accept it here, e.g. "2012-01-02T03:04:05+02"
31924 	 */
31925 };
31926 
duk__parse_string_iso8601_subset(duk_hthread * thr,const char * str)31927 DUK_LOCAL duk_bool_t duk__parse_string_iso8601_subset(duk_hthread *thr, const char *str) {
31928 	duk_int_t parts[DUK__NUM_ISO8601_PARSER_PARTS];
31929 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
31930 	duk_double_t d;
31931 	const duk_uint8_t *p;
31932 	duk_small_uint_t part_idx = 0;
31933 	duk_int_t accum = 0;
31934 	duk_small_uint_t ndigits = 0;
31935 	duk_bool_t neg_year = 0;
31936 	duk_bool_t neg_tzoffset = 0;
31937 	duk_uint_fast8_t ch;
31938 	duk_small_uint_t i;
31939 
31940 	/* During parsing, month and day are one-based; set defaults here. */
31941 	duk_memzero(parts, sizeof(parts));
31942 	DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] == 0);  /* don't care value, year is mandatory */
31943 	parts[DUK_DATE_IDX_MONTH] = 1;
31944 	parts[DUK_DATE_IDX_DAY] = 1;
31945 
31946 	/* Special handling for year sign. */
31947 	p = (const duk_uint8_t *) str;
31948 	ch = p[0];
31949 	if (ch == DUK_ASC_PLUS) {
31950 		p++;
31951 	} else if (ch == DUK_ASC_MINUS) {
31952 		neg_year = 1;
31953 		p++;
31954 	}
31955 
31956 	for (;;) {
31957 		ch = *p++;
31958 		DUK_DDD(DUK_DDDPRINT("parsing, part_idx=%ld, char=%ld ('%c')",
31959 		                     (long) part_idx, (long) ch,
31960 		                     (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : DUK_ASC_QUESTION)));
31961 
31962 		if (ch >= DUK_ASC_0 && ch <= DUK_ASC_9) {
31963 			if (ndigits >= 9) {
31964 				DUK_DDD(DUK_DDDPRINT("too many digits -> reject"));
31965 				goto reject;
31966 			}
31967 			if (part_idx == DUK__PI_MILLISECOND && ndigits >= 3) {
31968 				/* ignore millisecond fractions after 3 */
31969 			} else {
31970 				accum = accum * 10 + ((duk_int_t) ch) - ((duk_int_t) DUK_ASC_0) + 0x00;
31971 				ndigits++;
31972 			}
31973 		} else {
31974 			duk_uint_fast32_t match_val;
31975 			duk_small_uint_t sep_idx;
31976 
31977 			if (ndigits <= 0) {
31978 				goto reject;
31979 			}
31980 			if (part_idx == DUK__PI_MILLISECOND) {
31981 				/* complete the millisecond field */
31982 				while (ndigits < 3) {
31983 					accum *= 10;
31984 					ndigits++;
31985 				}
31986 			}
31987 			parts[part_idx] = accum;
31988 			DUK_DDD(DUK_DDDPRINT("wrote part %ld -> value %ld", (long) part_idx, (long) accum));
31989 
31990 			accum = 0;
31991 			ndigits = 0;
31992 
31993 			for (i = 0; i < (duk_small_uint_t) (sizeof(duk__parse_iso8601_seps) / sizeof(duk_uint8_t)); i++) {
31994 				if (duk__parse_iso8601_seps[i] == ch) {
31995 					break;
31996 				}
31997 			}
31998 			if (i == (duk_small_uint_t) (sizeof(duk__parse_iso8601_seps) / sizeof(duk_uint8_t))) {
31999 				DUK_DDD(DUK_DDDPRINT("separator character doesn't match -> reject"));
32000 				goto reject;
32001 			}
32002 
32003 			sep_idx = i;
32004 			match_val = (1UL << part_idx) + (1UL << (sep_idx + 9));  /* match against rule part/sep bits */
32005 
32006 			for (i = 0; i < (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t)); i++) {
32007 				duk_uint_fast32_t rule = duk__parse_iso8601_control[i];
32008 				duk_small_uint_t nextpart;
32009 				duk_small_uint_t cflags;
32010 
32011 				DUK_DDD(DUK_DDDPRINT("part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, considering rule=0x%08lx",
32012 				                     (long) part_idx, (long) sep_idx,
32013 				                     (unsigned long) match_val, (unsigned long) rule));
32014 
32015 				if ((rule & match_val) != match_val) {
32016 					continue;
32017 				}
32018 
32019 				DUK__UNPACK_RULE(rule, nextpart, cflags);
32020 
32021 				DUK_DDD(DUK_DDDPRINT("rule match -> part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, "
32022 				                     "rule=0x%08lx -> nextpart=%ld, cflags=0x%02lx",
32023 				                     (long) part_idx, (long) sep_idx,
32024 				                     (unsigned long) match_val, (unsigned long) rule,
32025 				                     (long) nextpart, (unsigned long) cflags));
32026 
32027 				if (cflags & DUK__CF_NEG) {
32028 					neg_tzoffset = 1;
32029 				}
32030 
32031 				if (cflags & DUK__CF_ACCEPT) {
32032 					goto accept;
32033 				}
32034 
32035 				if (cflags & DUK__CF_ACCEPT_NUL) {
32036 					DUK_ASSERT(*(p - 1) != (char) 0);
32037 					if (*p == DUK_ASC_NUL) {
32038 						goto accept;
32039 					}
32040 					goto reject;
32041 				}
32042 
32043 				part_idx = nextpart;
32044 				break;
32045 			}  /* rule match */
32046 
32047 			if (i == (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t))) {
32048 				DUK_DDD(DUK_DDDPRINT("no rule matches -> reject"));
32049 				goto reject;
32050 			}
32051 
32052 			if (ch == 0) {
32053 				/* This shouldn't be necessary, but check just in case
32054 				 * to avoid any chance of overruns.
32055 				 */
32056 				DUK_DDD(DUK_DDDPRINT("NUL after rule matching (should not happen) -> reject"));
32057 				goto reject;
32058 			}
32059 		}  /* if-digit-else-ctrl */
32060 	}  /* char loop */
32061 
32062 	/* We should never exit the loop above. */
32063 	DUK_UNREACHABLE();
32064 
32065  reject:
32066 	DUK_DDD(DUK_DDDPRINT("reject"));
32067 	return 0;
32068 
32069  accept:
32070 	DUK_DDD(DUK_DDDPRINT("accept"));
32071 
32072 	/* Apply timezone offset to get the main parts in UTC */
32073 	if (neg_year) {
32074 		parts[DUK__PI_YEAR] = -parts[DUK__PI_YEAR];
32075 	}
32076 	if (neg_tzoffset) {
32077 		parts[DUK__PI_HOUR] += parts[DUK__PI_TZHOUR];
32078 		parts[DUK__PI_MINUTE] += parts[DUK__PI_TZMINUTE];
32079 	} else {
32080 		parts[DUK__PI_HOUR] -= parts[DUK__PI_TZHOUR];
32081 		parts[DUK__PI_MINUTE] -= parts[DUK__PI_TZMINUTE];
32082 	}
32083 	parts[DUK__PI_MONTH] -= 1;  /* zero-based month */
32084 	parts[DUK__PI_DAY] -= 1;  /* zero-based day */
32085 
32086 	/* Use double parts, they tolerate unnormalized time.
32087 	 *
32088 	 * Note: DUK_DATE_IDX_WEEKDAY is initialized with a bogus value (DUK__PI_TZHOUR)
32089 	 * on purpose.  It won't be actually used by duk_bi_date_get_timeval_from_dparts(),
32090 	 * but will make the value initialized just in case, and avoid any
32091 	 * potential for Valgrind issues.
32092 	 */
32093 	for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) {
32094 		DUK_DDD(DUK_DDDPRINT("part[%ld] = %ld", (long) i, (long) parts[i]));
32095 		dparts[i] = parts[i];
32096 	}
32097 
32098 	d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
32099 	duk_push_number(thr, d);
32100 	return 1;
32101 }
32102 
32103 /*
32104  *  Date/time parsing helper.
32105  *
32106  *  Parse a datetime string into a time value.  We must first try to parse
32107  *  the input according to the standard format in E5.1 Section 15.9.1.15.
32108  *  If that fails, we can try to parse using custom parsing, which can
32109  *  either be platform neutral (custom code) or platform specific (using
32110  *  existing platform API calls).
32111  *
32112  *  Note in particular that we must parse whatever toString(), toUTCString(),
32113  *  and toISOString() can produce; see E5.1 Section 15.9.4.2.
32114  *
32115  *  Returns 1 to allow tail calling.
32116  *
32117  *  There is much room for improvement here with respect to supporting
32118  *  alternative datetime formats.  For instance, V8 parses '2012-01-01' as
32119  *  UTC and '2012/01/01' as local time.
32120  */
32121 
duk__parse_string(duk_hthread * thr,const char * str)32122 DUK_LOCAL duk_ret_t duk__parse_string(duk_hthread *thr, const char *str) {
32123 	/* XXX: there is a small risk here: because the ISO 8601 parser is
32124 	 * very loose, it may end up parsing some datetime values which
32125 	 * would be better parsed with a platform specific parser.
32126 	 */
32127 
32128 	DUK_ASSERT(str != NULL);
32129 	DUK_DDD(DUK_DDDPRINT("parse datetime from string '%s'", (const char *) str));
32130 
32131 	if (duk__parse_string_iso8601_subset(thr, str) != 0) {
32132 		return 1;
32133 	}
32134 
32135 #if defined(DUK_USE_DATE_PARSE_STRING)
32136 	/* Contract, either:
32137 	 * - Push value on stack and return 1
32138 	 * - Don't push anything on stack and return 0
32139 	 */
32140 
32141 	if (DUK_USE_DATE_PARSE_STRING(thr, str) != 0) {
32142 		return 1;
32143 	}
32144 #else
32145 	/* No platform-specific parsing, this is not an error. */
32146 #endif
32147 
32148 	duk_push_nan(thr);
32149 	return 1;
32150 }
32151 
32152 /*
32153  *  Calendar helpers
32154  *
32155  *  Some helpers are used for getters and can operate on normalized values
32156  *  which can be represented with 32-bit signed integers.  Other helpers are
32157  *  needed by setters and operate on un-normalized double values, must watch
32158  *  out for non-finite numbers etc.
32159  */
32160 
32161 DUK_LOCAL duk_uint8_t duk__days_in_month[12] = {
32162 	(duk_uint8_t) 31, (duk_uint8_t) 28, (duk_uint8_t) 31, (duk_uint8_t) 30,
32163 	(duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 31,
32164 	(duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31
32165 };
32166 
32167 /* Maximum iteration count for computing UTC-to-local time offset when
32168  * creating an ECMAScript time value from local parts.
32169  */
32170 #define DUK__LOCAL_TZOFFSET_MAXITER   4
32171 
32172 /* Because 'day since epoch' can be negative and is used to compute weekday
32173  * using a modulo operation, add this multiple of 7 to avoid negative values
32174  * when year is below 1970 epoch.  ECMAScript time values are restricted to
32175  * +/- 100 million days from epoch, so this adder fits nicely into 32 bits.
32176  * Round to a multiple of 7 (= floor(100000000 / 7) * 7) and add margin.
32177  */
32178 #define DUK__WEEKDAY_MOD_ADDER  (20000000 * 7)  /* 0x08583b00 */
32179 
duk_bi_date_is_leap_year(duk_int_t year)32180 DUK_INTERNAL duk_bool_t duk_bi_date_is_leap_year(duk_int_t year) {
32181 	if ((year % 4) != 0) {
32182 		return 0;
32183 	}
32184 	if ((year % 100) != 0) {
32185 		return 1;
32186 	}
32187 	if ((year % 400) != 0) {
32188 		return 0;
32189 	}
32190 	return 1;
32191 }
32192 
duk_bi_date_timeval_in_valid_range(duk_double_t x)32193 DUK_INTERNAL duk_bool_t duk_bi_date_timeval_in_valid_range(duk_double_t x) {
32194 	return (x >= -DUK_DATE_MSEC_100M_DAYS && x <= DUK_DATE_MSEC_100M_DAYS);
32195 }
32196 
duk_bi_date_timeval_in_leeway_range(duk_double_t x)32197 DUK_INTERNAL duk_bool_t duk_bi_date_timeval_in_leeway_range(duk_double_t x) {
32198 	return (x >= -DUK_DATE_MSEC_100M_DAYS_LEEWAY && x <= DUK_DATE_MSEC_100M_DAYS_LEEWAY);
32199 }
32200 
duk_bi_date_year_in_valid_range(duk_double_t x)32201 DUK_INTERNAL duk_bool_t duk_bi_date_year_in_valid_range(duk_double_t x) {
32202 	return (x >= DUK_DATE_MIN_ECMA_YEAR && x <= DUK_DATE_MAX_ECMA_YEAR);
32203 }
32204 
duk__timeclip(duk_double_t x)32205 DUK_LOCAL duk_double_t duk__timeclip(duk_double_t x) {
32206 	if (!DUK_ISFINITE(x)) {
32207 		return DUK_DOUBLE_NAN;
32208 	}
32209 
32210 	if (!duk_bi_date_timeval_in_valid_range(x)) {
32211 		return DUK_DOUBLE_NAN;
32212 	}
32213 
32214 	x = duk_js_tointeger_number(x);
32215 
32216 	/* Here we'd have the option to normalize -0 to +0. */
32217 	return x;
32218 }
32219 
32220 /* Integer division which floors also negative values correctly. */
duk__div_floor(duk_int_t a,duk_int_t b)32221 DUK_LOCAL duk_int_t duk__div_floor(duk_int_t a, duk_int_t b) {
32222 	DUK_ASSERT(b > 0);
32223 	if (a >= 0) {
32224 		return a / b;
32225 	} else {
32226 		/* e.g. a = -4, b = 5  -->  -4 - 5 + 1 / 5  -->  -8 / 5  -->  -1
32227 		 *      a = -5, b = 5  -->  -5 - 5 + 1 / 5  -->  -9 / 5  -->  -1
32228 		 *      a = -6, b = 5  -->  -6 - 5 + 1 / 5  -->  -10 / 5  -->  -2
32229 		 */
32230 		return (a - b + 1) / b;
32231 	}
32232 }
32233 
32234 /* Compute day number of the first day of a given year. */
duk__day_from_year(duk_int_t year)32235 DUK_LOCAL duk_int_t duk__day_from_year(duk_int_t year) {
32236 	/* Note: in integer arithmetic, (x / 4) is same as floor(x / 4) for non-negative
32237 	 * values, but is incorrect for negative ones.
32238 	 */
32239 	return 365 * (year - 1970)
32240 	       + duk__div_floor(year - 1969, 4)
32241 	       - duk__div_floor(year - 1901, 100)
32242 	       + duk__div_floor(year - 1601, 400);
32243 }
32244 
32245 /* Given a day number, determine year and day-within-year. */
duk__year_from_day(duk_int_t day,duk_small_int_t * out_day_within_year)32246 DUK_LOCAL duk_int_t duk__year_from_day(duk_int_t day, duk_small_int_t *out_day_within_year) {
32247 	duk_int_t year;
32248 	duk_int_t diff_days;
32249 
32250 	/* estimate year upwards (towards positive infinity), then back down;
32251 	 * two iterations should be enough
32252 	 */
32253 
32254 	if (day >= 0) {
32255 		year = 1970 + day / 365;
32256 	} else {
32257 		year = 1970 + day / 366;
32258 	}
32259 
32260 	for (;;) {
32261 		diff_days = duk__day_from_year(year) - day;
32262 		DUK_DDD(DUK_DDDPRINT("year=%ld day=%ld, diff_days=%ld", (long) year, (long) day, (long) diff_days));
32263 		if (diff_days <= 0) {
32264 			DUK_ASSERT(-diff_days < 366);  /* fits into duk_small_int_t */
32265 			*out_day_within_year = -diff_days;
32266 			DUK_DDD(DUK_DDDPRINT("--> year=%ld, day-within-year=%ld",
32267 			                     (long) year, (long) *out_day_within_year));
32268 			DUK_ASSERT(*out_day_within_year >= 0);
32269 			DUK_ASSERT(*out_day_within_year < (duk_bi_date_is_leap_year(year) ? 366 : 365));
32270 			return year;
32271 		}
32272 
32273 		/* Note: this is very tricky; we must never 'overshoot' the
32274 		 * correction downwards.
32275 		 */
32276 		year -= 1 + (diff_days - 1) / 366;  /* conservative */
32277 	}
32278 }
32279 
32280 /* Given a (year, month, day-within-month) triple, compute day number.
32281  * The input triple is un-normalized and may contain non-finite values.
32282  */
duk__make_day(duk_double_t year,duk_double_t month,duk_double_t day)32283 DUK_LOCAL duk_double_t duk__make_day(duk_double_t year, duk_double_t month, duk_double_t day) {
32284 	duk_int_t day_num;
32285 	duk_bool_t is_leap;
32286 	duk_small_int_t i, n;
32287 
32288 	/* Assume that year, month, day are all coerced to whole numbers.
32289 	 * They may also be NaN or infinity, in which case this function
32290 	 * must return NaN or infinity to ensure time value becomes NaN.
32291 	 * If 'day' is NaN, the final return will end up returning a NaN,
32292 	 * so it doesn't need to be checked here.
32293 	 */
32294 
32295 	if (!DUK_ISFINITE(year) || !DUK_ISFINITE(month)) {
32296 		return DUK_DOUBLE_NAN;
32297 	}
32298 
32299 	year += DUK_FLOOR(month / 12.0);
32300 
32301 	month = DUK_FMOD(month, 12.0);
32302 	if (month < 0.0) {
32303 		/* handle negative values */
32304 		month += 12.0;
32305 	}
32306 
32307 	/* The algorithm in E5.1 Section 15.9.1.12 normalizes month, but
32308 	 * does not normalize the day-of-month (nor check whether or not
32309 	 * it is finite) because it's not necessary for finding the day
32310 	 * number which matches the (year,month) pair.
32311 	 *
32312 	 * We assume that duk__day_from_year() is exact here.
32313 	 *
32314 	 * Without an explicit infinity / NaN check in the beginning,
32315 	 * day_num would be a bogus integer here.
32316 	 *
32317 	 * It's possible for 'year' to be out of integer range here.
32318 	 * If so, we need to return NaN without integer overflow.
32319 	 * This fixes test-bug-setyear-overflow.js.
32320 	 */
32321 
32322 	if (!duk_bi_date_year_in_valid_range(year)) {
32323 		DUK_DD(DUK_DDPRINT("year not in ecmascript valid range, avoid integer overflow: %lf", (double) year));
32324 		return DUK_DOUBLE_NAN;
32325 	}
32326 	day_num = duk__day_from_year((duk_int_t) year);
32327 	is_leap = duk_bi_date_is_leap_year((duk_int_t) year);
32328 
32329 	n = (duk_small_int_t) month;
32330 	for (i = 0; i < n; i++) {
32331 		day_num += duk__days_in_month[i];
32332 		if (i == 1 && is_leap) {
32333 			day_num++;
32334 		}
32335 	}
32336 
32337 	/* If 'day' is NaN, returns NaN. */
32338 	return (duk_double_t) day_num + day;
32339 }
32340 
32341 /* Split time value into parts.  The time value may contain fractions (it may
32342  * come from duk_time_to_components() API call) which are truncated.  Possible
32343  * local time adjustment has already been applied when reading the time value.
32344  */
duk_bi_date_timeval_to_parts(duk_double_t d,duk_int_t * parts,duk_double_t * dparts,duk_small_uint_t flags)32345 DUK_INTERNAL void duk_bi_date_timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_double_t *dparts, duk_small_uint_t flags) {
32346 	duk_double_t d1, d2;
32347 	duk_int_t t1, t2;
32348 	duk_int_t day_since_epoch;
32349 	duk_int_t year;  /* does not fit into 16 bits */
32350 	duk_small_int_t day_in_year;
32351 	duk_small_int_t month;
32352 	duk_small_int_t day;
32353 	duk_small_int_t dim;
32354 	duk_int_t jan1_since_epoch;
32355 	duk_small_int_t jan1_weekday;
32356 	duk_int_t equiv_year;
32357 	duk_small_uint_t i;
32358 	duk_bool_t is_leap;
32359 	duk_small_int_t arridx;
32360 
32361 	DUK_ASSERT(DUK_ISFINITE(d));    /* caller checks */
32362 	d = DUK_FLOOR(d);  /* remove fractions if present */
32363 	DUK_ASSERT(duk_double_equals(DUK_FLOOR(d), d));
32364 
32365 	/* The timevalue must be in valid ECMAScript range, but since a local
32366 	 * time offset can be applied, we need to allow a +/- 24h leeway to
32367 	 * the value.  In other words, although the UTC time is within the
32368 	 * ECMAScript range, the local part values can be just outside of it.
32369 	 */
32370 	DUK_UNREF(duk_bi_date_timeval_in_leeway_range);
32371 	DUK_ASSERT(duk_bi_date_timeval_in_leeway_range(d));
32372 
32373 	/* These computations are guaranteed to be exact for the valid
32374 	 * E5 time value range, assuming milliseconds without fractions.
32375 	 */
32376 	d1 = (duk_double_t) DUK_FMOD(d, (double) DUK_DATE_MSEC_DAY);
32377 	if (d1 < 0.0) {
32378 		/* deal with negative values */
32379 		d1 += (duk_double_t) DUK_DATE_MSEC_DAY;
32380 	}
32381 	d2 = DUK_FLOOR((double) (d / (duk_double_t) DUK_DATE_MSEC_DAY));
32382 	DUK_ASSERT(duk_double_equals(d2 * ((duk_double_t) DUK_DATE_MSEC_DAY) + d1, d));
32383 	/* now expected to fit into a 32-bit integer */
32384 	t1 = (duk_int_t) d1;
32385 	t2 = (duk_int_t) d2;
32386 	day_since_epoch = t2;
32387 	DUK_ASSERT(duk_double_equals((duk_double_t) t1, d1));
32388 	DUK_ASSERT(duk_double_equals((duk_double_t) t2, d2));
32389 
32390 	/* t1 = milliseconds within day (fits 32 bit)
32391 	 * t2 = day number from epoch (fits 32 bit, may be negative)
32392 	 */
32393 
32394 	parts[DUK_DATE_IDX_MILLISECOND] = t1 % 1000; t1 /= 1000;
32395 	parts[DUK_DATE_IDX_SECOND] = t1 % 60; t1 /= 60;
32396 	parts[DUK_DATE_IDX_MINUTE] = t1 % 60; t1 /= 60;
32397 	parts[DUK_DATE_IDX_HOUR] = t1;
32398 	DUK_ASSERT(parts[DUK_DATE_IDX_MILLISECOND] >= 0 && parts[DUK_DATE_IDX_MILLISECOND] <= 999);
32399 	DUK_ASSERT(parts[DUK_DATE_IDX_SECOND] >= 0 && parts[DUK_DATE_IDX_SECOND] <= 59);
32400 	DUK_ASSERT(parts[DUK_DATE_IDX_MINUTE] >= 0 && parts[DUK_DATE_IDX_MINUTE] <= 59);
32401 	DUK_ASSERT(parts[DUK_DATE_IDX_HOUR] >= 0 && parts[DUK_DATE_IDX_HOUR] <= 23);
32402 
32403 	DUK_DDD(DUK_DDDPRINT("d=%lf, d1=%lf, d2=%lf, t1=%ld, t2=%ld, parts: hour=%ld min=%ld sec=%ld msec=%ld",
32404 	                     (double) d, (double) d1, (double) d2, (long) t1, (long) t2,
32405 	                     (long) parts[DUK_DATE_IDX_HOUR],
32406 	                     (long) parts[DUK_DATE_IDX_MINUTE],
32407 	                     (long) parts[DUK_DATE_IDX_SECOND],
32408 	                     (long) parts[DUK_DATE_IDX_MILLISECOND]));
32409 
32410 	/* This assert depends on the input parts representing time inside
32411 	 * the ECMAScript range.
32412 	 */
32413 	DUK_ASSERT(t2 + DUK__WEEKDAY_MOD_ADDER >= 0);
32414 	parts[DUK_DATE_IDX_WEEKDAY] = (t2 + 4 + DUK__WEEKDAY_MOD_ADDER) % 7;  /* E5.1 Section 15.9.1.6 */
32415 	DUK_ASSERT(parts[DUK_DATE_IDX_WEEKDAY] >= 0 && parts[DUK_DATE_IDX_WEEKDAY] <= 6);
32416 
32417 	year = duk__year_from_day(t2, &day_in_year);
32418 	day = day_in_year;
32419 	is_leap = duk_bi_date_is_leap_year(year);
32420 	for (month = 0; month < 12; month++) {
32421 		dim = duk__days_in_month[month];
32422 		if (month == 1 && is_leap) {
32423 			dim++;
32424 		}
32425 		DUK_DDD(DUK_DDDPRINT("month=%ld, dim=%ld, day=%ld",
32426 		                     (long) month, (long) dim, (long) day));
32427 		if (day < dim) {
32428 			break;
32429 		}
32430 		day -= dim;
32431 	}
32432 	DUK_DDD(DUK_DDDPRINT("final month=%ld", (long) month));
32433 	DUK_ASSERT(month >= 0 && month <= 11);
32434 	DUK_ASSERT(day >= 0 && day <= 31);
32435 
32436 	/* Equivalent year mapping, used to avoid DST trouble when platform
32437 	 * may fail to provide reasonable DST answers for dates outside the
32438 	 * ordinary range (e.g. 1970-2038).  An equivalent year has the same
32439 	 * leap-year-ness as the original year and begins on the same weekday
32440 	 * (Jan 1).
32441 	 *
32442 	 * The year 2038 is avoided because there seem to be problems with it
32443 	 * on some platforms.  The year 1970 is also avoided as there were
32444 	 * practical problems with it; an equivalent year is used for it too,
32445 	 * which breaks some DST computations for 1970 right now, see e.g.
32446 	 * test-bi-date-tzoffset-brute-fi.js.
32447 	 */
32448 	if ((flags & DUK_DATE_FLAG_EQUIVYEAR) && (year < 1971 || year > 2037)) {
32449 		DUK_ASSERT(is_leap == 0 || is_leap == 1);
32450 
32451 		jan1_since_epoch = day_since_epoch - day_in_year;  /* day number for Jan 1 since epoch */
32452 		DUK_ASSERT(jan1_since_epoch + DUK__WEEKDAY_MOD_ADDER >= 0);
32453 		jan1_weekday = (jan1_since_epoch + 4 + DUK__WEEKDAY_MOD_ADDER) % 7;  /* E5.1 Section 15.9.1.6 */
32454 		DUK_ASSERT(jan1_weekday >= 0 && jan1_weekday <= 6);
32455 		arridx = jan1_weekday;
32456 		if (is_leap) {
32457 			arridx += 7;
32458 		}
32459 		DUK_ASSERT(arridx >= 0 && arridx < (duk_small_int_t) (sizeof(duk__date_equivyear) / sizeof(duk_uint8_t)));
32460 
32461 		equiv_year = (duk_int_t) duk__date_equivyear[arridx] + 1970;
32462 		year = equiv_year;
32463 		DUK_DDD(DUK_DDDPRINT("equiv year mapping, year=%ld, day_in_year=%ld, day_since_epoch=%ld, "
32464 		                     "jan1_since_epoch=%ld, jan1_weekday=%ld -> equiv year %ld",
32465 		                     (long) year, (long) day_in_year, (long) day_since_epoch,
32466 		                     (long) jan1_since_epoch, (long) jan1_weekday, (long) equiv_year));
32467 	}
32468 
32469 	parts[DUK_DATE_IDX_YEAR] = year;
32470 	parts[DUK_DATE_IDX_MONTH] = month;
32471 	parts[DUK_DATE_IDX_DAY] = day;
32472 
32473 	if (flags & DUK_DATE_FLAG_ONEBASED) {
32474 		parts[DUK_DATE_IDX_MONTH]++;  /* zero-based -> one-based */
32475 		parts[DUK_DATE_IDX_DAY]++;    /* -""- */
32476 	}
32477 
32478 	if (dparts != NULL) {
32479 		for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) {
32480 			dparts[i] = (duk_double_t) parts[i];
32481 		}
32482 	}
32483 }
32484 
32485 /* Compute time value from (double) parts.  The parts can be either UTC
32486  * or local time; if local, they need to be (conceptually) converted into
32487  * UTC time.  The parts may represent valid or invalid time, and may be
32488  * wildly out of range (but may cancel each other and still come out in
32489  * the valid Date range).
32490  */
duk_bi_date_get_timeval_from_dparts(duk_double_t * dparts,duk_small_uint_t flags)32491 DUK_INTERNAL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags) {
32492 #if defined(DUK_USE_PARANOID_DATE_COMPUTATION)
32493 	/* See comments below on MakeTime why these are volatile. */
32494 	volatile duk_double_t tmp_time;
32495 	volatile duk_double_t tmp_day;
32496 	volatile duk_double_t d;
32497 #else
32498 	duk_double_t tmp_time;
32499 	duk_double_t tmp_day;
32500 	duk_double_t d;
32501 #endif
32502 	duk_small_uint_t i;
32503 	duk_int_t tzoff, tzoffprev1, tzoffprev2;
32504 
32505 	/* Expects 'this' at top of stack on entry. */
32506 
32507 	/* Coerce all finite parts with ToInteger().  ToInteger() must not
32508 	 * be called for NaN/Infinity because it will convert e.g. NaN to
32509 	 * zero.  If ToInteger() has already been called, this has no side
32510 	 * effects and is idempotent.
32511 	 *
32512 	 * Don't read dparts[DUK_DATE_IDX_WEEKDAY]; it will cause Valgrind
32513 	 * issues if the value is uninitialized.
32514 	 */
32515 	for (i = 0; i <= DUK_DATE_IDX_MILLISECOND; i++) {
32516 		/* SCANBUILD: scan-build complains here about assigned value
32517 		 * being garbage or undefined.  This is correct but operating
32518 		 * on undefined values has no ill effect and is ignored by the
32519 		 * caller in the case where this happens.
32520 		 */
32521 		d = dparts[i];
32522 		if (DUK_ISFINITE(d)) {
32523 			dparts[i] = duk_js_tointeger_number(d);
32524 		}
32525 	}
32526 
32527 	/* Use explicit steps in computation to try to ensure that
32528 	 * computation happens with intermediate results coerced to
32529 	 * double values (instead of using something more accurate).
32530 	 * E.g. E5.1 Section 15.9.1.11 requires use of IEEE 754
32531 	 * rules (= ECMAScript '+' and '*' operators).
32532 	 *
32533 	 * Without 'volatile' even this approach fails on some platform
32534 	 * and compiler combinations.  For instance, gcc 4.8.1 on Ubuntu
32535 	 * 64-bit, with -m32 and without -std=c99, test-bi-date-canceling.js
32536 	 * would fail because of some optimizations when computing tmp_time
32537 	 * (MakeTime below).  Adding 'volatile' to tmp_time solved this
32538 	 * particular problem (annoyingly, also adding debug prints or
32539 	 * running the executable under valgrind hides it).
32540 	 */
32541 
32542 	/* MakeTime */
32543 	tmp_time = 0.0;
32544 	tmp_time += dparts[DUK_DATE_IDX_HOUR] * ((duk_double_t) DUK_DATE_MSEC_HOUR);
32545 	tmp_time += dparts[DUK_DATE_IDX_MINUTE] * ((duk_double_t) DUK_DATE_MSEC_MINUTE);
32546 	tmp_time += dparts[DUK_DATE_IDX_SECOND] * ((duk_double_t) DUK_DATE_MSEC_SECOND);
32547 	tmp_time += dparts[DUK_DATE_IDX_MILLISECOND];
32548 
32549 	/* MakeDay */
32550 	tmp_day = duk__make_day(dparts[DUK_DATE_IDX_YEAR], dparts[DUK_DATE_IDX_MONTH], dparts[DUK_DATE_IDX_DAY]);
32551 
32552 	/* MakeDate */
32553 	d = tmp_day * ((duk_double_t) DUK_DATE_MSEC_DAY) + tmp_time;
32554 
32555 	DUK_DDD(DUK_DDDPRINT("time=%lf day=%lf --> timeval=%lf",
32556 	                     (double) tmp_time, (double) tmp_day, (double) d));
32557 
32558 	/* Optional UTC conversion. */
32559 	if (flags & DUK_DATE_FLAG_LOCALTIME) {
32560 		/* DUK_USE_DATE_GET_LOCAL_TZOFFSET() needs to be called with a
32561 		 * time value computed from UTC parts.  At this point we only
32562 		 * have 'd' which is a time value computed from local parts, so
32563 		 * it is off by the UTC-to-local time offset which we don't know
32564 		 * yet.  The current solution for computing the UTC-to-local
32565 		 * time offset is to iterate a few times and detect a fixed
32566 		 * point or a two-cycle loop (or a sanity iteration limit),
32567 		 * see test-bi-date-local-parts.js and test-bi-date-tzoffset-basic-fi.js.
32568 		 *
32569 		 * E5.1 Section 15.9.1.9:
32570 		 * UTC(t) = t - LocalTZA - DaylightSavingTA(t - LocalTZA)
32571 		 *
32572 		 * For NaN/inf, DUK_USE_DATE_GET_LOCAL_TZOFFSET() returns 0.
32573 		 */
32574 
32575 #if 0
32576 		/* Old solution: don't iterate, incorrect */
32577 		tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);
32578 		DUK_DDD(DUK_DDDPRINT("tzoffset w/o iteration, tzoff=%ld", (long) tzoff));
32579 		d -= tzoff * 1000L;
32580 		DUK_UNREF(tzoffprev1);
32581 		DUK_UNREF(tzoffprev2);
32582 #endif
32583 
32584 		/* Iteration solution */
32585 		tzoff = 0;
32586 		tzoffprev1 = 999999999L;  /* invalid value which never matches */
32587 		for (i = 0; i < DUK__LOCAL_TZOFFSET_MAXITER; i++) {
32588 			tzoffprev2 = tzoffprev1;
32589 			tzoffprev1 = tzoff;
32590 			tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d - tzoff * 1000L);
32591 			DUK_DDD(DUK_DDDPRINT("tzoffset iteration, i=%d, tzoff=%ld, tzoffprev1=%ld tzoffprev2=%ld",
32592 			                     (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
32593 			if (tzoff == tzoffprev1) {
32594 				DUK_DDD(DUK_DDDPRINT("tzoffset iteration finished, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
32595 				                     (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
32596 				break;
32597 			} else if (tzoff == tzoffprev2) {
32598 				/* Two value cycle, see e.g. test-bi-date-tzoffset-basic-fi.js.
32599 				 * In these cases, favor a higher tzoffset to get a consistent
32600 				 * result which is independent of iteration count.  Not sure if
32601 				 * this is a generically correct solution.
32602 				 */
32603 				DUK_DDD(DUK_DDDPRINT("tzoffset iteration two-value cycle, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
32604 				                     (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
32605 				if (tzoffprev1 > tzoff) {
32606 					tzoff = tzoffprev1;
32607 				}
32608 				break;
32609 			}
32610 		}
32611 		DUK_DDD(DUK_DDDPRINT("tzoffset iteration, tzoff=%ld", (long) tzoff));
32612 		d -= tzoff * 1000L;
32613 	}
32614 
32615 	/* TimeClip(), which also handles Infinity -> NaN conversion */
32616 	d = duk__timeclip(d);
32617 
32618 	return d;
32619 }
32620 
32621 /*
32622  *  API oriented helpers
32623  */
32624 
32625 /* Push 'this' binding, check that it is a Date object; then push the
32626  * internal time value.  At the end, stack is: [ ... this timeval ].
32627  * Returns the time value.  Local time adjustment is done if requested.
32628  */
duk__push_this_get_timeval_tzoffset(duk_hthread * thr,duk_small_uint_t flags,duk_int_t * out_tzoffset)32629 DUK_LOCAL duk_double_t duk__push_this_get_timeval_tzoffset(duk_hthread *thr, duk_small_uint_t flags, duk_int_t *out_tzoffset) {
32630 	duk_hobject *h;
32631 	duk_double_t d;
32632 	duk_int_t tzoffset = 0;
32633 
32634 	duk_push_this(thr);
32635 	h = duk_get_hobject(thr, -1);  /* XXX: getter with class check, useful in built-ins */
32636 	if (h == NULL || DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_DATE) {
32637 		DUK_ERROR_TYPE(thr, "expected Date");
32638 		DUK_WO_NORETURN(return 0.0;);
32639 	}
32640 
32641 	duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
32642 	d = duk_to_number_m1(thr);
32643 	duk_pop(thr);
32644 
32645 	if (DUK_ISNAN(d)) {
32646 		if (flags & DUK_DATE_FLAG_NAN_TO_ZERO) {
32647 			d = 0.0;
32648 		}
32649 		if (flags & DUK_DATE_FLAG_NAN_TO_RANGE_ERROR) {
32650 			DUK_ERROR_RANGE(thr, "Invalid Date");
32651 			DUK_WO_NORETURN(return 0.0;);
32652 		}
32653 	}
32654 	/* if no NaN handling flag, may still be NaN here, but not Inf */
32655 	DUK_ASSERT(!DUK_ISINF(d));
32656 
32657 	if (flags & DUK_DATE_FLAG_LOCALTIME) {
32658 		/* Note: DST adjustment is determined using UTC time.
32659 		 * If 'd' is NaN, tzoffset will be 0.
32660 		 */
32661 		tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);  /* seconds */
32662 		d += tzoffset * 1000L;
32663 	}
32664 	if (out_tzoffset) {
32665 		*out_tzoffset = tzoffset;
32666 	}
32667 
32668 	/* [ ... this ] */
32669 	return d;
32670 }
32671 
duk__push_this_get_timeval(duk_hthread * thr,duk_small_uint_t flags)32672 DUK_LOCAL duk_double_t duk__push_this_get_timeval(duk_hthread *thr, duk_small_uint_t flags) {
32673 	return duk__push_this_get_timeval_tzoffset(thr, flags, NULL);
32674 }
32675 
32676 /* Set timeval to 'this' from dparts, push the new time value onto the
32677  * value stack and return 1 (caller can then tail call us).  Expects
32678  * the value stack to contain 'this' on the stack top.
32679  */
duk__set_this_timeval_from_dparts(duk_hthread * thr,duk_double_t * dparts,duk_small_uint_t flags)32680 DUK_LOCAL duk_ret_t duk__set_this_timeval_from_dparts(duk_hthread *thr, duk_double_t *dparts, duk_small_uint_t flags) {
32681 	duk_double_t d;
32682 
32683 	/* [ ... this ] */
32684 
32685 	d = duk_bi_date_get_timeval_from_dparts(dparts, flags);
32686 	duk_push_number(thr, d);  /* -> [ ... this timeval_new ] */
32687 	duk_dup_top(thr);         /* -> [ ... this timeval_new timeval_new ] */
32688 
32689 	/* Must force write because e.g. .setYear() must work even when
32690 	 * the Date instance is frozen.
32691 	 */
32692 	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
32693 
32694 	/* Stack top: new time value, return 1 to allow tail calls. */
32695 	return 1;
32696 }
32697 
32698 /* 'out_buf' must be at least DUK_BI_DATE_ISO8601_BUFSIZE long. */
duk__format_parts_iso8601(duk_int_t * parts,duk_int_t tzoffset,duk_small_uint_t flags,duk_uint8_t * out_buf)32699 DUK_LOCAL void duk__format_parts_iso8601(duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags, duk_uint8_t *out_buf) {
32700 	char yearstr[8];   /* "-123456\0" */
32701 	char tzstr[8];     /* "+11:22\0" */
32702 	char sep = (flags & DUK_DATE_FLAG_SEP_T) ? DUK_ASC_UC_T : DUK_ASC_SPACE;
32703 
32704 	DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12);
32705 	DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31);
32706 	DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= -999999 && parts[DUK_DATE_IDX_YEAR] <= 999999);
32707 
32708 	/* Note: %06d for positive value, %07d for negative value to include
32709 	 * sign and 6 digits.
32710 	 */
32711 	DUK_SNPRINTF(yearstr,
32712 	             sizeof(yearstr),
32713 	             (parts[DUK_DATE_IDX_YEAR] >= 0 && parts[DUK_DATE_IDX_YEAR] <= 9999) ? "%04ld" :
32714 	                    ((parts[DUK_DATE_IDX_YEAR] >= 0) ? "+%06ld" : "%07ld"),
32715 	             (long) parts[DUK_DATE_IDX_YEAR]);
32716 	yearstr[sizeof(yearstr) - 1] = (char) 0;
32717 
32718 	if (flags & DUK_DATE_FLAG_LOCALTIME) {
32719 		/* tzoffset seconds are dropped; 16 bits suffice for
32720 		 * time offset in minutes
32721 		 */
32722 		const char *fmt;
32723 		duk_small_int_t tmp, arg_hours, arg_minutes;
32724 
32725 		if (tzoffset >= 0) {
32726 			tmp = tzoffset;
32727 			fmt = "+%02d:%02d";
32728 		} else {
32729 			tmp = -tzoffset;
32730 			fmt = "-%02d:%02d";
32731 		}
32732 		tmp = tmp / 60;
32733 		arg_hours = tmp / 60;
32734 		arg_minutes = tmp % 60;
32735 		DUK_ASSERT(arg_hours <= 24);  /* Even less is actually guaranteed for a valid tzoffset. */
32736 		arg_hours = arg_hours & 0x3f;  /* For [0,24] this is a no-op, but fixes GCC 7 warning, see https://github.com/svaarala/duktape/issues/1602. */
32737 
32738 		DUK_SNPRINTF(tzstr, sizeof(tzstr), fmt, (int) arg_hours, (int) arg_minutes);
32739 		tzstr[sizeof(tzstr) - 1] = (char) 0;
32740 	} else {
32741 		tzstr[0] = DUK_ASC_UC_Z;
32742 		tzstr[1] = (char) 0;
32743 	}
32744 
32745 	/* Unlike year, the other parts fit into 16 bits so %d format
32746 	 * is portable.
32747 	 */
32748 	if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {
32749 		DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d%c%02d:%02d:%02d.%03d%s",
32750 		            (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY], (int) sep,
32751 		            (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE],
32752 		            (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND], (const char *) tzstr);
32753 	} else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {
32754 		DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d",
32755 		            (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY]);
32756 	} else {
32757 		DUK_ASSERT(flags & DUK_DATE_FLAG_TOSTRING_TIME);
32758 		DUK_SPRINTF((char *) out_buf, "%02d:%02d:%02d.%03d%s",
32759 		            (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE],
32760 		            (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND],
32761 		            (const char *) tzstr);
32762 	}
32763 }
32764 
32765 /* Helper for string conversion calls: check 'this' binding, get the
32766  * internal time value, and format date and/or time in a few formats.
32767  * Return value allows tail calls.
32768  */
duk__to_string_helper(duk_hthread * thr,duk_small_uint_t flags)32769 DUK_LOCAL duk_ret_t duk__to_string_helper(duk_hthread *thr, duk_small_uint_t flags) {
32770 	duk_double_t d;
32771 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
32772 	duk_int_t tzoffset;  /* seconds, doesn't fit into 16 bits */
32773 	duk_bool_t rc;
32774 	duk_uint8_t buf[DUK_BI_DATE_ISO8601_BUFSIZE];
32775 
32776 	DUK_UNREF(rc);  /* unreferenced with some options */
32777 
32778 	d = duk__push_this_get_timeval_tzoffset(thr, flags, &tzoffset);
32779 	if (DUK_ISNAN(d)) {
32780 		duk_push_hstring_stridx(thr, DUK_STRIDX_INVALID_DATE);
32781 		return 1;
32782 	}
32783 	DUK_ASSERT(DUK_ISFINITE(d));
32784 
32785 	/* formatters always get one-based month/day-of-month */
32786 	duk_bi_date_timeval_to_parts(d, parts, NULL, DUK_DATE_FLAG_ONEBASED);
32787 	DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12);
32788 	DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31);
32789 
32790 	if (flags & DUK_DATE_FLAG_TOSTRING_LOCALE) {
32791 		/* try locale specific formatter; if it refuses to format the
32792 		 * string, fall back to an ISO 8601 formatted value in local
32793 		 * time.
32794 		 */
32795 #if defined(DUK_USE_DATE_FORMAT_STRING)
32796 		/* Contract, either:
32797 		 * - Push string to value stack and return 1
32798 		 * - Don't push anything and return 0
32799 		 */
32800 
32801 		rc = DUK_USE_DATE_FORMAT_STRING(thr, parts, tzoffset, flags);
32802 		if (rc != 0) {
32803 			return 1;
32804 		}
32805 #else
32806 		/* No locale specific formatter; this is OK, we fall back
32807 		 * to ISO 8601.
32808 		 */
32809 #endif
32810 	}
32811 
32812 	/* Different calling convention than above used because the helper
32813 	 * is shared.
32814 	 */
32815 	duk__format_parts_iso8601(parts, tzoffset, flags, buf);
32816 	duk_push_string(thr, (const char *) buf);
32817 	return 1;
32818 }
32819 
32820 /* Helper for component getter calls: check 'this' binding, get the
32821  * internal time value, split it into parts (either as UTC time or
32822  * local time), push a specified component as a return value to the
32823  * value stack and return 1 (caller can then tail call us).
32824  */
duk__get_part_helper(duk_hthread * thr,duk_small_uint_t flags_and_idx)32825 DUK_LOCAL duk_ret_t duk__get_part_helper(duk_hthread *thr, duk_small_uint_t flags_and_idx) {
32826 	duk_double_t d;
32827 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
32828 	duk_small_uint_t idx_part = (duk_small_uint_t) (flags_and_idx >> DUK_DATE_FLAG_VALUE_SHIFT);  /* unpack args */
32829 
32830 	DUK_ASSERT_DISABLE(idx_part >= 0);  /* unsigned */
32831 	DUK_ASSERT(idx_part < DUK_DATE_IDX_NUM_PARTS);
32832 
32833 	d = duk__push_this_get_timeval(thr, flags_and_idx);
32834 	if (DUK_ISNAN(d)) {
32835 		duk_push_nan(thr);
32836 		return 1;
32837 	}
32838 	DUK_ASSERT(DUK_ISFINITE(d));
32839 
32840 	duk_bi_date_timeval_to_parts(d, parts, NULL, flags_and_idx);  /* no need to mask idx portion */
32841 
32842 	/* Setter APIs detect special year numbers (0...99) and apply a +1900
32843 	 * only in certain cases.  The legacy getYear() getter applies -1900
32844 	 * unconditionally.
32845 	 */
32846 	duk_push_int(thr, (flags_and_idx & DUK_DATE_FLAG_SUB1900) ? parts[idx_part] - 1900 : parts[idx_part]);
32847 	return 1;
32848 }
32849 
32850 /* Helper for component setter calls: check 'this' binding, get the
32851  * internal time value, split it into parts (either as UTC time or
32852  * local time), modify one or more components as specified, recompute
32853  * the time value, set it as the internal value.  Finally, push the
32854  * new time value as a return value to the value stack and return 1
32855  * (caller can then tail call us).
32856  */
duk__set_part_helper(duk_hthread * thr,duk_small_uint_t flags_and_maxnargs)32857 DUK_LOCAL duk_ret_t duk__set_part_helper(duk_hthread *thr, duk_small_uint_t flags_and_maxnargs) {
32858 	duk_double_t d;
32859 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
32860 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
32861 	duk_idx_t nargs;
32862 	duk_small_uint_t maxnargs = (duk_small_uint_t) (flags_and_maxnargs >> DUK_DATE_FLAG_VALUE_SHIFT);  /* unpack args */
32863 	duk_small_uint_t idx_first, idx;
32864 	duk_small_uint_t i;
32865 
32866 	nargs = duk_get_top(thr);
32867 	d = duk__push_this_get_timeval(thr, flags_and_maxnargs);
32868 	DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));
32869 
32870 	if (DUK_ISFINITE(d)) {
32871 		duk_bi_date_timeval_to_parts(d, parts, dparts, flags_and_maxnargs);
32872 	} else {
32873 		/* NaN timevalue: we need to coerce the arguments, but
32874 		 * the resulting internal timestamp needs to remain NaN.
32875 		 * This works but is not pretty: parts and dparts will
32876 		 * be partially uninitialized, but we only write to them.
32877 		 */
32878 	}
32879 
32880 	/*
32881 	 *  Determining which datetime components to overwrite based on
32882 	 *  stack arguments is a bit complicated, but important to factor
32883 	 *  out from setters themselves for compactness.
32884 	 *
32885 	 *  If DUK_DATE_FLAG_TIMESETTER, maxnargs indicates setter type:
32886 	 *
32887 	 *   1 -> millisecond
32888 	 *   2 -> second, [millisecond]
32889 	 *   3 -> minute, [second], [millisecond]
32890 	 *   4 -> hour, [minute], [second], [millisecond]
32891 	 *
32892 	 *  Else:
32893 	 *
32894 	 *   1 -> date
32895 	 *   2 -> month, [date]
32896 	 *   3 -> year, [month], [date]
32897 	 *
32898 	 *  By comparing nargs and maxnargs (and flags) we know which
32899 	 *  components to override.  We rely on part index ordering.
32900 	 */
32901 
32902 	if (flags_and_maxnargs & DUK_DATE_FLAG_TIMESETTER) {
32903 		DUK_ASSERT(maxnargs >= 1 && maxnargs <= 4);
32904 		idx_first = DUK_DATE_IDX_MILLISECOND - (maxnargs - 1);
32905 	} else {
32906 		DUK_ASSERT(maxnargs >= 1 && maxnargs <= 3);
32907 		idx_first = DUK_DATE_IDX_DAY - (maxnargs - 1);
32908 	}
32909 	DUK_ASSERT_DISABLE(idx_first >= 0);  /* unsigned */
32910 	DUK_ASSERT(idx_first < DUK_DATE_IDX_NUM_PARTS);
32911 
32912 	for (i = 0; i < maxnargs; i++) {
32913 		if ((duk_idx_t) i >= nargs) {
32914 			/* no argument given -> leave components untouched */
32915 			break;
32916 		}
32917 		idx = idx_first + i;
32918 		DUK_ASSERT_DISABLE(idx >= 0);  /* unsigned */
32919 		DUK_ASSERT(idx < DUK_DATE_IDX_NUM_PARTS);
32920 
32921 		if (idx == DUK_DATE_IDX_YEAR && (flags_and_maxnargs & DUK_DATE_FLAG_YEAR_FIXUP)) {
32922 			duk__twodigit_year_fixup(thr, (duk_idx_t) i);
32923 		}
32924 
32925 		dparts[idx] = duk_to_number(thr, (duk_idx_t) i);
32926 
32927 		if (idx == DUK_DATE_IDX_DAY) {
32928 			/* Day-of-month is one-based in the API, but zero-based
32929 			 * internally, so fix here.  Note that month is zero-based
32930 			 * both in the API and internally.
32931 			 */
32932 			/* SCANBUILD: complains about use of uninitialized values.
32933 			 * The complaint is correct, but operating in undefined
32934 			 * values here is intentional in some cases and the caller
32935 			 * ignores the results.
32936 			 */
32937 			dparts[idx] -= 1.0;
32938 		}
32939 	}
32940 
32941 	/* Leaves new timevalue on stack top and returns 1, which is correct
32942 	 * for part setters.
32943 	 */
32944 	if (DUK_ISFINITE(d)) {
32945 		return duk__set_this_timeval_from_dparts(thr, dparts, flags_and_maxnargs);
32946 	} else {
32947 		/* Internal timevalue is already NaN, so don't touch it. */
32948 		duk_push_nan(thr);
32949 		return 1;
32950 	}
32951 }
32952 
32953 /* Apply ToNumber() to specified index; if ToInteger(val) in [0,99], add
32954  * 1900 and replace value at idx_val.
32955  */
duk__twodigit_year_fixup(duk_hthread * thr,duk_idx_t idx_val)32956 DUK_LOCAL void duk__twodigit_year_fixup(duk_hthread *thr, duk_idx_t idx_val) {
32957 	duk_double_t d;
32958 
32959 	/* XXX: idx_val would fit into 16 bits, but using duk_small_uint_t
32960 	 * might not generate better code due to casting.
32961 	 */
32962 
32963 	/* E5 Sections 15.9.3.1, B.2.4, B.2.5 */
32964 	duk_to_number(thr, idx_val);
32965 	if (duk_is_nan(thr, idx_val)) {
32966 		return;
32967 	}
32968 	duk_dup(thr, idx_val);
32969 	duk_to_int(thr, -1);
32970 	d = duk_get_number(thr, -1);  /* get as double to handle huge numbers correctly */
32971 	if (d >= 0.0 && d <= 99.0) {
32972 		d += 1900.0;
32973 		duk_push_number(thr, d);
32974 		duk_replace(thr, idx_val);
32975 	}
32976 	duk_pop(thr);
32977 }
32978 
32979 /* Set datetime parts from stack arguments, defaulting any missing values.
32980  * Day-of-week is not set; it is not required when setting the time value.
32981  */
duk__set_parts_from_args(duk_hthread * thr,duk_double_t * dparts,duk_idx_t nargs)32982 DUK_LOCAL void duk__set_parts_from_args(duk_hthread *thr, duk_double_t *dparts, duk_idx_t nargs) {
32983 	duk_double_t d;
32984 	duk_small_uint_t i;
32985 	duk_small_uint_t idx;
32986 
32987 	/* Causes a ToNumber() coercion, but doesn't break coercion order since
32988 	 * year is coerced first anyway.
32989 	 */
32990 	duk__twodigit_year_fixup(thr, 0);
32991 
32992 	/* There are at most 7 args, but we use 8 here so that also
32993 	 * DUK_DATE_IDX_WEEKDAY gets initialized (to zero) to avoid the potential
32994 	 * for any Valgrind gripes later.
32995 	 */
32996 	for (i = 0; i < 8; i++) {
32997 		/* Note: rely on index ordering */
32998 		idx = DUK_DATE_IDX_YEAR + i;
32999 		if ((duk_idx_t) i < nargs) {
33000 			d = duk_to_number(thr, (duk_idx_t) i);
33001 			if (idx == DUK_DATE_IDX_DAY) {
33002 				/* Convert day from one-based to zero-based (internal).  This may
33003 				 * cause the day part to be negative, which is OK.
33004 				 */
33005 				d -= 1.0;
33006 			}
33007 		} else {
33008 			/* All components default to 0 except day-of-month which defaults
33009 			 * to 1.  However, because our internal day-of-month is zero-based,
33010 			 * it also defaults to zero here.
33011 			 */
33012 			d = 0.0;
33013 		}
33014 		dparts[idx] = d;
33015 	}
33016 
33017 	DUK_DDD(DUK_DDDPRINT("parts from args -> %lf %lf %lf %lf %lf %lf %lf %lf",
33018 	                     (double) dparts[0], (double) dparts[1],
33019 	                     (double) dparts[2], (double) dparts[3],
33020 	                     (double) dparts[4], (double) dparts[5],
33021 	                     (double) dparts[6], (double) dparts[7]));
33022 }
33023 
33024 /*
33025  *  Indirect magic value lookup for Date methods.
33026  *
33027  *  Date methods don't put their control flags into the function magic value
33028  *  because they wouldn't fit into a LIGHTFUNC's magic field.  Instead, the
33029  *  magic value is set to an index pointing to the array of control flags
33030  *  below.
33031  *
33032  *  This must be kept in strict sync with genbuiltins.py!
33033  */
33034 
33035 static duk_uint16_t duk__date_magics[] = {
33036 	/* 0: toString */
33037 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_LOCALTIME,
33038 
33039 	/* 1: toDateString */
33040 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_LOCALTIME,
33041 
33042 	/* 2: toTimeString */
33043 	DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_LOCALTIME,
33044 
33045 	/* 3: toLocaleString */
33046 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,
33047 
33048 	/* 4: toLocaleDateString */
33049 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,
33050 
33051 	/* 5: toLocaleTimeString */
33052 	DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,
33053 
33054 	/* 6: toUTCString */
33055 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME,
33056 
33057 	/* 7: toISOString */
33058 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_NAN_TO_RANGE_ERROR + DUK_DATE_FLAG_SEP_T,
33059 
33060 	/* 8: getFullYear */
33061 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),
33062 
33063 	/* 9: getUTCFullYear */
33064 	0 + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),
33065 
33066 	/* 10: getMonth */
33067 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MONTH << DUK_DATE_FLAG_VALUE_SHIFT),
33068 
33069 	/* 11: getUTCMonth */
33070 	0 + (DUK_DATE_IDX_MONTH << DUK_DATE_FLAG_VALUE_SHIFT),
33071 
33072 	/* 12: getDate */
33073 	DUK_DATE_FLAG_ONEBASED + DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_DAY << DUK_DATE_FLAG_VALUE_SHIFT),
33074 
33075 	/* 13: getUTCDate */
33076 	DUK_DATE_FLAG_ONEBASED + (DUK_DATE_IDX_DAY << DUK_DATE_FLAG_VALUE_SHIFT),
33077 
33078 	/* 14: getDay */
33079 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_WEEKDAY << DUK_DATE_FLAG_VALUE_SHIFT),
33080 
33081 	/* 15: getUTCDay */
33082 	0 + (DUK_DATE_IDX_WEEKDAY << DUK_DATE_FLAG_VALUE_SHIFT),
33083 
33084 	/* 16: getHours */
33085 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_HOUR << DUK_DATE_FLAG_VALUE_SHIFT),
33086 
33087 	/* 17: getUTCHours */
33088 	0 + (DUK_DATE_IDX_HOUR << DUK_DATE_FLAG_VALUE_SHIFT),
33089 
33090 	/* 18: getMinutes */
33091 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MINUTE << DUK_DATE_FLAG_VALUE_SHIFT),
33092 
33093 	/* 19: getUTCMinutes */
33094 	0 + (DUK_DATE_IDX_MINUTE << DUK_DATE_FLAG_VALUE_SHIFT),
33095 
33096 	/* 20: getSeconds */
33097 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_SECOND << DUK_DATE_FLAG_VALUE_SHIFT),
33098 
33099 	/* 21: getUTCSeconds */
33100 	0 + (DUK_DATE_IDX_SECOND << DUK_DATE_FLAG_VALUE_SHIFT),
33101 
33102 	/* 22: getMilliseconds */
33103 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MILLISECOND << DUK_DATE_FLAG_VALUE_SHIFT),
33104 
33105 	/* 23: getUTCMilliseconds */
33106 	0 + (DUK_DATE_IDX_MILLISECOND << DUK_DATE_FLAG_VALUE_SHIFT),
33107 
33108 	/* 24: setMilliseconds */
33109 	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
33110 
33111 	/* 25: setUTCMilliseconds */
33112 	DUK_DATE_FLAG_TIMESETTER + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
33113 
33114 	/* 26: setSeconds */
33115 	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
33116 
33117 	/* 27: setUTCSeconds */
33118 	DUK_DATE_FLAG_TIMESETTER + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
33119 
33120 	/* 28: setMinutes */
33121 	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
33122 
33123 	/* 29: setUTCMinutes */
33124 	DUK_DATE_FLAG_TIMESETTER + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
33125 
33126 	/* 30: setHours */
33127 	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (4 << DUK_DATE_FLAG_VALUE_SHIFT),
33128 
33129 	/* 31: setUTCHours */
33130 	DUK_DATE_FLAG_TIMESETTER + (4 << DUK_DATE_FLAG_VALUE_SHIFT),
33131 
33132 	/* 32: setDate */
33133 	DUK_DATE_FLAG_LOCALTIME + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
33134 
33135 	/* 33: setUTCDate */
33136 	0 + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
33137 
33138 	/* 34: setMonth */
33139 	DUK_DATE_FLAG_LOCALTIME + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
33140 
33141 	/* 35: setUTCMonth */
33142 	0 + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
33143 
33144 	/* 36: setFullYear */
33145 	DUK_DATE_FLAG_NAN_TO_ZERO + DUK_DATE_FLAG_LOCALTIME + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
33146 
33147 	/* 37: setUTCFullYear */
33148 	DUK_DATE_FLAG_NAN_TO_ZERO + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
33149 
33150 	/* 38: getYear */
33151 	DUK_DATE_FLAG_LOCALTIME + DUK_DATE_FLAG_SUB1900 + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),
33152 
33153 	/* 39: setYear */
33154 	DUK_DATE_FLAG_NAN_TO_ZERO + DUK_DATE_FLAG_YEAR_FIXUP + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
33155 };
33156 
duk__date_get_indirect_magic(duk_hthread * thr)33157 DUK_LOCAL duk_small_uint_t duk__date_get_indirect_magic(duk_hthread *thr) {
33158 	duk_small_uint_t magicidx = (duk_small_uint_t) duk_get_current_magic(thr);
33159 	DUK_ASSERT(magicidx < (duk_small_int_t) (sizeof(duk__date_magics) / sizeof(duk_uint16_t)));
33160 	return (duk_small_uint_t) duk__date_magics[magicidx];
33161 }
33162 
33163 #if defined(DUK_USE_DATE_BUILTIN)
33164 /*
33165  *  Constructor calls
33166  */
33167 
duk_bi_date_constructor(duk_hthread * thr)33168 DUK_INTERNAL duk_ret_t duk_bi_date_constructor(duk_hthread *thr) {
33169 	duk_idx_t nargs = duk_get_top(thr);
33170 	duk_bool_t is_cons = duk_is_constructor_call(thr);
33171 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
33172 	duk_double_t d;
33173 
33174 	DUK_DDD(DUK_DDDPRINT("Date constructor, nargs=%ld, is_cons=%ld", (long) nargs, (long) is_cons));
33175 
33176 	(void) duk_push_object_helper(thr,
33177 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
33178 	                              DUK_HOBJECT_FLAG_FASTREFS |
33179 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DATE),
33180 	                              DUK_BIDX_DATE_PROTOTYPE);
33181 
33182 	/* Unlike most built-ins, the internal [[PrimitiveValue]] of a Date
33183 	 * is mutable.
33184 	 */
33185 
33186 	if (nargs == 0 || !is_cons) {
33187 		d = duk__timeclip(duk_time_get_ecmascript_time_nofrac(thr));
33188 		duk_push_number(thr, d);
33189 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
33190 		if (!is_cons) {
33191 			/* called as a normal function: return new Date().toString() */
33192 			duk_to_string(thr, -1);
33193 		}
33194 		return 1;
33195 	} else if (nargs == 1) {
33196 		const char *str;
33197 		duk_to_primitive(thr, 0, DUK_HINT_NONE);
33198 		str = duk_get_string_notsymbol(thr, 0);
33199 		if (str) {
33200 			duk__parse_string(thr, str);
33201 			duk_replace(thr, 0);  /* may be NaN */
33202 		}
33203 		d = duk__timeclip(duk_to_number(thr, 0));  /* symbols fail here */
33204 		duk_push_number(thr, d);
33205 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
33206 		return 1;
33207 	}
33208 
33209 	duk__set_parts_from_args(thr, dparts, nargs);
33210 
33211 	/* Parts are in local time, convert when setting. */
33212 
33213 	(void) duk__set_this_timeval_from_dparts(thr, dparts, DUK_DATE_FLAG_LOCALTIME /*flags*/);  /* -> [ ... this timeval ] */
33214 	duk_pop(thr);  /* -> [ ... this ] */
33215 	return 1;
33216 }
33217 
duk_bi_date_constructor_parse(duk_hthread * thr)33218 DUK_INTERNAL duk_ret_t duk_bi_date_constructor_parse(duk_hthread *thr) {
33219 	return duk__parse_string(thr, duk_to_string(thr, 0));
33220 }
33221 
duk_bi_date_constructor_utc(duk_hthread * thr)33222 DUK_INTERNAL duk_ret_t duk_bi_date_constructor_utc(duk_hthread *thr) {
33223 	duk_idx_t nargs = duk_get_top(thr);
33224 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
33225 	duk_double_t d;
33226 
33227 	/* Behavior for nargs < 2 is implementation dependent: currently we'll
33228 	 * set a NaN time value (matching V8 behavior) in this case.
33229 	 */
33230 
33231 	if (nargs < 2) {
33232 		duk_push_nan(thr);
33233 	} else {
33234 		duk__set_parts_from_args(thr, dparts, nargs);
33235 		d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
33236 		duk_push_number(thr, d);
33237 	}
33238 	return 1;
33239 }
33240 
duk_bi_date_constructor_now(duk_hthread * thr)33241 DUK_INTERNAL duk_ret_t duk_bi_date_constructor_now(duk_hthread *thr) {
33242 	duk_double_t d;
33243 
33244 	d = duk_time_get_ecmascript_time_nofrac(thr);
33245 	DUK_ASSERT(duk_double_equals(duk__timeclip(d), d));  /* TimeClip() should never be necessary */
33246 	duk_push_number(thr, d);
33247 	return 1;
33248 }
33249 
33250 /*
33251  *  String/JSON conversions
33252  *
33253  *  Human readable conversions are now basically ISO 8601 with a space
33254  *  (instead of 'T') as the date/time separator.  This is a good baseline
33255  *  and is platform independent.
33256  *
33257  *  A shared native helper to provide many conversions.  Magic value contains
33258  *  a set of flags.  The helper provides:
33259  *
33260  *    toString()
33261  *    toDateString()
33262  *    toTimeString()
33263  *    toLocaleString()
33264  *    toLocaleDateString()
33265  *    toLocaleTimeString()
33266  *    toUTCString()
33267  *    toISOString()
33268  *
33269  *  Notes:
33270  *
33271  *    - Date.prototype.toGMTString() and Date.prototype.toUTCString() are
33272  *      required to be the same ECMAScript function object (!), so it is
33273  *      omitted from here.
33274  *
33275  *    - Date.prototype.toUTCString(): E5.1 specification does not require a
33276  *      specific format, but result should be human readable.  The
33277  *      specification suggests using ISO 8601 format with a space (instead
33278  *      of 'T') separator if a more human readable format is not available.
33279  *
33280  *    - Date.prototype.toISOString(): unlike other conversion functions,
33281  *      toISOString() requires a RangeError for invalid date values.
33282  */
33283 
duk_bi_date_prototype_tostring_shared(duk_hthread * thr)33284 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_tostring_shared(duk_hthread *thr) {
33285 	duk_small_uint_t flags = duk__date_get_indirect_magic(thr);
33286 	return duk__to_string_helper(thr, flags);
33287 }
33288 
duk_bi_date_prototype_value_of(duk_hthread * thr)33289 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_value_of(duk_hthread *thr) {
33290 	/* This native function is also used for Date.prototype.getTime()
33291 	 * as their behavior is identical.
33292 	 */
33293 
33294 	duk_double_t d = duk__push_this_get_timeval(thr, 0 /*flags*/);  /* -> [ this ] */
33295 	DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));
33296 	duk_push_number(thr, d);
33297 	return 1;
33298 }
33299 
duk_bi_date_prototype_to_json(duk_hthread * thr)33300 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_to_json(duk_hthread *thr) {
33301 	/* Note: toJSON() is a generic function which works even if 'this'
33302 	 * is not a Date.  The sole argument is ignored.
33303 	 */
33304 
33305 	duk_push_this(thr);
33306 	duk_to_object(thr, -1);
33307 
33308 	duk_dup_top(thr);
33309 	duk_to_primitive(thr, -1, DUK_HINT_NUMBER);
33310 	if (duk_is_number(thr, -1)) {
33311 		duk_double_t d = duk_get_number(thr, -1);
33312 		if (!DUK_ISFINITE(d)) {
33313 			duk_push_null(thr);
33314 			return 1;
33315 		}
33316 	}
33317 	duk_pop(thr);
33318 
33319 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_TO_ISO_STRING);
33320 	duk_dup_m2(thr);  /* -> [ O toIsoString O ] */
33321 	duk_call_method(thr, 0);
33322 	return 1;
33323 }
33324 
33325 /*
33326  *  Getters.
33327  *
33328  *  Implementing getters is quite easy.  The internal time value is either
33329  *  NaN, or represents milliseconds (without fractions) from Jan 1, 1970.
33330  *  The internal time value can be converted to integer parts, and each
33331  *  part will be normalized and will fit into a 32-bit signed integer.
33332  *
33333  *  A shared native helper to provide all getters.  Magic value contains
33334  *  a set of flags and also packs the date component index argument.  The
33335  *  helper provides:
33336  *
33337  *    getFullYear()
33338  *    getUTCFullYear()
33339  *    getMonth()
33340  *    getUTCMonth()
33341  *    getDate()
33342  *    getUTCDate()
33343  *    getDay()
33344  *    getUTCDay()
33345  *    getHours()
33346  *    getUTCHours()
33347  *    getMinutes()
33348  *    getUTCMinutes()
33349  *    getSeconds()
33350  *    getUTCSeconds()
33351  *    getMilliseconds()
33352  *    getUTCMilliseconds()
33353  *    getYear()
33354  *
33355  *  Notes:
33356  *
33357  *    - Date.prototype.getDate(): 'date' means day-of-month, and is
33358  *      zero-based in internal calculations but public API expects it to
33359  *      be one-based.
33360  *
33361  *    - Date.prototype.getTime() and Date.prototype.valueOf() have identical
33362  *      behavior.  They have separate function objects, but share the same C
33363  *      function (duk_bi_date_prototype_value_of).
33364  */
33365 
duk_bi_date_prototype_get_shared(duk_hthread * thr)33366 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_get_shared(duk_hthread *thr) {
33367 	duk_small_uint_t flags_and_idx = duk__date_get_indirect_magic(thr);
33368 	return duk__get_part_helper(thr, flags_and_idx);
33369 }
33370 
duk_bi_date_prototype_get_timezone_offset(duk_hthread * thr)33371 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_hthread *thr) {
33372 	/*
33373 	 *  Return (t - LocalTime(t)) in minutes:
33374 	 *
33375 	 *    t - LocalTime(t) = t - (t + LocalTZA + DaylightSavingTA(t))
33376 	 *                     = -(LocalTZA + DaylightSavingTA(t))
33377 	 *
33378 	 *  where DaylightSavingTA() is checked for time 't'.
33379 	 *
33380 	 *  Note that the sign of the result is opposite to common usage,
33381 	 *  e.g. for EE(S)T which normally is +2h or +3h from UTC, this
33382 	 *  function returns -120 or -180.
33383 	 *
33384 	 */
33385 
33386 	duk_double_t d;
33387 	duk_int_t tzoffset;
33388 
33389 	/* Note: DST adjustment is determined using UTC time. */
33390 	d = duk__push_this_get_timeval(thr, 0 /*flags*/);
33391 	DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));
33392 	if (DUK_ISNAN(d)) {
33393 		duk_push_nan(thr);
33394 	} else {
33395 		DUK_ASSERT(DUK_ISFINITE(d));
33396 		tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);
33397 		duk_push_int(thr, -tzoffset / 60);
33398 	}
33399 	return 1;
33400 }
33401 
33402 /*
33403  *  Setters.
33404  *
33405  *  Setters are a bit more complicated than getters.  Component setters
33406  *  break down the current time value into its (normalized) component
33407  *  parts, replace one or more components with -unnormalized- new values,
33408  *  and the components are then converted back into a time value.  As an
33409  *  example of using unnormalized values:
33410  *
33411  *    var d = new Date(1234567890);
33412  *
33413  *  is equivalent to:
33414  *
33415  *    var d = new Date(0);
33416  *    d.setUTCMilliseconds(1234567890);
33417  *
33418  *  A shared native helper to provide almost all setters.  Magic value
33419  *  contains a set of flags and also packs the "maxnargs" argument.  The
33420  *  helper provides:
33421  *
33422  *    setMilliseconds()
33423  *    setUTCMilliseconds()
33424  *    setSeconds()
33425  *    setUTCSeconds()
33426  *    setMinutes()
33427  *    setUTCMinutes()
33428  *    setHours()
33429  *    setUTCHours()
33430  *    setDate()
33431  *    setUTCDate()
33432  *    setMonth()
33433  *    setUTCMonth()
33434  *    setFullYear()
33435  *    setUTCFullYear()
33436  *    setYear()
33437  *
33438  *  Notes:
33439  *
33440  *    - Date.prototype.setYear() (Section B addition): special year check
33441  *      is omitted.  NaN / Infinity will just flow through and ultimately
33442  *      result in a NaN internal time value.
33443  *
33444  *    - Date.prototype.setYear() does not have optional arguments for
33445  *      setting month and day-in-month (like setFullYear()), but we indicate
33446  *      'maxnargs' to be 3 to get the year written to the correct component
33447  *      index in duk__set_part_helper().  The function has nargs == 1, so only
33448  *      the year will be set regardless of actual argument count.
33449  */
33450 
duk_bi_date_prototype_set_shared(duk_hthread * thr)33451 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_set_shared(duk_hthread *thr) {
33452 	duk_small_uint_t flags_and_maxnargs = duk__date_get_indirect_magic(thr);
33453 	return duk__set_part_helper(thr, flags_and_maxnargs);
33454 }
33455 
duk_bi_date_prototype_set_time(duk_hthread * thr)33456 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_set_time(duk_hthread *thr) {
33457 	duk_double_t d;
33458 
33459 	(void) duk__push_this_get_timeval(thr, 0 /*flags*/); /* -> [ timeval this ] */
33460 	d = duk__timeclip(duk_to_number(thr, 0));
33461 	duk_push_number(thr, d);
33462 	duk_dup_top(thr);
33463 	/* Must force write because .setTime() must work even when
33464 	 * the Date instance is frozen.
33465 	 */
33466 	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
33467 	/* -> [ timeval this timeval ] */
33468 
33469 	return 1;
33470 }
33471 
33472 /*
33473  *  Misc.
33474  */
33475 
33476 #if defined(DUK_USE_SYMBOL_BUILTIN)
duk_bi_date_prototype_toprimitive(duk_hthread * thr)33477 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_toprimitive(duk_hthread *thr) {
33478 	duk_size_t hintlen;
33479 	const char *hintstr;
33480 	duk_int_t hint;
33481 
33482 	/* Invokes OrdinaryToPrimitive() with suitable hint.  Note that the
33483 	 * method is generic, and works on non-Date arguments too.
33484 	 *
33485 	 * https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype-@@toprimitive
33486 	 */
33487 
33488 	duk_push_this(thr);
33489 	duk_require_object(thr, -1);
33490 	DUK_ASSERT_TOP(thr, 2);
33491 
33492 	hintstr = duk_require_lstring(thr, 0, &hintlen);
33493 	if ((hintlen == 6 && DUK_STRCMP(hintstr, "string") == 0) ||
33494 	    (hintlen == 7 && DUK_STRCMP(hintstr, "default") == 0)) {
33495 		hint = DUK_HINT_STRING;
33496 	} else if (hintlen == 6 && DUK_STRCMP(hintstr, "number") == 0) {
33497 		hint = DUK_HINT_NUMBER;
33498 	} else {
33499 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
33500 	}
33501 
33502 	duk_to_primitive_ordinary(thr, -1, hint);
33503 	return 1;
33504 }
33505 #endif  /* DUK_USE_SYMBOL_BUILTIN */
33506 
33507 #endif  /* DUK_USE_DATE_BUILTIN */
33508 
33509 /* automatic undefs */
33510 #undef DUK__CF_ACCEPT
33511 #undef DUK__CF_ACCEPT_NUL
33512 #undef DUK__CF_NEG
33513 #undef DUK__DPRINT_DPARTS
33514 #undef DUK__DPRINT_PARTS
33515 #undef DUK__DPRINT_PARTS_AND_DPARTS
33516 #undef DUK__LOCAL_TZOFFSET_MAXITER
33517 #undef DUK__NUM_ISO8601_PARSER_PARTS
33518 #undef DUK__PACK_RULE
33519 #undef DUK__PI_DAY
33520 #undef DUK__PI_HOUR
33521 #undef DUK__PI_MILLISECOND
33522 #undef DUK__PI_MINUTE
33523 #undef DUK__PI_MONTH
33524 #undef DUK__PI_SECOND
33525 #undef DUK__PI_TZHOUR
33526 #undef DUK__PI_TZMINUTE
33527 #undef DUK__PI_YEAR
33528 #undef DUK__PM_DAY
33529 #undef DUK__PM_HOUR
33530 #undef DUK__PM_MILLISECOND
33531 #undef DUK__PM_MINUTE
33532 #undef DUK__PM_MONTH
33533 #undef DUK__PM_SECOND
33534 #undef DUK__PM_TZHOUR
33535 #undef DUK__PM_TZMINUTE
33536 #undef DUK__PM_YEAR
33537 #undef DUK__RULE_MASK_PART_SEP
33538 #undef DUK__SI_COLON
33539 #undef DUK__SI_MINUS
33540 #undef DUK__SI_NUL
33541 #undef DUK__SI_PERIOD
33542 #undef DUK__SI_PLUS
33543 #undef DUK__SI_SPACE
33544 #undef DUK__SI_T
33545 #undef DUK__SI_Z
33546 #undef DUK__SM_COLON
33547 #undef DUK__SM_MINUS
33548 #undef DUK__SM_NUL
33549 #undef DUK__SM_PERIOD
33550 #undef DUK__SM_PLUS
33551 #undef DUK__SM_SPACE
33552 #undef DUK__SM_T
33553 #undef DUK__SM_Z
33554 #undef DUK__UNPACK_RULE
33555 #undef DUK__WEEKDAY_MOD_ADDER
33556 #undef DUK__YEAR
33557 /*
33558  *  Unix-like Date providers
33559  *
33560  *  Generally useful Unix / POSIX / ANSI Date providers.
33561  */
33562 
33563 /* #include duk_internal.h -> already included */
33564 
33565 /* The necessary #includes are in place in duk_config.h. */
33566 
33567 /* Buffer sizes for some UNIX calls.  Larger than strictly necessary
33568  * to avoid Valgrind errors.
33569  */
33570 #define DUK__STRPTIME_BUF_SIZE  64
33571 #define DUK__STRFTIME_BUF_SIZE  64
33572 
33573 #if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
33574 /* Get current ECMAScript time (= UNIX/Posix time, but in milliseconds). */
duk_bi_date_get_now_gettimeofday(void)33575 DUK_INTERNAL duk_double_t duk_bi_date_get_now_gettimeofday(void) {
33576 	struct timeval tv;
33577 	duk_double_t d;
33578 
33579 	if (gettimeofday(&tv, NULL) != 0) {
33580 		DUK_D(DUK_DPRINT("gettimeofday() failed"));
33581 		return 0.0;
33582 	}
33583 
33584 	/* As of Duktape 2.2.0 allow fractions. */
33585 	d = ((duk_double_t) tv.tv_sec) * 1000.0 +
33586 	    ((duk_double_t) tv.tv_usec) / 1000.0;
33587 
33588 	return d;
33589 }
33590 #endif  /* DUK_USE_DATE_NOW_GETTIMEOFDAY */
33591 
33592 #if defined(DUK_USE_DATE_NOW_TIME)
33593 /* Not a very good provider: only full seconds are available. */
duk_bi_date_get_now_time(void)33594 DUK_INTERNAL duk_double_t duk_bi_date_get_now_time(void) {
33595 	time_t t;
33596 
33597 	t = time(NULL);
33598 	if (t == (time_t) -1) {
33599 		DUK_D(DUK_DPRINT("time() failed"));
33600 		return 0.0;
33601 	}
33602 	return ((duk_double_t) t) * 1000.0;
33603 }
33604 #endif  /* DUK_USE_DATE_NOW_TIME */
33605 
33606 #if defined(DUK_USE_DATE_TZO_GMTIME) || defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME_S)
33607 /* Get local time offset (in seconds) for a certain (UTC) instant 'd'. */
duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d)33608 DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d) {
33609 	time_t t, t1, t2;
33610 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
33611 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
33612 	struct tm tms[2];
33613 #if defined(DUK_USE_DATE_TZO_GMTIME)
33614 	struct tm *tm_ptr;
33615 #endif
33616 
33617 	/* For NaN/inf, the return value doesn't matter. */
33618 	if (!DUK_ISFINITE(d)) {
33619 		return 0;
33620 	}
33621 
33622 	/* If not within ECMAScript range, some integer time calculations
33623 	 * won't work correctly (and some asserts will fail), so bail out
33624 	 * if so.  This fixes test-bug-date-insane-setyear.js.  There is
33625 	 * a +/- 24h leeway in this range check to avoid a test262 corner
33626 	 * case documented in test-bug-date-timeval-edges.js.
33627 	 */
33628 	if (!duk_bi_date_timeval_in_leeway_range(d)) {
33629 		DUK_DD(DUK_DDPRINT("timeval not within valid range, skip tzoffset computation to avoid integer overflows"));
33630 		return 0;
33631 	}
33632 
33633 	/*
33634 	 *  This is a bit tricky to implement portably.  The result depends
33635 	 *  on the timestamp (specifically, DST depends on the timestamp).
33636 	 *  If e.g. UNIX APIs are used, they'll have portability issues with
33637 	 *  very small and very large years.
33638 	 *
33639 	 *  Current approach:
33640 	 *
33641 	 *  - Stay within portable UNIX limits by using equivalent year mapping.
33642 	 *    Avoid year 1970 and 2038 as some conversions start to fail, at
33643 	 *    least on some platforms.  Avoiding 1970 means that there are
33644 	 *    currently DST discrepancies for 1970.
33645 	 *
33646 	 *  - Create a UTC and local time breakdowns from 't'.  Then create
33647 	 *    a time_t using gmtime() and localtime() and compute the time
33648 	 *    difference between the two.
33649 	 *
33650 	 *  Equivalent year mapping (E5 Section 15.9.1.8):
33651 	 *
33652 	 *    If the host environment provides functionality for determining
33653 	 *    daylight saving time, the implementation of ECMAScript is free
33654 	 *    to map the year in question to an equivalent year (same
33655 	 *    leap-year-ness and same starting week day for the year) for which
33656 	 *    the host environment provides daylight saving time information.
33657 	 *    The only restriction is that all equivalent years should produce
33658 	 *    the same result.
33659 	 *
33660 	 *  This approach is quite reasonable but not entirely correct, e.g.
33661 	 *  the specification also states (E5 Section 15.9.1.8):
33662 	 *
33663 	 *    The implementation of ECMAScript should not try to determine
33664 	 *    whether the exact time was subject to daylight saving time, but
33665 	 *    just whether daylight saving time would have been in effect if
33666 	 *    the _current daylight saving time algorithm_ had been used at the
33667 	 *    time.  This avoids complications such as taking into account the
33668 	 *    years that the locale observed daylight saving time year round.
33669 	 *
33670 	 *  Since we rely on the platform APIs for conversions between local
33671 	 *  time and UTC, we can't guarantee the above.  Rather, if the platform
33672 	 *  has historical DST rules they will be applied.  This seems to be the
33673 	 *  general preferred direction in ECMAScript standardization (or at least
33674 	 *  implementations) anyway, and even the equivalent year mapping should
33675 	 *  be disabled if the platform is known to handle DST properly for the
33676 	 *  full ECMAScript range.
33677 	 *
33678 	 *  The following has useful discussion and links:
33679 	 *
33680 	 *    https://bugzilla.mozilla.org/show_bug.cgi?id=351066
33681 	 */
33682 
33683 	duk_bi_date_timeval_to_parts(d, parts, dparts, DUK_DATE_FLAG_EQUIVYEAR /*flags*/);
33684 	DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= 1970 && parts[DUK_DATE_IDX_YEAR] <= 2038);
33685 
33686 	d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
33687 	DUK_ASSERT(d >= 0 && d < 2147483648.0 * 1000.0);  /* unsigned 31-bit range */
33688 	t = (time_t) (d / 1000.0);
33689 	DUK_DDD(DUK_DDDPRINT("timeval: %lf -> time_t %ld", (double) d, (long) t));
33690 
33691 	duk_memzero((void *) tms, sizeof(struct tm) * 2);
33692 
33693 #if defined(DUK_USE_DATE_TZO_GMTIME_R)
33694 	(void) gmtime_r(&t, &tms[0]);
33695 	(void) localtime_r(&t, &tms[1]);
33696 #elif defined(DUK_USE_DATE_TZO_GMTIME_S)
33697 	(void) gmtime_s(&t, &tms[0]);
33698 	(void) localtime_s(&t, &tms[1]);
33699 #elif defined(DUK_USE_DATE_TZO_GMTIME)
33700 	tm_ptr = gmtime(&t);
33701 	duk_memcpy((void *) &tms[0], tm_ptr, sizeof(struct tm));
33702 	tm_ptr = localtime(&t);
33703 	duk_memcpy((void *) &tms[1], tm_ptr, sizeof(struct tm));
33704 #else
33705 #error internal error
33706 #endif
33707 	DUK_DDD(DUK_DDDPRINT("gmtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
33708 	                     "wday:%ld,yday:%ld,isdst:%ld}",
33709 	                     (long) tms[0].tm_sec, (long) tms[0].tm_min, (long) tms[0].tm_hour,
33710 	                     (long) tms[0].tm_mday, (long) tms[0].tm_mon, (long) tms[0].tm_year,
33711 	                     (long) tms[0].tm_wday, (long) tms[0].tm_yday, (long) tms[0].tm_isdst));
33712 	DUK_DDD(DUK_DDDPRINT("localtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
33713 	                     "wday:%ld,yday:%ld,isdst:%ld}",
33714 	                     (long) tms[1].tm_sec, (long) tms[1].tm_min, (long) tms[1].tm_hour,
33715 	                     (long) tms[1].tm_mday, (long) tms[1].tm_mon, (long) tms[1].tm_year,
33716 	                     (long) tms[1].tm_wday, (long) tms[1].tm_yday, (long) tms[1].tm_isdst));
33717 
33718 	/* tm_isdst is both an input and an output to mktime(), use 0 to
33719 	 * avoid DST handling in mktime():
33720 	 * - https://github.com/svaarala/duktape/issues/406
33721 	 * - http://stackoverflow.com/questions/8558919/mktime-and-tm-isdst
33722 	 */
33723 	tms[0].tm_isdst = 0;
33724 	tms[1].tm_isdst = 0;
33725 	t1 = mktime(&tms[0]);  /* UTC */
33726 	t2 = mktime(&tms[1]);  /* local */
33727 	if (t1 == (time_t) -1 || t2 == (time_t) -1) {
33728 		/* This check used to be for (t < 0) but on some platforms
33729 		 * time_t is unsigned and apparently the proper way to detect
33730 		 * an mktime() error return is the cast above.  See e.g.:
33731 		 * http://pubs.opengroup.org/onlinepubs/009695299/functions/mktime.html
33732 		 */
33733 		goto mktime_error;
33734 	}
33735 	DUK_DDD(DUK_DDDPRINT("t1=%ld (utc), t2=%ld (local)", (long) t1, (long) t2));
33736 
33737 	/* Compute final offset in seconds, positive if local time ahead of
33738 	 * UTC (returned value is UTC-to-local offset).
33739 	 *
33740 	 * difftime() returns a double, so coercion to int generates quite
33741 	 * a lot of code.  Direct subtraction is not portable, however.
33742 	 * XXX: allow direct subtraction on known platforms.
33743 	 */
33744 #if 0
33745 	return (duk_int_t) (t2 - t1);
33746 #endif
33747 	return (duk_int_t) difftime(t2, t1);
33748 
33749  mktime_error:
33750 	/* XXX: return something more useful, so that caller can throw? */
33751 	DUK_D(DUK_DPRINT("mktime() failed, d=%lf", (double) d));
33752 	return 0;
33753 }
33754 #endif  /* DUK_USE_DATE_TZO_GMTIME */
33755 
33756 #if defined(DUK_USE_DATE_PRS_STRPTIME)
duk_bi_date_parse_string_strptime(duk_hthread * thr,const char * str)33757 DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_strptime(duk_hthread *thr, const char *str) {
33758 	struct tm tm;
33759 	time_t t;
33760 	char buf[DUK__STRPTIME_BUF_SIZE];
33761 
33762 	/* Copy to buffer with slack to avoid Valgrind gripes from strptime. */
33763 	DUK_ASSERT(str != NULL);
33764 	duk_memzero(buf, sizeof(buf));  /* valgrind whine without this */
33765 	DUK_SNPRINTF(buf, sizeof(buf), "%s", (const char *) str);
33766 	buf[sizeof(buf) - 1] = (char) 0;
33767 
33768 	DUK_DDD(DUK_DDDPRINT("parsing: '%s'", (const char *) buf));
33769 
33770 	duk_memzero(&tm, sizeof(tm));
33771 	if (strptime((const char *) buf, "%c", &tm) != NULL) {
33772 		DUK_DDD(DUK_DDDPRINT("before mktime: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
33773 		                     "wday:%ld,yday:%ld,isdst:%ld}",
33774 		                     (long) tm.tm_sec, (long) tm.tm_min, (long) tm.tm_hour,
33775 		                     (long) tm.tm_mday, (long) tm.tm_mon, (long) tm.tm_year,
33776 		                     (long) tm.tm_wday, (long) tm.tm_yday, (long) tm.tm_isdst));
33777 		tm.tm_isdst = -1;  /* negative: dst info not available */
33778 
33779 		t = mktime(&tm);
33780 		DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t));
33781 		if (t >= 0) {
33782 			duk_push_number(thr, ((duk_double_t) t) * 1000.0);
33783 			return 1;
33784 		}
33785 	}
33786 
33787 	return 0;
33788 }
33789 #endif  /* DUK_USE_DATE_PRS_STRPTIME */
33790 
33791 #if defined(DUK_USE_DATE_PRS_GETDATE)
duk_bi_date_parse_string_getdate(duk_hthread * thr,const char * str)33792 DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_getdate(duk_hthread *thr, const char *str) {
33793 	struct tm tm;
33794 	duk_small_int_t rc;
33795 	time_t t;
33796 
33797 	/* For this to work, DATEMSK must be set, so this is not very
33798 	 * convenient for an embeddable interpreter.
33799 	 */
33800 
33801 	duk_memzero(&tm, sizeof(struct tm));
33802 	rc = (duk_small_int_t) getdate_r(str, &tm);
33803 	DUK_DDD(DUK_DDDPRINT("getdate_r() -> %ld", (long) rc));
33804 
33805 	if (rc == 0) {
33806 		t = mktime(&tm);
33807 		DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t));
33808 		if (t >= 0) {
33809 			duk_push_number(thr, (duk_double_t) t);
33810 			return 1;
33811 		}
33812 	}
33813 
33814 	return 0;
33815 }
33816 #endif  /* DUK_USE_DATE_PRS_GETDATE */
33817 
33818 #if defined(DUK_USE_DATE_FMT_STRFTIME)
duk_bi_date_format_parts_strftime(duk_hthread * thr,duk_int_t * parts,duk_int_t tzoffset,duk_small_uint_t flags)33819 DUK_INTERNAL duk_bool_t duk_bi_date_format_parts_strftime(duk_hthread *thr, duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags) {
33820 	char buf[DUK__STRFTIME_BUF_SIZE];
33821 	struct tm tm;
33822 	const char *fmt;
33823 
33824 	DUK_UNREF(tzoffset);
33825 
33826 	/* If the platform doesn't support the entire ECMAScript range, we need
33827 	 * to return 0 so that the caller can fall back to the default formatter.
33828 	 *
33829 	 * For now, assume that if time_t is 8 bytes or more, the whole ECMAScript
33830 	 * range is supported.  For smaller time_t values (4 bytes in practice),
33831 	 * assumes that the signed 32-bit range is supported.
33832 	 *
33833 	 * XXX: detect this more correctly per platform.  The size of time_t is
33834 	 * probably not an accurate guarantee of strftime() supporting or not
33835 	 * supporting a large time range (the full ECMAScript range).
33836 	 */
33837 	if (sizeof(time_t) < 8 &&
33838 	    (parts[DUK_DATE_IDX_YEAR] < 1970 || parts[DUK_DATE_IDX_YEAR] > 2037)) {
33839 		/* be paranoid for 32-bit time values (even avoiding negative ones) */
33840 		return 0;
33841 	}
33842 
33843 	duk_memzero(&tm, sizeof(tm));
33844 	tm.tm_sec = parts[DUK_DATE_IDX_SECOND];
33845 	tm.tm_min = parts[DUK_DATE_IDX_MINUTE];
33846 	tm.tm_hour = parts[DUK_DATE_IDX_HOUR];
33847 	tm.tm_mday = parts[DUK_DATE_IDX_DAY];       /* already one-based */
33848 	tm.tm_mon = parts[DUK_DATE_IDX_MONTH] - 1;  /* one-based -> zero-based */
33849 	tm.tm_year = parts[DUK_DATE_IDX_YEAR] - 1900;
33850 	tm.tm_wday = parts[DUK_DATE_IDX_WEEKDAY];
33851 	tm.tm_isdst = 0;
33852 
33853 	duk_memzero(buf, sizeof(buf));
33854 	if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {
33855 		fmt = "%c";
33856 	} else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {
33857 		fmt = "%x";
33858 	} else {
33859 		DUK_ASSERT(flags & DUK_DATE_FLAG_TOSTRING_TIME);
33860 		fmt = "%X";
33861 	}
33862 	(void) strftime(buf, sizeof(buf) - 1, fmt, &tm);
33863 	DUK_ASSERT(buf[sizeof(buf) - 1] == 0);
33864 
33865 	duk_push_string(thr, buf);
33866 	return 1;
33867 }
33868 #endif  /* DUK_USE_DATE_FMT_STRFTIME */
33869 
33870 #if defined(DUK_USE_GET_MONOTONIC_TIME_CLOCK_GETTIME)
duk_bi_date_get_monotonic_time_clock_gettime(void)33871 DUK_INTERNAL duk_double_t duk_bi_date_get_monotonic_time_clock_gettime(void) {
33872 	struct timespec ts;
33873 
33874 	if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
33875 		return (duk_double_t) ts.tv_sec * 1000.0 + (duk_double_t) ts.tv_nsec / 1000000.0;
33876 	} else {
33877 		DUK_D(DUK_DPRINT("clock_gettime(CLOCK_MONOTONIC) failed"));
33878 		return 0.0;
33879 	}
33880 }
33881 #endif
33882 
33883 /* automatic undefs */
33884 #undef DUK__STRFTIME_BUF_SIZE
33885 #undef DUK__STRPTIME_BUF_SIZE
33886 /*
33887  *  Windows Date providers
33888  *
33889  *  Platform specific links:
33890  *
33891  *    - http://msdn.microsoft.com/en-us/library/windows/desktop/ms725473(v=vs.85).aspx
33892  */
33893 
33894 /* #include duk_internal.h -> already included */
33895 
33896 /* The necessary #includes are in place in duk_config.h. */
33897 
33898 #if defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS)
33899 /* Shared Windows helpers. */
duk__convert_systime_to_ularge(const SYSTEMTIME * st,ULARGE_INTEGER * res)33900 DUK_LOCAL void duk__convert_systime_to_ularge(const SYSTEMTIME *st, ULARGE_INTEGER *res) {
33901 	FILETIME ft;
33902 	if (SystemTimeToFileTime(st, &ft) == 0) {
33903 		DUK_D(DUK_DPRINT("SystemTimeToFileTime() failed, returning 0"));
33904 		res->QuadPart = 0;
33905 	} else {
33906 		res->LowPart = ft.dwLowDateTime;
33907 		res->HighPart = ft.dwHighDateTime;
33908 	}
33909 }
33910 
33911 #if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS)
duk__convert_filetime_to_ularge(const FILETIME * ft,ULARGE_INTEGER * res)33912 DUK_LOCAL void duk__convert_filetime_to_ularge(const FILETIME *ft, ULARGE_INTEGER *res) {
33913 	res->LowPart = ft->dwLowDateTime;
33914 	res->HighPart = ft->dwHighDateTime;
33915 }
33916 #endif  /* DUK_USE_DATE_NOW_WINDOWS_SUBMS */
33917 
duk__set_systime_jan1970(SYSTEMTIME * st)33918 DUK_LOCAL void duk__set_systime_jan1970(SYSTEMTIME *st) {
33919 	duk_memzero((void *) st, sizeof(*st));
33920 	st->wYear = 1970;
33921 	st->wMonth = 1;
33922 	st->wDayOfWeek = 4;  /* not sure whether or not needed; Thursday */
33923 	st->wDay = 1;
33924 	DUK_ASSERT(st->wHour == 0);
33925 	DUK_ASSERT(st->wMinute == 0);
33926 	DUK_ASSERT(st->wSecond == 0);
33927 	DUK_ASSERT(st->wMilliseconds == 0);
33928 }
33929 #endif  /* defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS) */
33930 
33931 #if defined(DUK_USE_DATE_NOW_WINDOWS)
duk_bi_date_get_now_windows(void)33932 DUK_INTERNAL duk_double_t duk_bi_date_get_now_windows(void) {
33933 	/* Suggested step-by-step method from documentation of RtlTimeToSecondsSince1970:
33934 	 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724928(v=vs.85).aspx
33935 	 */
33936 	SYSTEMTIME st1, st2;
33937 	ULARGE_INTEGER tmp1, tmp2;
33938 
33939 	GetSystemTime(&st1);
33940 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
33941 
33942 	duk__set_systime_jan1970(&st2);
33943 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);
33944 
33945 	/* Difference is in 100ns units, convert to milliseconds, keeping
33946 	 * fractions since Duktape 2.2.0.  This is only theoretical because
33947 	 * SYSTEMTIME is limited to milliseconds.
33948 	 */
33949 	return (duk_double_t) ((LONGLONG) tmp1.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000.0;
33950 }
33951 #endif  /* DUK_USE_DATE_NOW_WINDOWS */
33952 
33953 #if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS)
duk_bi_date_get_now_windows_subms(void)33954 DUK_INTERNAL duk_double_t duk_bi_date_get_now_windows_subms(void) {
33955 	/* Variant of the basic algorithm using GetSystemTimePreciseAsFileTime()
33956 	 * for more accuracy.
33957 	 */
33958 	FILETIME ft1;
33959 	SYSTEMTIME st2;
33960 	ULARGE_INTEGER tmp1, tmp2;
33961 
33962 	GetSystemTimePreciseAsFileTime(&ft1);
33963 	duk__convert_filetime_to_ularge((const FILETIME *) &ft1, &tmp1);
33964 
33965 	duk__set_systime_jan1970(&st2);
33966 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);
33967 
33968 	/* Difference is in 100ns units, convert to milliseconds, keeping
33969 	 * fractions since Duktape 2.2.0.
33970 	 */
33971 	return (duk_double_t) ((LONGLONG) tmp1.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000.0;
33972 }
33973 #endif  /* DUK_USE_DATE_NOW_WINDOWS */
33974 
33975 #if defined(DUK_USE_DATE_TZO_WINDOWS)
duk_bi_date_get_local_tzoffset_windows(duk_double_t d)33976 DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d) {
33977 	SYSTEMTIME st1;
33978 	SYSTEMTIME st2;
33979 	SYSTEMTIME st3;
33980 	ULARGE_INTEGER tmp1;
33981 	ULARGE_INTEGER tmp2;
33982 	ULARGE_INTEGER tmp3;
33983 	FILETIME ft1;
33984 
33985 	/* XXX: handling of timestamps outside Windows supported range.
33986 	 * How does Windows deal with dates before 1600?  Does windows
33987 	 * support all ECMAScript years (like -200000 and +200000)?
33988 	 * Should equivalent year mapping be used here too?  If so, use
33989 	 * a shared helper (currently integrated into timeval-to-parts).
33990 	 */
33991 
33992 	/* Use the approach described in "Remarks" of FileTimeToLocalFileTime:
33993 	 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724277(v=vs.85).aspx
33994 	 */
33995 
33996 	duk__set_systime_jan1970(&st1);
33997 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
33998 	tmp2.QuadPart = (ULONGLONG) (d * 10000.0);  /* millisec -> 100ns units since jan 1, 1970 */
33999 	tmp2.QuadPart += tmp1.QuadPart;             /* input 'd' in Windows UTC, 100ns units */
34000 
34001 	ft1.dwLowDateTime = tmp2.LowPart;
34002 	ft1.dwHighDateTime = tmp2.HighPart;
34003 	if (FileTimeToSystemTime((const FILETIME *) &ft1, &st2) == 0) {
34004 		DUK_D(DUK_DPRINT("FileTimeToSystemTime() failed, return tzoffset 0"));
34005 		return 0;
34006 	}
34007 	if (SystemTimeToTzSpecificLocalTime((LPTIME_ZONE_INFORMATION) NULL, &st2, &st3) == 0) {
34008 		DUK_D(DUK_DPRINT("SystemTimeToTzSpecificLocalTime() failed, return tzoffset 0"));
34009 		return 0;
34010 	}
34011 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st3, &tmp3);
34012 
34013 	/* Positive if local time ahead of UTC. */
34014 	return (duk_int_t) (((LONGLONG) tmp3.QuadPart - (LONGLONG) tmp2.QuadPart) / DUK_I64_CONSTANT(10000000));  /* seconds */
34015 }
34016 #endif  /* DUK_USE_DATE_TZO_WINDOWS */
34017 
34018 #if defined(DUK_USE_DATE_TZO_WINDOWS_NO_DST)
duk_bi_date_get_local_tzoffset_windows_no_dst(duk_double_t d)34019 DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_windows_no_dst(duk_double_t d) {
34020 	SYSTEMTIME st1;
34021 	SYSTEMTIME st2;
34022 	FILETIME ft1;
34023 	FILETIME ft2;
34024 	ULARGE_INTEGER tmp1;
34025 	ULARGE_INTEGER tmp2;
34026 
34027 	/* Do a similar computation to duk_bi_date_get_local_tzoffset_windows
34028 	 * but without accounting for daylight savings time.  Use this on
34029 	 * Windows platforms (like Durango) that don't support the
34030 	 * SystemTimeToTzSpecificLocalTime() call.
34031 	 */
34032 
34033 	/* current time not needed for this computation */
34034 	DUK_UNREF(d);
34035 
34036 	duk__set_systime_jan1970(&st1);
34037 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
34038 
34039 	ft1.dwLowDateTime = tmp1.LowPart;
34040 	ft1.dwHighDateTime = tmp1.HighPart;
34041 	if (FileTimeToLocalFileTime((const FILETIME *) &ft1, &ft2) == 0) {
34042 		DUK_D(DUK_DPRINT("FileTimeToLocalFileTime() failed, return tzoffset 0"));
34043 		return 0;
34044 	}
34045 	if (FileTimeToSystemTime((const FILETIME *) &ft2, &st2) == 0) {
34046 		DUK_D(DUK_DPRINT("FileTimeToSystemTime() failed, return tzoffset 0"));
34047 		return 0;
34048 	}
34049 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);
34050 
34051 	return (duk_int_t) (((LONGLONG) tmp2.QuadPart - (LONGLONG) tmp1.QuadPart) / DUK_I64_CONSTANT(10000000));  /* seconds */
34052 }
34053 #endif  /* DUK_USE_DATE_TZO_WINDOWS_NO_DST */
34054 
34055 #if defined(DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC)
duk_bi_date_get_monotonic_time_windows_qpc(void)34056 DUK_INTERNAL duk_double_t duk_bi_date_get_monotonic_time_windows_qpc(void) {
34057 	LARGE_INTEGER count, freq;
34058 
34059 	/* There are legacy issues with QueryPerformanceCounter():
34060 	 * - Potential jumps: https://support.microsoft.com/en-us/help/274323/performance-counter-value-may-unexpectedly-leap-forward
34061 	 * - Differences between cores (XP): https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx#qpc_support_in_windows_versions
34062 	 *
34063 	 * We avoid these by enabling QPC by default only for Vista or later.
34064 	 */
34065 
34066 	if (QueryPerformanceCounter(&count) && QueryPerformanceFrequency(&freq)) {
34067 		/* XXX: QueryPerformanceFrequency() can be cached */
34068 		return (duk_double_t) count.QuadPart / (duk_double_t) freq.QuadPart * 1000.0;
34069 	} else {
34070 		/* MSDN: "On systems that run Windows XP or later, the function
34071 		 * will always succeed and will thus never return zero."
34072 		 * Provide minimal error path just in case user enables this
34073 		 * feature in pre-XP Windows.
34074 		 */
34075 		return 0.0;
34076 	}
34077 }
34078 #endif  /* DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC */
34079 /*
34080  *  Duktape built-ins
34081  *
34082  *  Size optimization note: it might seem that vararg multipurpose functions
34083  *  like fin(), enc(), and dec() are not very size optimal, but using a single
34084  *  user-visible ECMAScript function saves a lot of run-time footprint; each
34085  *  Function instance takes >100 bytes.  Using a shared native helper and a
34086  *  'magic' value won't save much if there are multiple Function instances
34087  *  anyway.
34088  */
34089 
34090 /* #include duk_internal.h -> already included */
34091 
34092 #if defined(DUK_USE_DUKTAPE_BUILTIN)
34093 
duk_bi_duktape_object_info(duk_hthread * thr)34094 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_info(duk_hthread *thr) {
34095 	duk_inspect_value(thr, -1);
34096 	return 1;
34097 }
34098 
duk_bi_duktape_object_act(duk_hthread * thr)34099 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_act(duk_hthread *thr) {
34100 	duk_int_t level;
34101 
34102 	level = duk_to_int(thr, 0);
34103 	duk_inspect_callstack_entry(thr, level);
34104 	return 1;
34105 }
34106 
duk_bi_duktape_object_gc(duk_hthread * thr)34107 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_gc(duk_hthread *thr) {
34108 	duk_small_uint_t flags;
34109 
34110 	flags = (duk_small_uint_t) duk_get_uint(thr, 0);
34111 	duk_heap_mark_and_sweep(thr->heap, flags);
34112 
34113 	/* XXX: Not sure what the best return value would be in the API.
34114 	 * Return true for now.
34115 	 */
34116 	duk_push_true(thr);
34117 	return 1;
34118 }
34119 
34120 #if defined(DUK_USE_FINALIZER_SUPPORT)
duk_bi_duktape_object_fin(duk_hthread * thr)34121 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_fin(duk_hthread *thr) {
34122 	(void) duk_require_hobject(thr, 0);
34123 	if (duk_get_top(thr) >= 2) {
34124 		/* Set: currently a finalizer is disabled by setting it to
34125 		 * undefined; this does not remove the property at the moment.
34126 		 * The value could be type checked to be either a function
34127 		 * or something else; if something else, the property could
34128 		 * be deleted.  Must use duk_set_finalizer() to keep
34129 		 * DUK_HOBJECT_FLAG_HAVE_FINALIZER in sync.
34130 		 */
34131 		duk_set_top(thr, 2);
34132 		duk_set_finalizer(thr, 0);
34133 		return 0;
34134 	} else {
34135 		/* Get. */
34136 		DUK_ASSERT(duk_get_top(thr) == 1);
34137 		duk_get_finalizer(thr, 0);
34138 		return 1;
34139 	}
34140 }
34141 #endif  /* DUK_USE_FINALIZER_SUPPORT */
34142 
duk_bi_duktape_object_enc(duk_hthread * thr)34143 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_enc(duk_hthread *thr) {
34144 	duk_hstring *h_str;
34145 
34146 	/* Vararg function: must be careful to check/require arguments.
34147 	 * The JSON helpers accept invalid indices and treat them like
34148 	 * non-existent optional parameters.
34149 	 */
34150 
34151 	h_str = duk_require_hstring(thr, 0);  /* Could reject symbols, but no point: won't match comparisons. */
34152 	duk_require_valid_index(thr, 1);
34153 
34154 	if (h_str == DUK_HTHREAD_STRING_HEX(thr)) {
34155 		duk_set_top(thr, 2);
34156 		duk_hex_encode(thr, 1);
34157 		DUK_ASSERT_TOP(thr, 2);
34158 	} else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) {
34159 		duk_set_top(thr, 2);
34160 		duk_base64_encode(thr, 1);
34161 		DUK_ASSERT_TOP(thr, 2);
34162 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JX)
34163 	} else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {
34164 		duk_bi_json_stringify_helper(thr,
34165 		                             1 /*idx_value*/,
34166 		                             2 /*idx_replacer*/,
34167 		                             3 /*idx_space*/,
34168 		                             DUK_JSON_FLAG_EXT_CUSTOM |
34169 		                             DUK_JSON_FLAG_ASCII_ONLY |
34170 		                             DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/);
34171 #endif
34172 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JC)
34173 	} else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {
34174 		duk_bi_json_stringify_helper(thr,
34175 		                             1 /*idx_value*/,
34176 		                             2 /*idx_replacer*/,
34177 		                             3 /*idx_space*/,
34178 		                             DUK_JSON_FLAG_EXT_COMPATIBLE |
34179 		                             DUK_JSON_FLAG_ASCII_ONLY /*flags*/);
34180 #endif
34181 	} else {
34182 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
34183 	}
34184 	return 1;
34185 }
34186 
duk_bi_duktape_object_dec(duk_hthread * thr)34187 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_dec(duk_hthread *thr) {
34188 	duk_hstring *h_str;
34189 
34190 	/* Vararg function: must be careful to check/require arguments.
34191 	 * The JSON helpers accept invalid indices and treat them like
34192 	 * non-existent optional parameters.
34193 	 */
34194 
34195 	h_str = duk_require_hstring(thr, 0);  /* Could reject symbols, but no point: won't match comparisons */
34196 	duk_require_valid_index(thr, 1);
34197 
34198 	if (h_str == DUK_HTHREAD_STRING_HEX(thr)) {
34199 		duk_set_top(thr, 2);
34200 		duk_hex_decode(thr, 1);
34201 		DUK_ASSERT_TOP(thr, 2);
34202 	} else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) {
34203 		duk_set_top(thr, 2);
34204 		duk_base64_decode(thr, 1);
34205 		DUK_ASSERT_TOP(thr, 2);
34206 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JX)
34207 	} else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {
34208 		duk_bi_json_parse_helper(thr,
34209 		                         1 /*idx_value*/,
34210 		                         2 /*idx_replacer*/,
34211 		                         DUK_JSON_FLAG_EXT_CUSTOM /*flags*/);
34212 #endif
34213 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JC)
34214 	} else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {
34215 		duk_bi_json_parse_helper(thr,
34216 		                         1 /*idx_value*/,
34217 		                         2 /*idx_replacer*/,
34218 		                         DUK_JSON_FLAG_EXT_COMPATIBLE /*flags*/);
34219 #endif
34220 	} else {
34221 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
34222 	}
34223 	return 1;
34224 }
34225 
34226 /*
34227  *  Compact an object
34228  */
34229 
duk_bi_duktape_object_compact(duk_hthread * thr)34230 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_compact(duk_hthread *thr) {
34231 	DUK_ASSERT_TOP(thr, 1);
34232 	duk_compact(thr, 0);
34233 	return 1;  /* return the argument object */
34234 }
34235 
34236 #endif  /* DUK_USE_DUKTAPE_BUILTIN */
34237 /*
34238  *  WHATWG Encoding API built-ins
34239  *
34240  *  API specification: https://encoding.spec.whatwg.org/#api
34241  *  Web IDL: https://www.w3.org/TR/WebIDL/
34242  */
34243 
34244 /* #include duk_internal.h -> already included */
34245 
34246 /*
34247  *  Data structures for encoding/decoding
34248  */
34249 
34250 typedef struct {
34251 	duk_uint8_t *out;      /* where to write next byte(s) */
34252 	duk_codepoint_t lead;  /* lead surrogate */
34253 } duk__encode_context;
34254 
34255 typedef struct {
34256 	/* UTF-8 decoding state */
34257 	duk_codepoint_t codepoint;  /* built up incrementally */
34258 	duk_uint8_t upper;          /* max value of next byte (decode error otherwise) */
34259 	duk_uint8_t lower;          /* min value of next byte (ditto) */
34260 	duk_uint8_t needed;         /* how many more bytes we need */
34261 	duk_uint8_t bom_handled;    /* BOM seen or no longer expected */
34262 
34263 	/* Decoder configuration */
34264 	duk_uint8_t fatal;
34265 	duk_uint8_t ignore_bom;
34266 } duk__decode_context;
34267 
34268 /* The signed duk_codepoint_t type is used to signal a decoded codepoint
34269  * (>= 0) or various other states using negative values.
34270  */
34271 #define DUK__CP_CONTINUE   (-1)  /* continue to next byte, no completed codepoint */
34272 #define DUK__CP_ERROR      (-2)  /* decoding error */
34273 #define DUK__CP_RETRY      (-3)  /* decoding error; retry last byte */
34274 
34275 /*
34276  *  Raw helpers for encoding/decoding
34277  */
34278 
34279 /* Emit UTF-8 (= CESU-8) encoded U+FFFD (replacement char), i.e. ef bf bd. */
duk__utf8_emit_repl(duk_uint8_t * ptr)34280 DUK_LOCAL duk_uint8_t *duk__utf8_emit_repl(duk_uint8_t *ptr) {
34281 	*ptr++ = 0xef;
34282 	*ptr++ = 0xbf;
34283 	*ptr++ = 0xbd;
34284 	return ptr;
34285 }
34286 
duk__utf8_decode_init(duk__decode_context * dec_ctx)34287 DUK_LOCAL void duk__utf8_decode_init(duk__decode_context *dec_ctx) {
34288 	/* (Re)init the decoding state of 'dec_ctx' but leave decoder
34289 	 * configuration fields untouched.
34290 	 */
34291 	dec_ctx->codepoint = 0x0000L;
34292 	dec_ctx->upper = 0xbf;
34293 	dec_ctx->lower = 0x80;
34294 	dec_ctx->needed = 0;
34295 	dec_ctx->bom_handled = 0;
34296 }
34297 
duk__utf8_decode_next(duk__decode_context * dec_ctx,duk_uint8_t x)34298 DUK_LOCAL duk_codepoint_t duk__utf8_decode_next(duk__decode_context *dec_ctx, duk_uint8_t x) {
34299 	/*
34300 	 *  UTF-8 algorithm based on the Encoding specification:
34301 	 *  https://encoding.spec.whatwg.org/#utf-8-decoder
34302 	 *
34303 	 *  Two main states: decoding initial byte vs. decoding continuation
34304 	 *  bytes.  Shortest length encoding is validated by restricting the
34305 	 *  allowed range of first continuation byte using 'lower' and 'upper'.
34306 	 */
34307 
34308 	if (dec_ctx->needed == 0) {
34309 		/* process initial byte */
34310 		if (x <= 0x7f) {
34311 			/* U+0000-U+007F, 1 byte (ASCII) */
34312 			return (duk_codepoint_t) x;
34313 		} else if (x >= 0xc2 && x <= 0xdf) {
34314 			/* U+0080-U+07FF, 2 bytes */
34315 			dec_ctx->needed = 1;
34316 			dec_ctx->codepoint = x & 0x1f;
34317 			DUK_ASSERT(dec_ctx->lower == 0x80);
34318 			DUK_ASSERT(dec_ctx->upper == 0xbf);
34319 			return DUK__CP_CONTINUE;
34320 		} else if (x >= 0xe0 && x <= 0xef) {
34321 			/* U+0800-U+FFFF, 3 bytes */
34322 			if (x == 0xe0) {
34323 				dec_ctx->lower = 0xa0;
34324 				DUK_ASSERT(dec_ctx->upper == 0xbf);
34325 			} else if (x == 0xed) {
34326 				DUK_ASSERT(dec_ctx->lower == 0x80);
34327 				dec_ctx->upper = 0x9f;
34328 			}
34329 			dec_ctx->needed = 2;
34330 			dec_ctx->codepoint = x & 0x0f;
34331 			return DUK__CP_CONTINUE;
34332 		} else if (x >= 0xf0 && x <= 0xf4) {
34333 			/* U+010000-U+10FFFF, 4 bytes */
34334 			if (x == 0xf0) {
34335 				dec_ctx->lower = 0x90;
34336 				DUK_ASSERT(dec_ctx->upper == 0xbf);
34337 			} else if (x == 0xf4) {
34338 				DUK_ASSERT(dec_ctx->lower == 0x80);
34339 				dec_ctx->upper = 0x8f;
34340 			}
34341 			dec_ctx->needed = 3;
34342 			dec_ctx->codepoint = x & 0x07;
34343 			return DUK__CP_CONTINUE;
34344 		} else {
34345 			/* not a legal initial byte */
34346 			return DUK__CP_ERROR;
34347 		}
34348 	} else {
34349 		/* process continuation byte */
34350 		if (x >= dec_ctx->lower && x <= dec_ctx->upper) {
34351 			dec_ctx->lower = 0x80;
34352 			dec_ctx->upper = 0xbf;
34353 			dec_ctx->codepoint = (dec_ctx->codepoint << 6) | (x & 0x3f);
34354 			if (--dec_ctx->needed > 0) {
34355 				/* need more bytes */
34356 				return DUK__CP_CONTINUE;
34357 			} else {
34358 				/* got a codepoint */
34359 				duk_codepoint_t ret;
34360 				DUK_ASSERT(dec_ctx->codepoint <= 0x10ffffL);  /* Decoding rules guarantee. */
34361 				ret = dec_ctx->codepoint;
34362 				dec_ctx->codepoint = 0x0000L;
34363 				dec_ctx->needed = 0;
34364 				return ret;
34365 			}
34366 		} else {
34367 			/* We just encountered an illegal UTF-8 continuation byte.  This might
34368 			 * be the initial byte of the next character; if we return a plain
34369 			 * error status and the decoder is in replacement mode, the character
34370 			 * will be masked.  We still need to alert the caller to the error
34371 			 * though.
34372 			 */
34373 			dec_ctx->codepoint = 0x0000L;
34374 			dec_ctx->needed = 0;
34375 			dec_ctx->lower = 0x80;
34376 			dec_ctx->upper = 0xbf;
34377 			return DUK__CP_RETRY;
34378 		}
34379 	}
34380 }
34381 
34382 #if defined(DUK_USE_ENCODING_BUILTINS)
duk__utf8_encode_char(void * udata,duk_codepoint_t codepoint)34383 DUK_LOCAL void duk__utf8_encode_char(void *udata, duk_codepoint_t codepoint) {
34384 	duk__encode_context *enc_ctx;
34385 
34386 	DUK_ASSERT(codepoint >= 0);
34387 	enc_ctx = (duk__encode_context *) udata;
34388 	DUK_ASSERT(enc_ctx != NULL);
34389 
34390 #if !defined(DUK_USE_PREFER_SIZE)
34391 	if (codepoint <= 0x7f && enc_ctx->lead == 0x0000L) {
34392 		/* Fast path for ASCII. */
34393 		*enc_ctx->out++ = (duk_uint8_t) codepoint;
34394 		return;
34395 	}
34396 #endif
34397 
34398 	if (DUK_UNLIKELY(codepoint > 0x10ffffL)) {
34399 		/* cannot legally encode in UTF-8 */
34400 		codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
34401 	} else if (codepoint >= 0xd800L && codepoint <= 0xdfffL) {
34402 		if (codepoint <= 0xdbffL) {
34403 			/* high surrogate */
34404 			duk_codepoint_t prev_lead = enc_ctx->lead;
34405 			enc_ctx->lead = codepoint;
34406 			if (prev_lead == 0x0000L) {
34407 				/* high surrogate, no output */
34408 				return;
34409 			} else {
34410 				/* consecutive high surrogates, consider first one unpaired */
34411 				codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
34412 			}
34413 		} else {
34414 			/* low surrogate */
34415 			if (enc_ctx->lead != 0x0000L) {
34416 				codepoint = (duk_codepoint_t) (0x010000L + ((enc_ctx->lead - 0xd800L) << 10) + (codepoint - 0xdc00L));
34417 				enc_ctx->lead = 0x0000L;
34418 			} else {
34419 				/* unpaired low surrogate */
34420 				DUK_ASSERT(enc_ctx->lead == 0x0000L);
34421 				codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
34422 			}
34423 		}
34424 	} else {
34425 		if (enc_ctx->lead != 0x0000L) {
34426 			/* unpaired high surrogate: emit replacement character and the input codepoint */
34427 			enc_ctx->lead = 0x0000L;
34428 			enc_ctx->out = duk__utf8_emit_repl(enc_ctx->out);
34429 		}
34430 	}
34431 
34432 	/* Codepoint may be original input, a decoded surrogate pair, or may
34433 	 * have been replaced with U+FFFD.
34434 	 */
34435 	enc_ctx->out += duk_unicode_encode_xutf8((duk_ucodepoint_t) codepoint, enc_ctx->out);
34436 }
34437 #endif  /* DUK_USE_ENCODING_BUILTINS */
34438 
34439 /* Shared helper for buffer-to-string using a TextDecoder() compatible UTF-8
34440  * decoder.
34441  */
duk__decode_helper(duk_hthread * thr,duk__decode_context * dec_ctx)34442 DUK_LOCAL duk_ret_t duk__decode_helper(duk_hthread *thr, duk__decode_context *dec_ctx) {
34443 	const duk_uint8_t *input;
34444 	duk_size_t len = 0;
34445 	duk_size_t len_tmp;
34446 	duk_bool_t stream = 0;
34447 	duk_codepoint_t codepoint;
34448 	duk_uint8_t *output;
34449 	const duk_uint8_t *in;
34450 	duk_uint8_t *out;
34451 
34452 	DUK_ASSERT(dec_ctx != NULL);
34453 
34454 	/* Careful with input buffer pointer: any side effects involving
34455 	 * code execution (e.g. getters, coercion calls, and finalizers)
34456 	 * may cause a resize and invalidate a pointer we've read.  This
34457 	 * is why the pointer is actually looked up at the last minute.
34458 	 * Argument validation must still happen first to match WHATWG
34459 	 * required side effect order.
34460 	 */
34461 
34462 	if (duk_is_undefined(thr, 0)) {
34463 		duk_push_fixed_buffer_nozero(thr, 0);
34464 		duk_replace(thr, 0);
34465 	}
34466 	(void) duk_require_buffer_data(thr, 0, &len);  /* Need 'len', avoid pointer. */
34467 
34468 	if (duk_check_type_mask(thr, 1, DUK_TYPE_MASK_UNDEFINED |
34469 	                                DUK_TYPE_MASK_NULL |
34470 	                                DUK_TYPE_MASK_NONE)) {
34471 		/* Use defaults, treat missing value like undefined. */
34472 	} else {
34473 		duk_require_type_mask(thr, 1, DUK_TYPE_MASK_UNDEFINED |
34474 	                                      DUK_TYPE_MASK_NULL |
34475 	                                      DUK_TYPE_MASK_LIGHTFUNC |
34476 	                                      DUK_TYPE_MASK_BUFFER |
34477 		                              DUK_TYPE_MASK_OBJECT);
34478 		if (duk_get_prop_literal(thr, 1, "stream")) {
34479 			stream = duk_to_boolean(thr, -1);
34480 		}
34481 	}
34482 
34483 	/* Allowance is 3*len in the general case because all bytes may potentially
34484 	 * become U+FFFD.  If the first byte completes a non-BMP codepoint it will
34485 	 * decode to a CESU-8 surrogate pair (6 bytes) so we allow 3 extra bytes to
34486 	 * compensate: (1*3)+3 = 6.  Non-BMP codepoints are safe otherwise because
34487 	 * the 4->6 expansion is well under the 3x allowance.
34488 	 *
34489 	 * XXX: As with TextEncoder, need a better buffer allocation strategy here.
34490 	 */
34491 	if (len >= (DUK_HBUFFER_MAX_BYTELEN / 3) - 3) {
34492 		DUK_ERROR_TYPE(thr, DUK_STR_RESULT_TOO_LONG);
34493 		DUK_WO_NORETURN(return 0;);
34494 	}
34495 	output = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, 3 + (3 * len));  /* used parts will be always manually written over */
34496 
34497 	input = (const duk_uint8_t *) duk_get_buffer_data(thr, 0, &len_tmp);
34498 	DUK_ASSERT(input != NULL || len == 0);
34499 	if (DUK_UNLIKELY(len != len_tmp)) {
34500 		/* Very unlikely but possible: source buffer was resized by
34501 		 * a side effect when fixed buffer was pushed.  Output buffer
34502 		 * may not be large enough to hold output, so just fail if
34503 		 * length has changed.
34504 		 */
34505 		DUK_D(DUK_DPRINT("input buffer resized by side effect, fail"));
34506 		goto fail_type;
34507 	}
34508 
34509 	/* From this point onwards it's critical that no side effect occur
34510 	 * which may disturb 'input': finalizer execution, property accesses,
34511 	 * active coercions, etc.  Even an allocation related mark-and-sweep
34512 	 * may affect the pointer because it may trigger a pending finalizer.
34513 	 */
34514 
34515 	in = input;
34516 	out = output;
34517 	while (in < input + len) {
34518 		codepoint = duk__utf8_decode_next(dec_ctx, *in++);
34519 		if (codepoint < 0) {
34520 			if (codepoint == DUK__CP_CONTINUE) {
34521 				continue;
34522 			}
34523 
34524 			/* Decoding error with or without retry. */
34525 			DUK_ASSERT(codepoint == DUK__CP_ERROR || codepoint == DUK__CP_RETRY);
34526 			if (codepoint == DUK__CP_RETRY) {
34527 				--in;  /* retry last byte */
34528 			}
34529 			/* replacement mode: replace with U+FFFD */
34530 			codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
34531 			if (dec_ctx->fatal) {
34532 				/* fatal mode: throw a TypeError */
34533 				goto fail_type;
34534 			}
34535 			/* Continue with 'codepoint', Unicode replacement. */
34536 		}
34537 		DUK_ASSERT(codepoint >= 0x0000L && codepoint <= 0x10ffffL);
34538 
34539 		if (!dec_ctx->bom_handled) {
34540 			dec_ctx->bom_handled = 1;
34541 			if (codepoint == 0xfeffL && !dec_ctx->ignore_bom) {
34542 				continue;
34543 			}
34544 		}
34545 
34546 		out += duk_unicode_encode_cesu8((duk_ucodepoint_t) codepoint, out);
34547 		DUK_ASSERT(out <= output + (3 + (3 * len)));
34548 	}
34549 
34550 	if (!stream) {
34551 		if (dec_ctx->needed != 0) {
34552 			/* truncated sequence at end of buffer */
34553 			if (dec_ctx->fatal) {
34554 				goto fail_type;
34555 			} else {
34556 				out += duk_unicode_encode_cesu8(DUK_UNICODE_CP_REPLACEMENT_CHARACTER, out);
34557 				DUK_ASSERT(out <= output + (3 + (3 * len)));
34558 			}
34559 		}
34560 		duk__utf8_decode_init(dec_ctx);  /* Initialize decoding state for potential reuse. */
34561 	}
34562 
34563 	/* Output buffer is fixed and thus stable even if there had been
34564 	 * side effects (which there shouldn't be).
34565 	 */
34566 	duk_push_lstring(thr, (const char *) output, (duk_size_t) (out - output));
34567 	return 1;
34568 
34569  fail_type:
34570 	DUK_ERROR_TYPE(thr, DUK_STR_UTF8_DECODE_FAILED);
34571 	DUK_WO_NORETURN(return 0;);
34572 }
34573 
34574 /*
34575  *  Built-in bindings
34576  */
34577 
34578 #if defined(DUK_USE_ENCODING_BUILTINS)
duk_bi_textencoder_constructor(duk_hthread * thr)34579 DUK_INTERNAL duk_ret_t duk_bi_textencoder_constructor(duk_hthread *thr) {
34580 	/* TextEncoder currently requires no persistent state, so the constructor
34581 	 * does nothing on purpose.
34582 	 */
34583 
34584 	duk_require_constructor_call(thr);
34585 	return 0;
34586 }
34587 
duk_bi_textencoder_prototype_encoding_getter(duk_hthread * thr)34588 DUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encoding_getter(duk_hthread *thr) {
34589 	duk_push_literal(thr, "utf-8");
34590 	return 1;
34591 }
34592 
duk_bi_textencoder_prototype_encode(duk_hthread * thr)34593 DUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encode(duk_hthread *thr) {
34594 	duk__encode_context enc_ctx;
34595 	duk_size_t len;
34596 	duk_size_t final_len;
34597 	duk_uint8_t *output;
34598 
34599 	DUK_ASSERT_TOP(thr, 1);
34600 	if (duk_is_undefined(thr, 0)) {
34601 		len = 0;
34602 	} else {
34603 		duk_hstring *h_input;
34604 
34605 		h_input = duk_to_hstring(thr, 0);
34606 		DUK_ASSERT(h_input != NULL);
34607 
34608 		len = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_input);
34609 		if (len >= DUK_HBUFFER_MAX_BYTELEN / 3) {
34610 			DUK_ERROR_TYPE(thr, DUK_STR_RESULT_TOO_LONG);
34611 			DUK_WO_NORETURN(return 0;);
34612 		}
34613 	}
34614 
34615 	/* Allowance is 3*len because all bytes can potentially be replaced with
34616 	 * U+FFFD -- which rather inconveniently encodes to 3 bytes in UTF-8.
34617 	 * Rely on dynamic buffer data pointer stability: no other code has
34618 	 * access to the data pointer.
34619 	 *
34620 	 * XXX: The buffer allocation strategy used here is rather inefficient.
34621 	 * Maybe switch to a chunk-based strategy, or preprocess the string to
34622 	 * figure out the space needed ahead of time?
34623 	 */
34624 	DUK_ASSERT(3 * len >= len);
34625 	output = (duk_uint8_t *) duk_push_dynamic_buffer(thr, 3 * len);
34626 
34627 	if (len > 0) {
34628 		DUK_ASSERT(duk_is_string(thr, 0));  /* True if len > 0. */
34629 
34630 		/* XXX: duk_decode_string() is used to process the input
34631 		 * string.  For standard ECMAScript strings, represented
34632 		 * internally as CESU-8, this is fine.  However, behavior
34633 		 * beyond CESU-8 is not very strict: codepoints using an
34634 		 * extended form of UTF-8 are also accepted, and invalid
34635 		 * codepoint sequences (which are allowed in Duktape strings)
34636 		 * are not handled as well as they could (e.g. invalid
34637 		 * continuation bytes may mask following codepoints).
34638 		 * This is how ECMAScript code would also see such strings.
34639 		 * Maybe replace duk_decode_string() with an explicit strict
34640 		 * CESU-8 decoder here?
34641 		 */
34642 		enc_ctx.lead = 0x0000L;
34643 		enc_ctx.out = output;
34644 		duk_decode_string(thr, 0, duk__utf8_encode_char, (void *) &enc_ctx);
34645 		if (enc_ctx.lead != 0x0000L) {
34646 			/* unpaired high surrogate at end of string */
34647 			enc_ctx.out = duk__utf8_emit_repl(enc_ctx.out);
34648 			DUK_ASSERT(enc_ctx.out <= output + (3 * len));
34649 		}
34650 
34651 		/* The output buffer is usually very much oversized, so shrink it to
34652 		 * actually needed size.  Pointer stability assumed up to this point.
34653 		 */
34654 		DUK_ASSERT_TOP(thr, 2);
34655 		DUK_ASSERT(output == (duk_uint8_t *) duk_get_buffer_data(thr, -1, NULL));
34656 
34657 		final_len = (duk_size_t) (enc_ctx.out - output);
34658 		duk_resize_buffer(thr, -1, final_len);
34659 		/* 'output' and 'enc_ctx.out' are potentially invalidated by the resize. */
34660 	} else {
34661 		final_len = 0;
34662 	}
34663 
34664 	/* Standard WHATWG output is a Uint8Array.  Here the Uint8Array will
34665 	 * be backed by a dynamic buffer which differs from e.g. Uint8Arrays
34666 	 * created as 'new Uint8Array(N)'.  ECMAScript code won't see the
34667 	 * difference but C code will.  When bufferobjects are not supported,
34668 	 * returns a plain dynamic buffer.
34669 	 */
34670 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
34671 	duk_push_buffer_object(thr, -1, 0, final_len, DUK_BUFOBJ_UINT8ARRAY);
34672 #endif
34673 	return 1;
34674 }
34675 
duk_bi_textdecoder_constructor(duk_hthread * thr)34676 DUK_INTERNAL duk_ret_t duk_bi_textdecoder_constructor(duk_hthread *thr) {
34677 	duk__decode_context *dec_ctx;
34678 	duk_bool_t fatal = 0;
34679 	duk_bool_t ignore_bom = 0;
34680 
34681 	DUK_ASSERT_TOP(thr, 2);
34682 	duk_require_constructor_call(thr);
34683 	if (!duk_is_undefined(thr, 0)) {
34684 		/* XXX: For now ignore 'label' (encoding identifier). */
34685 		duk_to_string(thr, 0);
34686 	}
34687 	if (!duk_is_null_or_undefined(thr, 1)) {
34688 		if (duk_get_prop_literal(thr, 1, "fatal")) {
34689 			fatal = duk_to_boolean(thr, -1);
34690 		}
34691 		if (duk_get_prop_literal(thr, 1, "ignoreBOM")) {
34692 			ignore_bom = duk_to_boolean(thr, -1);
34693 		}
34694 	}
34695 
34696 	duk_push_this(thr);
34697 
34698 	/* The decode context is not assumed to be zeroed; all fields are
34699 	 * initialized explicitly.
34700 	 */
34701 	dec_ctx = (duk__decode_context *) duk_push_fixed_buffer(thr, sizeof(duk__decode_context));
34702 	dec_ctx->fatal = (duk_uint8_t) fatal;
34703 	dec_ctx->ignore_bom = (duk_uint8_t) ignore_bom;
34704 	duk__utf8_decode_init(dec_ctx);  /* Initializes remaining fields. */
34705 
34706 	duk_put_prop_literal(thr, -2, DUK_INTERNAL_SYMBOL("Context"));
34707 	return 0;
34708 }
34709 
34710 /* Get TextDecoder context from 'this'; leaves garbage on stack. */
duk__get_textdecoder_context(duk_hthread * thr)34711 DUK_LOCAL duk__decode_context *duk__get_textdecoder_context(duk_hthread *thr) {
34712 	duk__decode_context *dec_ctx;
34713 	duk_push_this(thr);
34714 	duk_get_prop_literal(thr, -1, DUK_INTERNAL_SYMBOL("Context"));
34715 	dec_ctx = (duk__decode_context *) duk_require_buffer(thr, -1, NULL);
34716 	DUK_ASSERT(dec_ctx != NULL);
34717 	return dec_ctx;
34718 }
34719 
duk_bi_textdecoder_prototype_shared_getter(duk_hthread * thr)34720 DUK_INTERNAL duk_ret_t duk_bi_textdecoder_prototype_shared_getter(duk_hthread *thr) {
34721 	duk__decode_context *dec_ctx;
34722 	duk_int_t magic;
34723 
34724 	dec_ctx = duk__get_textdecoder_context(thr);
34725 	magic = duk_get_current_magic(thr);
34726 	switch (magic) {
34727 	case 0:
34728 		/* Encoding is now fixed, so _Context lookup is only needed to
34729 		 * validate the 'this' binding (TypeError if not TextDecoder-like).
34730 		 */
34731 		duk_push_literal(thr, "utf-8");
34732 		break;
34733 	case 1:
34734 		duk_push_boolean(thr, dec_ctx->fatal);
34735 		break;
34736 	default:
34737 		duk_push_boolean(thr, dec_ctx->ignore_bom);
34738 		break;
34739 	}
34740 
34741 	return 1;
34742 }
34743 
duk_bi_textdecoder_prototype_decode(duk_hthread * thr)34744 DUK_INTERNAL duk_ret_t duk_bi_textdecoder_prototype_decode(duk_hthread *thr) {
34745 	duk__decode_context *dec_ctx;
34746 
34747 	dec_ctx = duk__get_textdecoder_context(thr);
34748 	return duk__decode_helper(thr, dec_ctx);
34749 }
34750 #endif  /* DUK_USE_ENCODING_BUILTINS */
34751 
34752 /*
34753  *  Internal helper for Node.js Buffer
34754  */
34755 
34756 /* Internal helper used for Node.js Buffer .toString().  Value stack convention
34757  * is currently odd: it mimics TextDecoder .decode() so that argument must be at
34758  * index 0, and decode options (not present for Buffer) at index 1.  Return value
34759  * is a Duktape/C function return value.
34760  */
duk_textdecoder_decode_utf8_nodejs(duk_hthread * thr)34761 DUK_INTERNAL duk_ret_t duk_textdecoder_decode_utf8_nodejs(duk_hthread *thr) {
34762 	duk__decode_context dec_ctx;
34763 
34764 	dec_ctx.fatal = 0;  /* use replacement chars */
34765 	dec_ctx.ignore_bom = 1;  /* ignore BOMs (matches Node.js Buffer .toString()) */
34766 	duk__utf8_decode_init(&dec_ctx);
34767 
34768 	return duk__decode_helper(thr, &dec_ctx);
34769 }
34770 
34771 /* automatic undefs */
34772 #undef DUK__CP_CONTINUE
34773 #undef DUK__CP_ERROR
34774 #undef DUK__CP_RETRY
34775 /*
34776  *  Error built-ins
34777  */
34778 
34779 /* #include duk_internal.h -> already included */
34780 
duk_bi_error_constructor_shared(duk_hthread * thr)34781 DUK_INTERNAL duk_ret_t duk_bi_error_constructor_shared(duk_hthread *thr) {
34782 	/* Behavior for constructor and non-constructor call is
34783 	 * the same except for augmenting the created error.  When
34784 	 * called as a constructor, the caller (duk_new()) will handle
34785 	 * augmentation; when called as normal function, we need to do
34786 	 * it here.
34787 	 */
34788 
34789 	duk_small_int_t bidx_prototype = duk_get_current_magic(thr);
34790 
34791 	/* same for both error and each subclass like TypeError */
34792 	duk_uint_t flags_and_class = DUK_HOBJECT_FLAG_EXTENSIBLE |
34793 	                             DUK_HOBJECT_FLAG_FASTREFS |
34794 	                             DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR);
34795 
34796 	(void) duk_push_object_helper(thr, flags_and_class, bidx_prototype);
34797 
34798 	/* If message is undefined, the own property 'message' is not set at
34799 	 * all to save property space.  An empty message is inherited anyway.
34800 	 */
34801 	if (!duk_is_undefined(thr, 0)) {
34802 		duk_to_string(thr, 0);
34803 		duk_dup_0(thr);  /* [ message error message ] */
34804 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
34805 	}
34806 
34807 	/* Augment the error if called as a normal function.  __FILE__ and __LINE__
34808 	 * are not desirable in this case.
34809 	 */
34810 
34811 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
34812 	if (!duk_is_constructor_call(thr)) {
34813 		duk_err_augment_error_create(thr, thr, NULL, 0, DUK_AUGMENT_FLAG_NOBLAME_FILELINE);
34814 	}
34815 #endif
34816 
34817 	return 1;
34818 }
34819 
duk_bi_error_prototype_to_string(duk_hthread * thr)34820 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_to_string(duk_hthread *thr) {
34821 	/* XXX: optimize with more direct internal access */
34822 
34823 	duk_push_this(thr);
34824 	(void) duk_require_hobject_promote_mask(thr, -1, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
34825 
34826 	/* [ ... this ] */
34827 
34828 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_NAME);
34829 	if (duk_is_undefined(thr, -1)) {
34830 		duk_pop(thr);
34831 		duk_push_literal(thr, "Error");
34832 	} else {
34833 		duk_to_string(thr, -1);
34834 	}
34835 
34836 	/* [ ... this name ] */
34837 
34838 	/* XXX: Are steps 6 and 7 in E5 Section 15.11.4.4 duplicated by
34839 	 * accident or are they actually needed?  The first ToString()
34840 	 * could conceivably return 'undefined'.
34841 	 */
34842 	duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE);
34843 	if (duk_is_undefined(thr, -1)) {
34844 		duk_pop(thr);
34845 		duk_push_hstring_empty(thr);
34846 	} else {
34847 		duk_to_string(thr, -1);
34848 	}
34849 
34850 	/* [ ... this name message ] */
34851 
34852 	if (duk_get_length(thr, -2) == 0) {
34853 		/* name is empty -> return message */
34854 		return 1;
34855 	}
34856 	if (duk_get_length(thr, -1) == 0) {
34857 		/* message is empty -> return name */
34858 		duk_pop(thr);
34859 		return 1;
34860 	}
34861 	duk_push_literal(thr, ": ");
34862 	duk_insert(thr, -2);  /* ... name ': ' message */
34863 	duk_concat(thr, 3);
34864 
34865 	return 1;
34866 }
34867 
34868 #if defined(DUK_USE_TRACEBACKS)
34869 
34870 /*
34871  *  Traceback handling
34872  *
34873  *  The unified helper decodes the traceback and produces various requested
34874  *  outputs.  It should be optimized for size, and may leave garbage on stack,
34875  *  only the topmost return value matters.  For instance, traceback separator
34876  *  and decoded strings are pushed even when looking for filename only.
34877  *
34878  *  NOTE: although _Tracedata is an internal property, user code can currently
34879  *  write to the array (or replace it with something other than an array).
34880  *  The code below must tolerate arbitrary _Tracedata.  It can throw errors
34881  *  etc, but cannot cause a segfault or memory unsafe behavior.
34882  */
34883 
34884 /* constants arbitrary, chosen for small loads */
34885 #define DUK__OUTPUT_TYPE_TRACEBACK   (-1)
34886 #define DUK__OUTPUT_TYPE_FILENAME    0
34887 #define DUK__OUTPUT_TYPE_LINENUMBER  1
34888 
duk__error_getter_helper(duk_hthread * thr,duk_small_int_t output_type)34889 DUK_LOCAL duk_ret_t duk__error_getter_helper(duk_hthread *thr, duk_small_int_t output_type) {
34890 	duk_idx_t idx_td;
34891 	duk_small_int_t i;  /* traceback depth fits into 16 bits */
34892 	duk_small_int_t t;  /* stack type fits into 16 bits */
34893 	duk_small_int_t count_func = 0;  /* traceback depth ensures fits into 16 bits */
34894 	const char *str_tailcall = " tailcall";
34895 	const char *str_strict = " strict";
34896 	const char *str_construct = " construct";
34897 	const char *str_prevyield = " preventsyield";
34898 	const char *str_directeval = " directeval";
34899 	const char *str_empty = "";
34900 
34901 	DUK_ASSERT_TOP(thr, 0);  /* fixed arg count */
34902 
34903 	duk_push_this(thr);
34904 	duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_TRACEDATA);
34905 	idx_td = duk_get_top_index(thr);
34906 
34907 	duk_push_hstring_stridx(thr, DUK_STRIDX_NEWLINE_4SPACE);
34908 	duk_push_this(thr);
34909 
34910 	/* [ ... this tracedata sep this ] */
34911 
34912 	/* XXX: skip null filename? */
34913 
34914 	if (duk_check_type(thr, idx_td, DUK_TYPE_OBJECT)) {
34915 		/* Current tracedata contains 2 entries per callstack entry. */
34916 		for (i = 0; ; i += 2) {
34917 			duk_int_t pc;
34918 			duk_uint_t line;
34919 			duk_uint_t flags;
34920 			duk_double_t d;
34921 			const char *funcname;
34922 			const char *filename;
34923 			duk_hobject *h_func;
34924 			duk_hstring *h_name;
34925 
34926 			duk_require_stack(thr, 5);
34927 			duk_get_prop_index(thr, idx_td, (duk_uarridx_t) i);
34928 			duk_get_prop_index(thr, idx_td, (duk_uarridx_t) (i + 1));
34929 			d = duk_to_number_m1(thr);
34930 			pc = duk_double_to_int_t(DUK_FMOD(d, DUK_DOUBLE_2TO32));
34931 			flags = duk_double_to_uint_t(DUK_FLOOR(d / DUK_DOUBLE_2TO32));
34932 			t = (duk_small_int_t) duk_get_type(thr, -2);
34933 
34934 			if (t == DUK_TYPE_OBJECT || t == DUK_TYPE_LIGHTFUNC) {
34935 				/*
34936 				 *  ECMAScript/native function call or lightfunc call
34937 				 */
34938 
34939 				count_func++;
34940 
34941 				/* [ ... v1(func) v2(pc+flags) ] */
34942 
34943 				/* These may be systematically omitted by Duktape
34944 				 * with certain config options, but allow user to
34945 				 * set them on a case-by-case basis.
34946 				 */
34947 				duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_NAME);
34948 				duk_get_prop_stridx_short(thr, -3, DUK_STRIDX_FILE_NAME);
34949 
34950 #if defined(DUK_USE_PC2LINE)
34951 				line = (duk_uint_t) duk_hobject_pc2line_query(thr, -4, (duk_uint_fast32_t) pc);
34952 #else
34953 				line = 0;
34954 #endif
34955 
34956 				/* [ ... v1 v2 name filename ] */
34957 
34958 				/* When looking for .fileName/.lineNumber, blame first
34959 				 * function which has a .fileName.
34960 				 */
34961 				if (duk_is_string_notsymbol(thr, -1)) {
34962 					if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
34963 						return 1;
34964 					} else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
34965 						duk_push_uint(thr, line);
34966 						return 1;
34967 					}
34968 				}
34969 
34970 				/* XXX: Change 'anon' handling here too, to use empty string for anonymous functions? */
34971 				/* XXX: Could be improved by coercing to a readable duk_tval (especially string escaping) */
34972 				h_name = duk_get_hstring_notsymbol(thr, -2);  /* may be NULL */
34973 				funcname = (h_name == NULL || h_name == DUK_HTHREAD_STRING_EMPTY_STRING(thr)) ?
34974 				           "[anon]" : (const char *) DUK_HSTRING_GET_DATA(h_name);
34975 				filename = duk_get_string_notsymbol(thr, -1);
34976 				filename = filename ? filename : "";
34977 				DUK_ASSERT(funcname != NULL);
34978 				DUK_ASSERT(filename != NULL);
34979 
34980 				h_func = duk_get_hobject(thr, -4);  /* NULL for lightfunc */
34981 
34982 				if (h_func == NULL) {
34983 					duk_push_sprintf(thr, "at %s light%s%s%s%s%s",
34984 					                 (const char *) funcname,
34985 					                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
34986 					                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
34987 					                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
34988 					                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
34989 					                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
34990 				} else if (DUK_HOBJECT_HAS_NATFUNC(h_func)) {
34991 					duk_push_sprintf(thr, "at %s (%s) native%s%s%s%s%s",
34992 					                 (const char *) funcname,
34993 					                 (const char *) filename,
34994 					                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
34995 					                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
34996 					                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
34997 					                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
34998 					                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
34999 				} else {
35000 					duk_push_sprintf(thr, "at %s (%s:%lu)%s%s%s%s%s",
35001 					                 (const char *) funcname,
35002 					                 (const char *) filename,
35003 					                 (unsigned long) line,
35004 					                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
35005 					                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
35006 					                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
35007 					                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
35008 					                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
35009 				}
35010 				duk_replace(thr, -5);   /* [ ... v1 v2 name filename str ] -> [ ... str v2 name filename ] */
35011 				duk_pop_3(thr);         /* -> [ ... str ] */
35012 			} else if (t == DUK_TYPE_STRING) {
35013 				const char *str_file;
35014 
35015 				/*
35016 				 *  __FILE__ / __LINE__ entry, here 'pc' is line number directly.
35017 				 *  Sometimes __FILE__ / __LINE__ is reported as the source for
35018 				 *  the error (fileName, lineNumber), sometimes not.
35019 				 */
35020 
35021 				/* [ ... v1(filename) v2(line+flags) ] */
35022 
35023 				/* When looking for .fileName/.lineNumber, blame compilation
35024 				 * or C call site unless flagged not to do so.
35025 				 */
35026 				if (!(flags & DUK_TB_FLAG_NOBLAME_FILELINE)) {
35027 					if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
35028 						duk_pop(thr);
35029 						return 1;
35030 					} else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
35031 						duk_push_int(thr, pc);
35032 						return 1;
35033 					}
35034 				}
35035 
35036 				/* Tracedata is trusted but avoid any risk of using a NULL
35037 				 * for %s format because it has undefined behavior.  Symbols
35038 				 * don't need to be explicitly rejected as they pose no memory
35039 				 * safety issues.
35040 				 */
35041 				str_file = (const char *) duk_get_string(thr, -2);
35042 				duk_push_sprintf(thr, "at [anon] (%s:%ld) internal",
35043 				                 (const char *) (str_file ? str_file : "null"), (long) pc);
35044 				duk_replace(thr, -3);  /* [ ... v1 v2 str ] -> [ ... str v2 ] */
35045 				duk_pop(thr);          /* -> [ ... str ] */
35046 			} else {
35047 				/* unknown, ignore */
35048 				duk_pop_2(thr);
35049 				break;
35050 			}
35051 		}
35052 
35053 		if (count_func >= DUK_USE_TRACEBACK_DEPTH) {
35054 			/* Possibly truncated; there is no explicit truncation
35055 			 * marker so this is the best we can do.
35056 			 */
35057 
35058 			duk_push_hstring_stridx(thr, DUK_STRIDX_BRACKETED_ELLIPSIS);
35059 		}
35060 	}
35061 
35062 	/* [ ... this tracedata sep this str1 ... strN ] */
35063 
35064 	if (output_type != DUK__OUTPUT_TYPE_TRACEBACK) {
35065 		return 0;
35066 	} else {
35067 		/* The 'this' after 'sep' will get ToString() coerced by
35068 		 * duk_join() automatically.  We don't want to do that
35069 		 * coercion when providing .fileName or .lineNumber (GH-254).
35070 		 */
35071 		duk_join(thr, duk_get_top(thr) - (idx_td + 2) /*count, not including sep*/);
35072 		return 1;
35073 	}
35074 }
35075 
35076 /* XXX: Output type could be encoded into native function 'magic' value to
35077  * save space.  For setters the stridx could be encoded into 'magic'.
35078  */
35079 
duk_bi_error_prototype_stack_getter(duk_hthread * thr)35080 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_getter(duk_hthread *thr) {
35081 	return duk__error_getter_helper(thr, DUK__OUTPUT_TYPE_TRACEBACK);
35082 }
35083 
duk_bi_error_prototype_filename_getter(duk_hthread * thr)35084 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_getter(duk_hthread *thr) {
35085 	return duk__error_getter_helper(thr, DUK__OUTPUT_TYPE_FILENAME);
35086 }
35087 
duk_bi_error_prototype_linenumber_getter(duk_hthread * thr)35088 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_hthread *thr) {
35089 	return duk__error_getter_helper(thr, DUK__OUTPUT_TYPE_LINENUMBER);
35090 }
35091 
35092 #else  /* DUK_USE_TRACEBACKS */
35093 
35094 /*
35095  *  Traceback handling when tracebacks disabled.
35096  *
35097  *  The fileName / lineNumber stubs are now necessary because built-in
35098  *  data will include the accessor properties in Error.prototype.  If those
35099  *  are removed for builds without tracebacks, these can also be removed.
35100  *  'stack' should still be present and produce a ToString() equivalent:
35101  *  this is useful for user code which prints a stacktrace and expects to
35102  *  see something useful.  A normal stacktrace also begins with a ToString()
35103  *  of the error so this makes sense.
35104  */
35105 
duk_bi_error_prototype_stack_getter(duk_hthread * thr)35106 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_getter(duk_hthread *thr) {
35107 	/* XXX: remove this native function and map 'stack' accessor
35108 	 * to the toString() implementation directly.
35109 	 */
35110 	return duk_bi_error_prototype_to_string(thr);
35111 }
35112 
duk_bi_error_prototype_filename_getter(duk_hthread * thr)35113 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_getter(duk_hthread *thr) {
35114 	DUK_UNREF(thr);
35115 	return 0;
35116 }
35117 
duk_bi_error_prototype_linenumber_getter(duk_hthread * thr)35118 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_hthread *thr) {
35119 	DUK_UNREF(thr);
35120 	return 0;
35121 }
35122 
35123 #endif  /* DUK_USE_TRACEBACKS */
35124 
duk__error_setter_helper(duk_hthread * thr,duk_small_uint_t stridx_key)35125 DUK_LOCAL duk_ret_t duk__error_setter_helper(duk_hthread *thr, duk_small_uint_t stridx_key) {
35126 	/* Attempt to write 'stack', 'fileName', 'lineNumber' works as if
35127 	 * user code called Object.defineProperty() to create an overriding
35128 	 * own property.  This allows user code to overwrite .fileName etc
35129 	 * intuitively as e.g. "err.fileName = 'dummy'" as one might expect.
35130 	 * See https://github.com/svaarala/duktape/issues/387.
35131 	 */
35132 
35133 	DUK_ASSERT_TOP(thr, 1);  /* fixed arg count: value */
35134 
35135 	duk_push_this(thr);
35136 	duk_push_hstring_stridx(thr, stridx_key);
35137 	duk_dup_0(thr);
35138 
35139 	/* [ ... obj key value ] */
35140 
35141 	DUK_DD(DUK_DDPRINT("error setter: %!T %!T %!T",
35142 	                   duk_get_tval(thr, -3), duk_get_tval(thr, -2), duk_get_tval(thr, -1)));
35143 
35144 	duk_def_prop(thr, -3, DUK_DEFPROP_HAVE_VALUE |
35145 	                      DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE |
35146 	                      DUK_DEFPROP_HAVE_ENUMERABLE | /*not enumerable*/
35147 	                      DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE);
35148 	return 0;
35149 }
35150 
duk_bi_error_prototype_stack_setter(duk_hthread * thr)35151 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_setter(duk_hthread *thr) {
35152 	return duk__error_setter_helper(thr, DUK_STRIDX_STACK);
35153 }
35154 
duk_bi_error_prototype_filename_setter(duk_hthread * thr)35155 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_setter(duk_hthread *thr) {
35156 	return duk__error_setter_helper(thr, DUK_STRIDX_FILE_NAME);
35157 }
35158 
duk_bi_error_prototype_linenumber_setter(duk_hthread * thr)35159 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_setter(duk_hthread *thr) {
35160 	return duk__error_setter_helper(thr, DUK_STRIDX_LINE_NUMBER);
35161 }
35162 
35163 /* automatic undefs */
35164 #undef DUK__OUTPUT_TYPE_FILENAME
35165 #undef DUK__OUTPUT_TYPE_LINENUMBER
35166 #undef DUK__OUTPUT_TYPE_TRACEBACK
35167 /*
35168  *  Function built-ins
35169  */
35170 
35171 /* #include duk_internal.h -> already included */
35172 
35173 /* Needed even when Function built-in is disabled. */
duk_bi_function_prototype(duk_hthread * thr)35174 DUK_INTERNAL duk_ret_t duk_bi_function_prototype(duk_hthread *thr) {
35175 	/* ignore arguments, return undefined (E5 Section 15.3.4) */
35176 	DUK_UNREF(thr);
35177 	return 0;
35178 }
35179 
35180 #if defined(DUK_USE_FUNCTION_BUILTIN)
duk_bi_function_constructor(duk_hthread * thr)35181 DUK_INTERNAL duk_ret_t duk_bi_function_constructor(duk_hthread *thr) {
35182 	duk_hstring *h_sourcecode;
35183 	duk_idx_t nargs;
35184 	duk_idx_t i;
35185 	duk_small_uint_t comp_flags;
35186 	duk_hcompfunc *func;
35187 	duk_hobject *outer_lex_env;
35188 	duk_hobject *outer_var_env;
35189 
35190 	/* normal and constructor calls have identical semantics */
35191 
35192 	nargs = duk_get_top(thr);
35193 	for (i = 0; i < nargs; i++) {
35194 		duk_to_string(thr, i);  /* Rejects Symbols during coercion. */
35195 	}
35196 
35197 	if (nargs == 0) {
35198 		duk_push_hstring_empty(thr);
35199 		duk_push_hstring_empty(thr);
35200 	} else if (nargs == 1) {
35201 		/* XXX: cover this with the generic >1 case? */
35202 		duk_push_hstring_empty(thr);
35203 	} else {
35204 		duk_insert(thr, 0);   /* [ arg1 ... argN-1 body] -> [body arg1 ... argN-1] */
35205 		duk_push_literal(thr, ",");
35206 		duk_insert(thr, 1);
35207 		duk_join(thr, nargs - 1);
35208 	}
35209 
35210 	/* [ body formals ], formals is comma separated list that needs to be parsed */
35211 
35212 	DUK_ASSERT_TOP(thr, 2);
35213 
35214 	/* XXX: this placeholder is not always correct, but use for now.
35215 	 * It will fail in corner cases; see test-dev-func-cons-args.js.
35216 	 */
35217 	duk_push_literal(thr, "function(");
35218 	duk_dup_1(thr);
35219 	duk_push_literal(thr, "){");
35220 	duk_dup_0(thr);
35221 	duk_push_literal(thr, "\n}");  /* Newline is important to handle trailing // comment. */
35222 	duk_concat(thr, 5);
35223 
35224 	/* [ body formals source ] */
35225 
35226 	DUK_ASSERT_TOP(thr, 3);
35227 
35228 	/* strictness is not inherited, intentional */
35229 	comp_flags = DUK_COMPILE_FUNCEXPR;
35230 
35231 	duk_push_hstring_stridx(thr, DUK_STRIDX_COMPILE);  /* XXX: copy from caller? */  /* XXX: ignored now */
35232 	h_sourcecode = duk_require_hstring(thr, -2);  /* no symbol check needed; -2 is concat'd code */
35233 	duk_js_compile(thr,
35234 	               (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode),
35235 	               (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode),
35236 	               comp_flags);
35237 
35238 	/* Force .name to 'anonymous' (ES2015). */
35239 	duk_push_literal(thr, "anonymous");
35240 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
35241 
35242 	func = (duk_hcompfunc *) duk_known_hobject(thr, -1);
35243 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) func));
35244 	DUK_ASSERT(DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) func));
35245 
35246 	/* [ body formals source template ] */
35247 
35248 	/* only outer_lex_env matters, as functions always get a new
35249 	 * variable declaration environment.
35250 	 */
35251 
35252 	outer_lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
35253 	outer_var_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
35254 
35255 	duk_js_push_closure(thr, func, outer_var_env, outer_lex_env, 1 /*add_auto_proto*/);
35256 
35257 	/* [ body formals source template closure ] */
35258 
35259 	return 1;
35260 }
35261 #endif  /* DUK_USE_FUNCTION_BUILTIN */
35262 
35263 #if defined(DUK_USE_FUNCTION_BUILTIN)
duk_bi_function_prototype_to_string(duk_hthread * thr)35264 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_to_string(duk_hthread *thr) {
35265 	duk_tval *tv;
35266 
35267 	/*
35268 	 *  E5 Section 15.3.4.2 places few requirements on the output of
35269 	 *  this function: the result is implementation dependent, must
35270 	 *  follow FunctionDeclaration syntax (in particular, must have a
35271 	 *  name even for anonymous functions or functions with empty name).
35272 	 *  The output does NOT need to compile into anything useful.
35273 	 *
35274 	 *  E6 Section 19.2.3.5 changes the requirements completely: the
35275 	 *  result must either eval() to a functionally equivalent object
35276 	 *  OR eval() to a SyntaxError.
35277 	 *
35278 	 *  We opt for the SyntaxError approach for now, with a syntax that
35279 	 *  mimics V8's native function syntax:
35280 	 *
35281 	 *      'function cos() { [native code] }'
35282 	 *
35283 	 *  but extended with [ecmascript code], [bound code], and
35284 	 *  [lightfunc code].
35285 	 */
35286 
35287 	duk_push_this(thr);
35288 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
35289 	DUK_ASSERT(tv != NULL);
35290 
35291 	if (DUK_TVAL_IS_OBJECT(tv)) {
35292 		duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv);
35293 		const char *func_name;
35294 
35295 		/* Function name: missing/undefined is mapped to empty string,
35296 		 * otherwise coerce to string.  No handling for invalid identifier
35297 		 * characters or e.g. '{' in the function name.  This doesn't
35298 		 * really matter as long as a SyntaxError results.  Technically
35299 		 * if the name contained a suitable prefix followed by '//' it
35300 		 * might cause the result to parse without error.
35301 		 */
35302 		duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_NAME);
35303 		if (duk_is_undefined(thr, -1)) {
35304 			func_name = "";
35305 		} else {
35306 			func_name = duk_to_string(thr, -1);
35307 			DUK_ASSERT(func_name != NULL);
35308 		}
35309 
35310 		if (DUK_HOBJECT_IS_COMPFUNC(obj)) {
35311 			duk_push_sprintf(thr, "function %s() { [ecmascript code] }", (const char *) func_name);
35312 		} else if (DUK_HOBJECT_IS_NATFUNC(obj)) {
35313 			duk_push_sprintf(thr, "function %s() { [native code] }", (const char *) func_name);
35314 		} else if (DUK_HOBJECT_IS_BOUNDFUNC(obj)) {
35315 			duk_push_sprintf(thr, "function %s() { [bound code] }", (const char *) func_name);
35316 		} else {
35317 			goto type_error;
35318 		}
35319 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
35320 		duk_push_lightfunc_tostring(thr, tv);
35321 	} else {
35322 		goto type_error;
35323 	}
35324 
35325 	return 1;
35326 
35327  type_error:
35328 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
35329 }
35330 #endif
35331 
35332 /* Always present because the native function pointer is needed in call
35333  * handling.
35334  */
duk_bi_function_prototype_call(duk_hthread * thr)35335 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_call(duk_hthread *thr) {
35336 	/* .call() is dealt with in call handling by simulating its
35337 	 * effects so this function is actually never called.
35338 	 */
35339 	DUK_UNREF(thr);
35340 	return DUK_RET_TYPE_ERROR;
35341 }
35342 
duk_bi_function_prototype_apply(duk_hthread * thr)35343 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_apply(duk_hthread *thr) {
35344 	/* Like .call(), never actually called. */
35345 	DUK_UNREF(thr);
35346 	return DUK_RET_TYPE_ERROR;
35347 }
35348 
duk_bi_reflect_apply(duk_hthread * thr)35349 DUK_INTERNAL duk_ret_t duk_bi_reflect_apply(duk_hthread *thr) {
35350 	/* Like .call(), never actually called. */
35351 	DUK_UNREF(thr);
35352 	return DUK_RET_TYPE_ERROR;
35353 }
35354 
duk_bi_reflect_construct(duk_hthread * thr)35355 DUK_INTERNAL duk_ret_t duk_bi_reflect_construct(duk_hthread *thr) {
35356 	/* Like .call(), never actually called. */
35357 	DUK_UNREF(thr);
35358 	return DUK_RET_TYPE_ERROR;
35359 }
35360 
35361 #if defined(DUK_USE_FUNCTION_BUILTIN)
35362 /* Create a bound function which points to a target function which may
35363  * be bound or non-bound.  If the target is bound, the argument lists
35364  * and 'this' binding of the functions are merged and the resulting
35365  * function points directly to the non-bound target.
35366  */
duk_bi_function_prototype_bind(duk_hthread * thr)35367 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_bind(duk_hthread *thr) {
35368 	duk_hboundfunc *h_bound;
35369 	duk_idx_t nargs;  /* bound args, not counting 'this' binding */
35370 	duk_idx_t bound_nargs;
35371 	duk_int_t bound_len;
35372 	duk_tval *tv_prevbound;
35373 	duk_idx_t n_prevbound;
35374 	duk_tval *tv_res;
35375 	duk_tval *tv_tmp;
35376 
35377 	/* XXX: C API call, e.g. duk_push_bound_function(thr, target_idx, nargs); */
35378 
35379 	/* Vararg function, careful arg handling, e.g. thisArg may not
35380 	 * be present.
35381 	 */
35382 	nargs = duk_get_top(thr) - 1;  /* actual args, not counting 'this' binding */
35383 	if (nargs < 0) {
35384 		nargs++;
35385 		duk_push_undefined(thr);
35386 	}
35387 	DUK_ASSERT(nargs >= 0);
35388 
35389 	/* Limit 'nargs' for bound functions to guarantee arithmetic
35390 	 * below will never wrap.
35391 	 */
35392 	if (nargs > (duk_idx_t) DUK_HBOUNDFUNC_MAX_ARGS) {
35393 		DUK_DCERROR_RANGE_INVALID_COUNT(thr);
35394 	}
35395 
35396 	duk_push_this(thr);
35397 	duk_require_callable(thr, -1);
35398 
35399 	/* [ thisArg arg1 ... argN func ]  (thisArg+args == nargs+1 total) */
35400 	DUK_ASSERT_TOP(thr, nargs + 2);
35401 
35402 	/* Create bound function object. */
35403 	h_bound = duk_push_hboundfunc(thr);
35404 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&h_bound->target));
35405 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&h_bound->this_binding));
35406 	DUK_ASSERT(h_bound->args == NULL);
35407 	DUK_ASSERT(h_bound->nargs == 0);
35408 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_bound) == NULL);
35409 
35410 	/* [ thisArg arg1 ... argN func boundFunc ] */
35411 
35412 	/* If the target is a bound function, argument lists must be
35413 	 * merged.  The 'this' binding closest to the target function
35414 	 * wins because in call handling the 'this' gets replaced over
35415 	 * and over again until we call the non-bound function.
35416 	 */
35417 	tv_prevbound = NULL;
35418 	n_prevbound = 0;
35419 	tv_tmp = DUK_GET_TVAL_POSIDX(thr, 0);
35420 	DUK_TVAL_SET_TVAL(&h_bound->this_binding, tv_tmp);
35421 	tv_tmp = DUK_GET_TVAL_NEGIDX(thr, -2);
35422 	DUK_TVAL_SET_TVAL(&h_bound->target, tv_tmp);
35423 
35424 	if (DUK_TVAL_IS_OBJECT(tv_tmp)) {
35425 		duk_hobject *h_target;
35426 		duk_hobject *bound_proto;
35427 
35428 		h_target = DUK_TVAL_GET_OBJECT(tv_tmp);
35429 		DUK_ASSERT(DUK_HOBJECT_IS_CALLABLE(h_target));
35430 
35431 		/* Internal prototype must be copied from the target.
35432 		 * For lightfuncs Function.prototype is used and is already
35433 		 * in place.
35434 		 */
35435 		bound_proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_target);
35436 		DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) h_bound, bound_proto);
35437 
35438 		/* The 'strict' flag is copied to get the special [[Get]] of E5.1
35439 		 * Section 15.3.5.4 to apply when a 'caller' value is a strict bound
35440 		 * function.  Not sure if this is correct, because the specification
35441 		 * is a bit ambiguous on this point but it would make sense.
35442 		 */
35443 		/* Strictness is inherited from target. */
35444 		if (DUK_HOBJECT_HAS_STRICT(h_target)) {
35445 			DUK_HOBJECT_SET_STRICT((duk_hobject *) h_bound);
35446 		}
35447 
35448 		if (DUK_HOBJECT_HAS_BOUNDFUNC(h_target)) {
35449 			duk_hboundfunc *h_boundtarget;
35450 
35451 			h_boundtarget = (duk_hboundfunc *) (void *) h_target;
35452 
35453 			/* The final function should always be non-bound, unless
35454 			 * there's a bug in the internals.  Assert for it.
35455 			 */
35456 			DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(&h_boundtarget->target) ||
35457 			           (DUK_TVAL_IS_OBJECT(&h_boundtarget->target) &&
35458 			            DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(&h_boundtarget->target)) &&
35459 			            !DUK_HOBJECT_IS_BOUNDFUNC(DUK_TVAL_GET_OBJECT(&h_boundtarget->target))));
35460 
35461 			DUK_TVAL_SET_TVAL(&h_bound->target, &h_boundtarget->target);
35462 			DUK_TVAL_SET_TVAL(&h_bound->this_binding, &h_boundtarget->this_binding);
35463 
35464 			tv_prevbound = h_boundtarget->args;
35465 			n_prevbound = h_boundtarget->nargs;
35466 		}
35467 	} else {
35468 		/* Lightfuncs are always strict. */
35469 		duk_hobject *bound_proto;
35470 
35471 		DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_tmp));
35472 		DUK_HOBJECT_SET_STRICT((duk_hobject *) h_bound);
35473 		bound_proto = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
35474 		DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) h_bound, bound_proto);
35475 	}
35476 
35477 	DUK_TVAL_INCREF(thr, &h_bound->target);  /* old values undefined, no decref needed */
35478 	DUK_TVAL_INCREF(thr, &h_bound->this_binding);
35479 
35480 	bound_nargs = n_prevbound + nargs;
35481 	if (bound_nargs > (duk_idx_t) DUK_HBOUNDFUNC_MAX_ARGS) {
35482 		DUK_DCERROR_RANGE_INVALID_COUNT(thr);
35483 	}
35484 	tv_res = (duk_tval *) DUK_ALLOC_CHECKED(thr, ((duk_size_t) bound_nargs) * sizeof(duk_tval));
35485 	DUK_ASSERT(tv_res != NULL || bound_nargs == 0);
35486 	DUK_ASSERT(h_bound->args == NULL);
35487 	DUK_ASSERT(h_bound->nargs == 0);
35488 	h_bound->args = tv_res;
35489 	h_bound->nargs = bound_nargs;
35490 
35491 	DUK_ASSERT(n_prevbound >= 0);
35492 	duk_copy_tvals_incref(thr, tv_res, tv_prevbound, (duk_size_t) n_prevbound);
35493 	DUK_ASSERT(nargs >= 0);
35494 	duk_copy_tvals_incref(thr, tv_res + n_prevbound, DUK_GET_TVAL_POSIDX(thr, 1), (duk_size_t) nargs);
35495 
35496 	/* [ thisArg arg1 ... argN func boundFunc ] */
35497 
35498 	/* Bound function 'length' property is interesting.
35499 	 * For lightfuncs, simply read the virtual property.
35500 	 */
35501 	duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH);
35502 	bound_len = duk_get_int(thr, -1);  /* ES2015: no coercion */
35503 	if (bound_len < nargs) {
35504 		bound_len = 0;
35505 	} else {
35506 		bound_len -= nargs;
35507 	}
35508 	if (sizeof(duk_int_t) > 4 && bound_len > (duk_int_t) DUK_UINT32_MAX) {
35509 		bound_len = (duk_int_t) DUK_UINT32_MAX;
35510 	}
35511 	duk_pop(thr);
35512 	DUK_ASSERT(bound_len >= 0);
35513 	tv_tmp = thr->valstack_top++;
35514 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv_tmp));
35515 	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv_tmp));
35516 	DUK_TVAL_SET_U32(tv_tmp, (duk_uint32_t) bound_len);  /* in-place update, fastint */
35517 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);  /* attrs in E6 Section 9.2.4 */
35518 
35519 	/* XXX: could these be virtual? */
35520 	/* Caller and arguments must use the same thrower, [[ThrowTypeError]]. */
35521 	duk_xdef_prop_stridx_thrower(thr, -1, DUK_STRIDX_CALLER);
35522 	duk_xdef_prop_stridx_thrower(thr, -1, DUK_STRIDX_LC_ARGUMENTS);
35523 
35524 	/* Function name and fileName (non-standard). */
35525 	duk_push_literal(thr, "bound ");  /* ES2015 19.2.3.2. */
35526 	duk_get_prop_stridx(thr, -3, DUK_STRIDX_NAME);
35527 	if (!duk_is_string_notsymbol(thr, -1)) {
35528 		/* ES2015 has requirement to check that .name of target is a string
35529 		 * (also must check for Symbol); if not, targetName should be the
35530 		 * empty string.  ES2015 19.2.3.2.
35531 		 */
35532 		duk_pop(thr);
35533 		duk_push_hstring_empty(thr);
35534 	}
35535 	duk_concat(thr, 2);
35536 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
35537 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
35538 	duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME);
35539 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_C);
35540 #endif
35541 
35542 	DUK_DDD(DUK_DDDPRINT("created bound function: %!iT", (duk_tval *) duk_get_tval(thr, -1)));
35543 
35544 	return 1;
35545 }
35546 #endif  /* DUK_USE_FUNCTION_BUILTIN */
35547 
35548 /* %NativeFunctionPrototype% .length getter. */
duk_bi_native_function_length(duk_hthread * thr)35549 DUK_INTERNAL duk_ret_t duk_bi_native_function_length(duk_hthread *thr) {
35550 	duk_tval *tv;
35551 	duk_hnatfunc *h;
35552 	duk_int16_t func_nargs;
35553 
35554 	tv = duk_get_borrowed_this_tval(thr);
35555 	DUK_ASSERT(tv != NULL);
35556 
35557 	if (DUK_TVAL_IS_OBJECT(tv)) {
35558 		h = (duk_hnatfunc *) DUK_TVAL_GET_OBJECT(tv);
35559 		DUK_ASSERT(h != NULL);
35560 		if (!DUK_HOBJECT_IS_NATFUNC((duk_hobject *) h)) {
35561 			goto fail_type;
35562 		}
35563 		func_nargs = h->nargs;
35564 		duk_push_int(thr, func_nargs == DUK_HNATFUNC_NARGS_VARARGS ? 0 : func_nargs);
35565 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
35566 		duk_small_uint_t lf_flags;
35567 		duk_small_uint_t lf_len;
35568 
35569 		lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
35570 		lf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
35571 		duk_push_uint(thr, lf_len);
35572 	} else {
35573 		goto fail_type;
35574 	}
35575 	return 1;
35576 
35577  fail_type:
35578 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
35579 }
35580 
35581 /* %NativeFunctionPrototype% .name getter. */
duk_bi_native_function_name(duk_hthread * thr)35582 DUK_INTERNAL duk_ret_t duk_bi_native_function_name(duk_hthread *thr) {
35583 	duk_tval *tv;
35584 	duk_hnatfunc *h;
35585 
35586 	tv = duk_get_borrowed_this_tval(thr);
35587 	DUK_ASSERT(tv != NULL);
35588 
35589 	if (DUK_TVAL_IS_OBJECT(tv)) {
35590 		h = (duk_hnatfunc *) DUK_TVAL_GET_OBJECT(tv);
35591 		DUK_ASSERT(h != NULL);
35592 		if (!DUK_HOBJECT_IS_NATFUNC((duk_hobject *) h)) {
35593 			goto fail_type;
35594 		}
35595 #if 0
35596 		duk_push_hnatfunc_name(thr, h);
35597 #endif
35598 		duk_push_hstring_empty(thr);
35599 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
35600 		duk_push_lightfunc_name(thr, tv);
35601 	} else {
35602 		goto fail_type;
35603 	}
35604 	return 1;
35605 
35606  fail_type:
35607 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
35608 }
35609 
35610 #if defined(DUK_USE_SYMBOL_BUILTIN)
duk_bi_function_prototype_hasinstance(duk_hthread * thr)35611 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_hasinstance(duk_hthread *thr) {
35612 	/* This binding: RHS, stack index 0: LHS. */
35613 	duk_bool_t ret;
35614 
35615 	ret = duk_js_instanceof_ordinary(thr, DUK_GET_TVAL_POSIDX(thr, 0), DUK_GET_THIS_TVAL_PTR(thr));
35616 	duk_push_boolean(thr, ret);
35617 	return 1;
35618 }
35619 #endif  /* DUK_USE_SYMBOL_BUILTIN */
35620 /*
35621  *  Global object built-ins
35622  */
35623 
35624 /* #include duk_internal.h -> already included */
35625 
35626 /*
35627  *  Encoding/decoding helpers
35628  */
35629 
35630 /* XXX: Could add fast path (for each transform callback) with direct byte
35631  * lookups (no shifting) and no explicit check for x < 0x80 before table
35632  * lookup.
35633  */
35634 
35635 /* Macros for creating and checking bitmasks for character encoding.
35636  * Bit number is a bit counterintuitive, but minimizes code size.
35637  */
35638 #define DUK__MKBITS(a,b,c,d,e,f,g,h)  ((duk_uint8_t) ( \
35639 	((a) << 0) | ((b) << 1) | ((c) << 2) | ((d) << 3) | \
35640 	((e) << 4) | ((f) << 5) | ((g) << 6) | ((h) << 7) \
35641 	))
35642 #define DUK__CHECK_BITMASK(table,cp)  ((table)[(cp) >> 3] & (1 << ((cp) & 0x07)))
35643 
35644 /* E5.1 Section 15.1.3.3: uriReserved + uriUnescaped + '#' */
35645 DUK_LOCAL const duk_uint8_t duk__encode_uriunescaped_table[16] = {
35646 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
35647 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
35648 	DUK__MKBITS(0, 1, 0, 1, 1, 0, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x20-0x2f */
35649 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 0, 1, 0, 1),  /* 0x30-0x3f */
35650 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x40-0x4f */
35651 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1),  /* 0x50-0x5f */
35652 	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x60-0x6f */
35653 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0),  /* 0x70-0x7f */
35654 };
35655 
35656 /* E5.1 Section 15.1.3.4: uriUnescaped */
35657 DUK_LOCAL const duk_uint8_t duk__encode_uricomponent_unescaped_table[16] = {
35658 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
35659 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
35660 	DUK__MKBITS(0, 1, 0, 0, 0, 0, 0, 1), DUK__MKBITS(1, 1, 1, 0, 0, 1, 1, 0),  /* 0x20-0x2f */
35661 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0),  /* 0x30-0x3f */
35662 	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x40-0x4f */
35663 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1),  /* 0x50-0x5f */
35664 	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x60-0x6f */
35665 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0),  /* 0x70-0x7f */
35666 };
35667 
35668 /* E5.1 Section 15.1.3.1: uriReserved + '#' */
35669 DUK_LOCAL const duk_uint8_t duk__decode_uri_reserved_table[16] = {
35670 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
35671 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
35672 	DUK__MKBITS(0, 0, 0, 1, 1, 0, 1, 0), DUK__MKBITS(0, 0, 0, 1, 1, 0, 0, 1),  /* 0x20-0x2f */
35673 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 0, 1),  /* 0x30-0x3f */
35674 	DUK__MKBITS(1, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x40-0x4f */
35675 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x50-0x5f */
35676 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x60-0x6f */
35677 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x70-0x7f */
35678 };
35679 
35680 /* E5.1 Section 15.1.3.2: empty */
35681 DUK_LOCAL const duk_uint8_t duk__decode_uri_component_reserved_table[16] = {
35682 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
35683 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
35684 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x20-0x2f */
35685 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x30-0x3f */
35686 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x40-0x4f */
35687 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x50-0x5f */
35688 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x60-0x6f */
35689 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x70-0x7f */
35690 };
35691 
35692 #if defined(DUK_USE_SECTION_B)
35693 /* E5.1 Section B.2.2, step 7. */
35694 DUK_LOCAL const duk_uint8_t duk__escape_unescaped_table[16] = {
35695 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
35696 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
35697 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 1, 1),  /* 0x20-0x2f */
35698 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0),  /* 0x30-0x3f */
35699 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x40-0x4f */
35700 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1),  /* 0x50-0x5f */
35701 	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x60-0x6f */
35702 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 0)   /* 0x70-0x7f */
35703 };
35704 #endif  /* DUK_USE_SECTION_B */
35705 
35706 typedef struct {
35707 	duk_hthread *thr;
35708 	duk_hstring *h_str;
35709 	duk_bufwriter_ctx bw;
35710 	const duk_uint8_t *p;
35711 	const duk_uint8_t *p_start;
35712 	const duk_uint8_t *p_end;
35713 } duk__transform_context;
35714 
35715 typedef void (*duk__transform_callback)(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp);
35716 
35717 /* XXX: refactor and share with other code */
duk__decode_hex_escape(const duk_uint8_t * p,duk_small_int_t n)35718 DUK_LOCAL duk_small_int_t duk__decode_hex_escape(const duk_uint8_t *p, duk_small_int_t n) {
35719 	duk_small_int_t ch;
35720 	duk_small_int_t t = 0;
35721 
35722 	while (n > 0) {
35723 		t = t * 16;
35724 		ch = (duk_small_int_t) duk_hex_dectab[*p++];
35725 		if (DUK_LIKELY(ch >= 0)) {
35726 			t += ch;
35727 		} else {
35728 			return -1;
35729 		}
35730 		n--;
35731 	}
35732 	return t;
35733 }
35734 
duk__transform_helper(duk_hthread * thr,duk__transform_callback callback,const void * udata)35735 DUK_LOCAL int duk__transform_helper(duk_hthread *thr, duk__transform_callback callback, const void *udata) {
35736 	duk__transform_context tfm_ctx_alloc;
35737 	duk__transform_context *tfm_ctx = &tfm_ctx_alloc;
35738 	duk_codepoint_t cp;
35739 
35740 	tfm_ctx->thr = thr;
35741 
35742 	tfm_ctx->h_str = duk_to_hstring(thr, 0);
35743 	DUK_ASSERT(tfm_ctx->h_str != NULL);
35744 
35745 	DUK_BW_INIT_PUSHBUF(thr, &tfm_ctx->bw, DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str));  /* initial size guess */
35746 
35747 	tfm_ctx->p_start = DUK_HSTRING_GET_DATA(tfm_ctx->h_str);
35748 	tfm_ctx->p_end = tfm_ctx->p_start + DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str);
35749 	tfm_ctx->p = tfm_ctx->p_start;
35750 
35751 	while (tfm_ctx->p < tfm_ctx->p_end) {
35752 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &tfm_ctx->p, tfm_ctx->p_start, tfm_ctx->p_end);
35753 		callback(tfm_ctx, udata, cp);
35754 	}
35755 
35756 	DUK_BW_COMPACT(thr, &tfm_ctx->bw);
35757 
35758 	(void) duk_buffer_to_string(thr, -1);  /* Safe if transform is safe. */
35759 	return 1;
35760 }
35761 
duk__transform_callback_encode_uri(duk__transform_context * tfm_ctx,const void * udata,duk_codepoint_t cp)35762 DUK_LOCAL void duk__transform_callback_encode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
35763 	duk_uint8_t xutf8_buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
35764 	duk_small_int_t len;
35765 	duk_codepoint_t cp1, cp2;
35766 	duk_small_int_t i, t;
35767 	const duk_uint8_t *unescaped_table = (const duk_uint8_t *) udata;
35768 
35769 	/* UTF-8 encoded bytes escaped as %xx%xx%xx... -> 3 * nbytes.
35770 	 * Codepoint range is restricted so this is a slightly too large
35771 	 * but doesn't matter.
35772 	 */
35773 	DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 3 * DUK_UNICODE_MAX_XUTF8_LENGTH);
35774 
35775 	if (cp < 0) {
35776 		goto uri_error;
35777 	} else if ((cp < 0x80L) && DUK__CHECK_BITMASK(unescaped_table, cp)) {
35778 		DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp);
35779 		return;
35780 	} else if (cp >= 0xdc00L && cp <= 0xdfffL) {
35781 		goto uri_error;
35782 	} else if (cp >= 0xd800L && cp <= 0xdbffL) {
35783 		/* Needs lookahead */
35784 		if (duk_unicode_decode_xutf8(tfm_ctx->thr, &tfm_ctx->p, tfm_ctx->p_start, tfm_ctx->p_end, (duk_ucodepoint_t *) &cp2) == 0) {
35785 			goto uri_error;
35786 		}
35787 		if (!(cp2 >= 0xdc00L && cp2 <= 0xdfffL)) {
35788 			goto uri_error;
35789 		}
35790 		cp1 = cp;
35791 		cp = (duk_codepoint_t) (((cp1 - 0xd800L) << 10) + (cp2 - 0xdc00L) + 0x10000L);
35792 	} else if (cp > 0x10ffffL) {
35793 		/* Although we can allow non-BMP characters (they'll decode
35794 		 * back into surrogate pairs), we don't allow extended UTF-8
35795 		 * characters; they would encode to URIs which won't decode
35796 		 * back because of strict UTF-8 checks in URI decoding.
35797 		 * (However, we could just as well allow them here.)
35798 		 */
35799 		goto uri_error;
35800 	} else {
35801 		/* Non-BMP characters within valid UTF-8 range: encode as is.
35802 		 * They'll decode back into surrogate pairs if the escaped
35803 		 * output is decoded.
35804 		 */
35805 		;
35806 	}
35807 
35808 	len = duk_unicode_encode_xutf8((duk_ucodepoint_t) cp, xutf8_buf);
35809 	for (i = 0; i < len; i++) {
35810 		t = (duk_small_int_t) xutf8_buf[i];
35811 		DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
35812 		                      &tfm_ctx->bw,
35813 		                      DUK_ASC_PERCENT,
35814 		                      (duk_uint8_t) duk_uc_nybbles[t >> 4],
35815                                       (duk_uint8_t) duk_uc_nybbles[t & 0x0f]);
35816 	}
35817 
35818 	return;
35819 
35820  uri_error:
35821 	DUK_ERROR_URI(tfm_ctx->thr, DUK_STR_INVALID_INPUT);
35822 	DUK_WO_NORETURN(return;);
35823 }
35824 
duk__transform_callback_decode_uri(duk__transform_context * tfm_ctx,const void * udata,duk_codepoint_t cp)35825 DUK_LOCAL void duk__transform_callback_decode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
35826 	const duk_uint8_t *reserved_table = (const duk_uint8_t *) udata;
35827 	duk_small_uint_t utf8_blen;
35828 	duk_codepoint_t min_cp;
35829 	duk_small_int_t t;  /* must be signed */
35830 	duk_small_uint_t i;
35831 
35832 	/* Maximum write size: XUTF8 path writes max DUK_UNICODE_MAX_XUTF8_LENGTH,
35833 	 * percent escape path writes max two times CESU-8 encoded BMP length.
35834 	 */
35835 	DUK_BW_ENSURE(tfm_ctx->thr,
35836 	              &tfm_ctx->bw,
35837 	              (DUK_UNICODE_MAX_XUTF8_LENGTH >= 2 * DUK_UNICODE_MAX_CESU8_BMP_LENGTH ?
35838 	              DUK_UNICODE_MAX_XUTF8_LENGTH : DUK_UNICODE_MAX_CESU8_BMP_LENGTH));
35839 
35840 	if (cp == (duk_codepoint_t) '%') {
35841 		const duk_uint8_t *p = tfm_ctx->p;
35842 		duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p);  /* bytes left */
35843 
35844 		DUK_DDD(DUK_DDDPRINT("percent encoding, left=%ld", (long) left));
35845 
35846 		if (left < 2) {
35847 			goto uri_error;
35848 		}
35849 
35850 		t = duk__decode_hex_escape(p, 2);
35851 		DUK_DDD(DUK_DDDPRINT("first byte: %ld", (long) t));
35852 		if (t < 0) {
35853 			goto uri_error;
35854 		}
35855 
35856 		if (t < 0x80) {
35857 			if (DUK__CHECK_BITMASK(reserved_table, t)) {
35858 				/* decode '%xx' to '%xx' if decoded char in reserved set */
35859 				DUK_ASSERT(tfm_ctx->p - 1 >= tfm_ctx->p_start);
35860 				DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
35861 				                      &tfm_ctx->bw,
35862 				                      DUK_ASC_PERCENT,
35863 				                      p[0],
35864 				                      p[1]);
35865 			} else {
35866 				DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) t);
35867 			}
35868 			tfm_ctx->p += 2;
35869 			return;
35870 		}
35871 
35872 		/* Decode UTF-8 codepoint from a sequence of hex escapes.  The
35873 		 * first byte of the sequence has been decoded to 't'.
35874 		 *
35875 		 * Note that UTF-8 validation must be strict according to the
35876 		 * specification: E5.1 Section 15.1.3, decode algorithm step
35877 		 * 4.d.vii.8.  URIError from non-shortest encodings is also
35878 		 * specifically noted in the spec.
35879 		 */
35880 
35881 		DUK_ASSERT(t >= 0x80);
35882 		if (t < 0xc0) {
35883 			/* continuation byte */
35884 			goto uri_error;
35885 		} else if (t < 0xe0) {
35886 			/* 110x xxxx; 2 bytes */
35887 			utf8_blen = 2;
35888 			min_cp = 0x80L;
35889 			cp = t & 0x1f;
35890 		} else if (t < 0xf0) {
35891 			/* 1110 xxxx; 3 bytes */
35892 			utf8_blen = 3;
35893 			min_cp = 0x800L;
35894 			cp = t & 0x0f;
35895 		} else if (t < 0xf8) {
35896 			/* 1111 0xxx; 4 bytes */
35897 			utf8_blen = 4;
35898 			min_cp = 0x10000L;
35899 			cp = t & 0x07;
35900 		} else {
35901 			/* extended utf-8 not allowed for URIs */
35902 			goto uri_error;
35903 		}
35904 
35905 		if (left < utf8_blen * 3 - 1) {
35906 			/* '%xx%xx...%xx', p points to char after first '%' */
35907 			goto uri_error;
35908 		}
35909 
35910 		p += 3;
35911 		for (i = 1; i < utf8_blen; i++) {
35912 			/* p points to digit part ('%xy', p points to 'x') */
35913 			t = duk__decode_hex_escape(p, 2);
35914 			DUK_DDD(DUK_DDDPRINT("i=%ld utf8_blen=%ld cp=%ld t=0x%02lx",
35915 			                     (long) i, (long) utf8_blen, (long) cp, (unsigned long) t));
35916 			if (t < 0) {
35917 				goto uri_error;
35918 			}
35919 			if ((t & 0xc0) != 0x80) {
35920 				goto uri_error;
35921 			}
35922 			cp = (cp << 6) + (t & 0x3f);
35923 			p += 3;
35924 		}
35925 		p--;  /* p overshoots */
35926 		tfm_ctx->p = p;
35927 
35928 		DUK_DDD(DUK_DDDPRINT("final cp=%ld, min_cp=%ld", (long) cp, (long) min_cp));
35929 
35930 		if (cp < min_cp || cp > 0x10ffffL || (cp >= 0xd800L && cp <= 0xdfffL)) {
35931 			goto uri_error;
35932 		}
35933 
35934 		/* The E5.1 algorithm checks whether or not a decoded codepoint
35935 		 * is below 0x80 and perhaps may be in the "reserved" set.
35936 		 * This seems pointless because the single byte UTF-8 case is
35937 		 * handled separately, and non-shortest encodings are rejected.
35938 		 * So, 'cp' cannot be below 0x80 here, and thus cannot be in
35939 		 * the reserved set.
35940 		 */
35941 
35942 		/* utf-8 validation ensures these */
35943 		DUK_ASSERT(cp >= 0x80L && cp <= 0x10ffffL);
35944 
35945 		if (cp >= 0x10000L) {
35946 			cp -= 0x10000L;
35947 			DUK_ASSERT(cp < 0x100000L);
35948 
35949 			DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp >> 10) + 0xd800L));
35950 			DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp & 0x03ffL) + 0xdc00L));
35951 		} else {
35952 			DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
35953 		}
35954 	} else {
35955 		DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
35956 	}
35957 	return;
35958 
35959  uri_error:
35960 	DUK_ERROR_URI(tfm_ctx->thr, DUK_STR_INVALID_INPUT);
35961 	DUK_WO_NORETURN(return;);
35962 }
35963 
35964 #if defined(DUK_USE_SECTION_B)
duk__transform_callback_escape(duk__transform_context * tfm_ctx,const void * udata,duk_codepoint_t cp)35965 DUK_LOCAL void duk__transform_callback_escape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
35966 	DUK_UNREF(udata);
35967 
35968 	DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 6);
35969 
35970 	if (cp < 0) {
35971 		goto esc_error;
35972 	} else if ((cp < 0x80L) && DUK__CHECK_BITMASK(duk__escape_unescaped_table, cp)) {
35973 		DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp);
35974 	} else if (cp < 0x100L) {
35975 		DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
35976 		                      &tfm_ctx->bw,
35977 		                      (duk_uint8_t) DUK_ASC_PERCENT,
35978 		                      (duk_uint8_t) duk_uc_nybbles[cp >> 4],
35979 		                      (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]);
35980 	} else if (cp < 0x10000L) {
35981 		DUK_BW_WRITE_RAW_U8_6(tfm_ctx->thr,
35982 		                      &tfm_ctx->bw,
35983 		                      (duk_uint8_t) DUK_ASC_PERCENT,
35984 		                      (duk_uint8_t) DUK_ASC_LC_U,
35985 		                      (duk_uint8_t) duk_uc_nybbles[cp >> 12],
35986 		                      (duk_uint8_t) duk_uc_nybbles[(cp >> 8) & 0x0f],
35987 		                      (duk_uint8_t) duk_uc_nybbles[(cp >> 4) & 0x0f],
35988 		                      (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]);
35989 	} else {
35990 		/* Characters outside BMP cannot be escape()'d.  We could
35991 		 * encode them as surrogate pairs (for codepoints inside
35992 		 * valid UTF-8 range, but not extended UTF-8).  Because
35993 		 * escape() and unescape() are legacy functions, we don't.
35994 		 */
35995 		goto esc_error;
35996 	}
35997 
35998 	return;
35999 
36000  esc_error:
36001 	DUK_ERROR_TYPE(tfm_ctx->thr, DUK_STR_INVALID_INPUT);
36002 	DUK_WO_NORETURN(return;);
36003 }
36004 
duk__transform_callback_unescape(duk__transform_context * tfm_ctx,const void * udata,duk_codepoint_t cp)36005 DUK_LOCAL void duk__transform_callback_unescape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
36006 	duk_small_int_t t;
36007 
36008 	DUK_UNREF(udata);
36009 
36010 	if (cp == (duk_codepoint_t) '%') {
36011 		const duk_uint8_t *p = tfm_ctx->p;
36012 		duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p);  /* bytes left */
36013 
36014 		if (left >= 5 && p[0] == 'u' &&
36015 		    ((t = duk__decode_hex_escape(p + 1, 4)) >= 0)) {
36016 			cp = (duk_codepoint_t) t;
36017 			tfm_ctx->p += 5;
36018 		} else if (left >= 2 &&
36019 		           ((t = duk__decode_hex_escape(p, 2)) >= 0)) {
36020 			cp = (duk_codepoint_t) t;
36021 			tfm_ctx->p += 2;
36022 		}
36023 	}
36024 
36025 	DUK_BW_WRITE_ENSURE_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
36026 }
36027 #endif  /* DUK_USE_SECTION_B */
36028 
36029 /*
36030  *  Eval
36031  *
36032  *  Eval needs to handle both a "direct eval" and an "indirect eval".
36033  *  Direct eval handling needs access to the caller's activation so that its
36034  *  lexical environment can be accessed.  A direct eval is only possible from
36035  *  ECMAScript code; an indirect eval call is possible also from C code.
36036  *  When an indirect eval call is made from C code, there may not be a
36037  *  calling activation at all which needs careful handling.
36038  */
36039 
duk_bi_global_object_eval(duk_hthread * thr)36040 DUK_INTERNAL duk_ret_t duk_bi_global_object_eval(duk_hthread *thr) {
36041 	duk_hstring *h;
36042 	duk_activation *act_caller;
36043 	duk_activation *act_eval;
36044 	duk_hcompfunc *func;
36045 	duk_hobject *outer_lex_env;
36046 	duk_hobject *outer_var_env;
36047 	duk_bool_t this_to_global = 1;
36048 	duk_small_uint_t comp_flags;
36049 	duk_int_t level = -2;
36050 	duk_small_uint_t call_flags;
36051 
36052 	DUK_ASSERT(duk_get_top(thr) == 1 || duk_get_top(thr) == 2);  /* 2 when called by debugger */
36053 	DUK_ASSERT(thr->callstack_top >= 1);  /* at least this function exists */
36054 	DUK_ASSERT(thr->callstack_curr != NULL);
36055 	DUK_ASSERT((thr->callstack_curr->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0 || /* indirect eval */
36056 	           (thr->callstack_top >= 2));  /* if direct eval, calling activation must exist */
36057 
36058 	/*
36059 	 *  callstack_top - 1 --> this function
36060 	 *  callstack_top - 2 --> caller (may not exist)
36061 	 *
36062 	 *  If called directly from C, callstack_top might be 1.  If calling
36063 	 *  activation doesn't exist, call must be indirect.
36064 	 */
36065 
36066 	h = duk_get_hstring_notsymbol(thr, 0);
36067 	if (!h) {
36068 		/* Symbol must be returned as is, like any non-string values. */
36069 		return 1;  /* return arg as-is */
36070 	}
36071 
36072 #if defined(DUK_USE_DEBUGGER_SUPPORT)
36073 	/* NOTE: level is used only by the debugger and should never be present
36074 	 * for an ECMAScript eval().
36075 	 */
36076 	DUK_ASSERT(level == -2);  /* by default, use caller's environment */
36077 	if (duk_get_top(thr) >= 2 && duk_is_number(thr, 1)) {
36078 		level = duk_get_int(thr, 1);
36079 	}
36080 	DUK_ASSERT(level <= -2);  /* This is guaranteed by debugger code. */
36081 #endif
36082 
36083 	/* [ source ] */
36084 
36085 	comp_flags = DUK_COMPILE_EVAL;
36086 	act_eval = thr->callstack_curr;  /* this function */
36087 	DUK_ASSERT(act_eval != NULL);
36088 	act_caller = duk_hthread_get_activation_for_level(thr, level);
36089 	if (act_caller != NULL) {
36090 		/* Have a calling activation, check for direct eval (otherwise
36091 		 * assume indirect eval.
36092 		 */
36093 		if ((act_caller->flags & DUK_ACT_FLAG_STRICT) &&
36094 		    (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL)) {
36095 			/* Only direct eval inherits strictness from calling code
36096 			 * (E5.1 Section 10.1.1).
36097 			 */
36098 			comp_flags |= DUK_COMPILE_STRICT;
36099 		}
36100 	} else {
36101 		DUK_ASSERT((act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0);
36102 	}
36103 
36104 	duk_push_hstring_stridx(thr, DUK_STRIDX_INPUT);  /* XXX: copy from caller? */
36105 	duk_js_compile(thr,
36106 	               (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h),
36107 	               (duk_size_t) DUK_HSTRING_GET_BYTELEN(h),
36108 	               comp_flags);
36109 	func = (duk_hcompfunc *) duk_known_hobject(thr, -1);
36110 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) func));
36111 
36112 	/* [ source template ] */
36113 
36114 	/* E5 Section 10.4.2 */
36115 
36116 	if (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
36117 		DUK_ASSERT(thr->callstack_top >= 2);
36118 		DUK_ASSERT(act_caller != NULL);
36119 		if (act_caller->lex_env == NULL) {
36120 			DUK_ASSERT(act_caller->var_env == NULL);
36121 			DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
36122 
36123 			/* this may have side effects, so re-lookup act */
36124 			duk_js_init_activation_environment_records_delayed(thr, act_caller);
36125 		}
36126 		DUK_ASSERT(act_caller->lex_env != NULL);
36127 		DUK_ASSERT(act_caller->var_env != NULL);
36128 
36129 		this_to_global = 0;
36130 
36131 		if (DUK_HOBJECT_HAS_STRICT((duk_hobject *) func)) {
36132 			duk_hdecenv *new_env;
36133 			duk_hobject *act_lex_env;
36134 
36135 			DUK_DDD(DUK_DDDPRINT("direct eval call to a strict function -> "
36136 			                     "var_env and lex_env to a fresh env, "
36137 			                     "this_binding to caller's this_binding"));
36138 
36139 			act_lex_env = act_caller->lex_env;
36140 
36141 			new_env = duk_hdecenv_alloc(thr,
36142 			                            DUK_HOBJECT_FLAG_EXTENSIBLE |
36143 			                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
36144 			DUK_ASSERT(new_env != NULL);
36145 			duk_push_hobject(thr, (duk_hobject *) new_env);
36146 
36147 			DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
36148 			DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, act_lex_env);
36149 			DUK_HOBJECT_INCREF_ALLOWNULL(thr, act_lex_env);
36150 			DUK_DDD(DUK_DDDPRINT("new_env allocated: %!iO", (duk_heaphdr *) new_env));
36151 
36152 			outer_lex_env = (duk_hobject *) new_env;
36153 			outer_var_env = (duk_hobject *) new_env;
36154 
36155 			duk_insert(thr, 0);  /* stash to bottom of value stack to keep new_env reachable for duration of eval */
36156 
36157 			/* compiler's responsibility */
36158 			DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV((duk_hobject *) func));
36159 		} else {
36160 			DUK_DDD(DUK_DDDPRINT("direct eval call to a non-strict function -> "
36161 			                     "var_env and lex_env to caller's envs, "
36162 			                     "this_binding to caller's this_binding"));
36163 
36164 			outer_lex_env = act_caller->lex_env;
36165 			outer_var_env = act_caller->var_env;
36166 
36167 			/* compiler's responsibility */
36168 			DUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV((duk_hobject *) func));
36169 		}
36170 	} else {
36171 		DUK_DDD(DUK_DDDPRINT("indirect eval call -> var_env and lex_env to "
36172 		                     "global object, this_binding to global object"));
36173 
36174 		this_to_global = 1;
36175 		outer_lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
36176 		outer_var_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
36177 	}
36178 
36179 	/* Eval code doesn't need an automatic .prototype object. */
36180 	duk_js_push_closure(thr, func, outer_var_env, outer_lex_env, 0 /*add_auto_proto*/);
36181 
36182 	/* [ env? source template closure ] */
36183 
36184 	if (this_to_global) {
36185 		DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
36186 		duk_push_hobject_bidx(thr, DUK_BIDX_GLOBAL);
36187 	} else {
36188 		duk_tval *tv;
36189 		DUK_ASSERT(thr->callstack_top >= 2);
36190 		DUK_ASSERT(act_caller != NULL);
36191 		tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act_caller->bottom_byteoff - sizeof(duk_tval));  /* this is just beneath bottom */
36192 		DUK_ASSERT(tv >= thr->valstack);
36193 		duk_push_tval(thr, tv);
36194 	}
36195 
36196 	DUK_DDD(DUK_DDDPRINT("eval -> lex_env=%!iO, var_env=%!iO, this_binding=%!T",
36197 	                     (duk_heaphdr *) outer_lex_env,
36198 	                     (duk_heaphdr *) outer_var_env,
36199 	                     duk_get_tval(thr, -1)));
36200 
36201 	/* [ env? source template closure this ] */
36202 
36203 	call_flags = 0;
36204 	if (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
36205 		/* Set DIRECT_EVAL flag for the call; it's not strictly
36206 		 * needed for the 'inner' eval call (the eval body) but
36207 		 * current new.target implementation expects to find it
36208 		 * so it can traverse direct eval chains up to the real
36209 		 * calling function.
36210 		 */
36211 		call_flags |= DUK_CALL_FLAG_DIRECT_EVAL;
36212 	}
36213 	duk_handle_call_unprotected_nargs(thr, 0, call_flags);
36214 
36215 	/* [ env? source template result ] */
36216 
36217 	return 1;
36218 }
36219 
36220 /*
36221  *  Parsing of ints and floats
36222  */
36223 
36224 #if defined(DUK_USE_GLOBAL_BUILTIN)
duk_bi_global_object_parse_int(duk_hthread * thr)36225 DUK_INTERNAL duk_ret_t duk_bi_global_object_parse_int(duk_hthread *thr) {
36226 	duk_int32_t radix;
36227 	duk_small_uint_t s2n_flags;
36228 
36229 	DUK_ASSERT_TOP(thr, 2);
36230 	duk_to_string(thr, 0);  /* Reject symbols. */
36231 
36232 	radix = duk_to_int32(thr, 1);
36233 
36234 	/* While parseInt() recognizes 0xdeadbeef, it doesn't recognize
36235 	 * ES2015 0o123 or 0b10001.
36236 	 */
36237 	s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
36238 	            DUK_S2N_FLAG_ALLOW_GARBAGE |
36239 	            DUK_S2N_FLAG_ALLOW_PLUS |
36240 	            DUK_S2N_FLAG_ALLOW_MINUS |
36241 	            DUK_S2N_FLAG_ALLOW_LEADING_ZERO |
36242 	            DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
36243 
36244 	/* Specification stripPrefix maps to DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT.
36245 	 *
36246 	 * Don't autodetect octals (from leading zeroes), require user code to
36247 	 * provide an explicit radix 8 for parsing octal.  See write-up from Mozilla:
36248 	 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt#ECMAScript_5_Removes_Octal_Interpretation
36249 	 */
36250 
36251 	if (radix != 0) {
36252 		if (radix < 2 || radix > 36) {
36253 			goto ret_nan;
36254 		}
36255 		if (radix != 16) {
36256 			s2n_flags &= ~DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
36257 		}
36258 	} else {
36259 		radix = 10;
36260 	}
36261 
36262 	duk_dup_0(thr);
36263 	duk_numconv_parse(thr, (duk_small_int_t) radix, s2n_flags);
36264 	return 1;
36265 
36266  ret_nan:
36267 	duk_push_nan(thr);
36268 	return 1;
36269 }
36270 #endif  /* DUK_USE_GLOBAL_BUILTIN */
36271 
36272 #if defined(DUK_USE_GLOBAL_BUILTIN)
duk_bi_global_object_parse_float(duk_hthread * thr)36273 DUK_INTERNAL duk_ret_t duk_bi_global_object_parse_float(duk_hthread *thr) {
36274 	duk_small_uint_t s2n_flags;
36275 
36276 	DUK_ASSERT_TOP(thr, 1);
36277 	duk_to_string(thr, 0);  /* Reject symbols. */
36278 
36279 	/* XXX: check flags */
36280 	s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
36281 	            DUK_S2N_FLAG_ALLOW_EXP |
36282 	            DUK_S2N_FLAG_ALLOW_GARBAGE |
36283 	            DUK_S2N_FLAG_ALLOW_PLUS |
36284 	            DUK_S2N_FLAG_ALLOW_MINUS |
36285 	            DUK_S2N_FLAG_ALLOW_INF |
36286 	            DUK_S2N_FLAG_ALLOW_FRAC |
36287 	            DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
36288 	            DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
36289 	            DUK_S2N_FLAG_ALLOW_LEADING_ZERO;
36290 
36291 	duk_numconv_parse(thr, 10 /*radix*/, s2n_flags);
36292 	return 1;
36293 }
36294 #endif  /* DUK_USE_GLOBAL_BUILTIN */
36295 
36296 /*
36297  *  Number checkers
36298  */
36299 
36300 #if defined(DUK_USE_GLOBAL_BUILTIN)
duk_bi_global_object_is_nan(duk_hthread * thr)36301 DUK_INTERNAL duk_ret_t duk_bi_global_object_is_nan(duk_hthread *thr) {
36302 	duk_double_t d = duk_to_number(thr, 0);
36303 	duk_push_boolean(thr, (duk_bool_t) DUK_ISNAN(d));
36304 	return 1;
36305 }
36306 #endif  /* DUK_USE_GLOBAL_BUILTIN */
36307 
36308 #if defined(DUK_USE_GLOBAL_BUILTIN)
duk_bi_global_object_is_finite(duk_hthread * thr)36309 DUK_INTERNAL duk_ret_t duk_bi_global_object_is_finite(duk_hthread *thr) {
36310 	duk_double_t d = duk_to_number(thr, 0);
36311 	duk_push_boolean(thr, (duk_bool_t) DUK_ISFINITE(d));
36312 	return 1;
36313 }
36314 #endif  /* DUK_USE_GLOBAL_BUILTIN */
36315 
36316 /*
36317  *  URI handling
36318  */
36319 
36320 #if defined(DUK_USE_GLOBAL_BUILTIN)
duk_bi_global_object_decode_uri(duk_hthread * thr)36321 DUK_INTERNAL duk_ret_t duk_bi_global_object_decode_uri(duk_hthread *thr) {
36322 	return duk__transform_helper(thr, duk__transform_callback_decode_uri, (const void *) duk__decode_uri_reserved_table);
36323 }
36324 
duk_bi_global_object_decode_uri_component(duk_hthread * thr)36325 DUK_INTERNAL duk_ret_t duk_bi_global_object_decode_uri_component(duk_hthread *thr) {
36326 	return duk__transform_helper(thr, duk__transform_callback_decode_uri, (const void *) duk__decode_uri_component_reserved_table);
36327 }
36328 
duk_bi_global_object_encode_uri(duk_hthread * thr)36329 DUK_INTERNAL duk_ret_t duk_bi_global_object_encode_uri(duk_hthread *thr) {
36330 	return duk__transform_helper(thr, duk__transform_callback_encode_uri, (const void *) duk__encode_uriunescaped_table);
36331 }
36332 
duk_bi_global_object_encode_uri_component(duk_hthread * thr)36333 DUK_INTERNAL duk_ret_t duk_bi_global_object_encode_uri_component(duk_hthread *thr) {
36334 	return duk__transform_helper(thr, duk__transform_callback_encode_uri, (const void *) duk__encode_uricomponent_unescaped_table);
36335 }
36336 
36337 #if defined(DUK_USE_SECTION_B)
duk_bi_global_object_escape(duk_hthread * thr)36338 DUK_INTERNAL duk_ret_t duk_bi_global_object_escape(duk_hthread *thr) {
36339 	return duk__transform_helper(thr, duk__transform_callback_escape, (const void *) NULL);
36340 }
36341 
duk_bi_global_object_unescape(duk_hthread * thr)36342 DUK_INTERNAL duk_ret_t duk_bi_global_object_unescape(duk_hthread *thr) {
36343 	return duk__transform_helper(thr, duk__transform_callback_unescape, (const void *) NULL);
36344 }
36345 #endif  /* DUK_USE_SECTION_B */
36346 #endif  /* DUK_USE_GLOBAL_BUILTIN */
36347 
36348 /* automatic undefs */
36349 #undef DUK__CHECK_BITMASK
36350 #undef DUK__MKBITS
36351 /*
36352  *  JSON built-ins.
36353  *
36354  *  See doc/json.rst.
36355  *
36356  *  Codepoints are handled as duk_uint_fast32_t to ensure that the full
36357  *  unsigned 32-bit range is supported.  This matters to e.g. JX.
36358  *
36359  *  Input parsing doesn't do an explicit end-of-input check at all.  This is
36360  *  safe: input string data is always NUL-terminated (0x00) and valid JSON
36361  *  inputs never contain plain NUL characters, so that as long as syntax checks
36362  *  are correct, we'll never read past the NUL.  This approach reduces code size
36363  *  and improves parsing performance, but it's critical that syntax checks are
36364  *  indeed correct!
36365  */
36366 
36367 /* #include duk_internal.h -> already included */
36368 
36369 #if defined(DUK_USE_JSON_SUPPORT)
36370 
36371 /*
36372  *  Local defines and forward declarations.
36373  */
36374 
36375 #define DUK__JSON_DECSTR_BUFSIZE 128
36376 #define DUK__JSON_DECSTR_CHUNKSIZE 64
36377 #define DUK__JSON_ENCSTR_CHUNKSIZE 64
36378 #define DUK__JSON_STRINGIFY_BUFSIZE 128
36379 #define DUK__JSON_MAX_ESC_LEN 10  /* '\Udeadbeef' */
36380 
36381 DUK_LOCAL_DECL void duk__json_dec_syntax_error(duk_json_dec_ctx *js_ctx);
36382 DUK_LOCAL_DECL void duk__json_dec_eat_white(duk_json_dec_ctx *js_ctx);
36383 #if defined(DUK_USE_JX)
36384 DUK_LOCAL_DECL duk_uint8_t duk__json_dec_peek(duk_json_dec_ctx *js_ctx);
36385 #endif
36386 DUK_LOCAL_DECL duk_uint8_t duk__json_dec_get(duk_json_dec_ctx *js_ctx);
36387 DUK_LOCAL_DECL duk_uint8_t duk__json_dec_get_nonwhite(duk_json_dec_ctx *js_ctx);
36388 DUK_LOCAL_DECL duk_uint_fast32_t duk__json_dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n);
36389 DUK_LOCAL_DECL void duk__json_dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx);
36390 DUK_LOCAL_DECL void duk__json_dec_string(duk_json_dec_ctx *js_ctx);
36391 #if defined(DUK_USE_JX)
36392 DUK_LOCAL_DECL void duk__json_dec_plain_string(duk_json_dec_ctx *js_ctx);
36393 DUK_LOCAL_DECL void duk__json_dec_pointer(duk_json_dec_ctx *js_ctx);
36394 DUK_LOCAL_DECL void duk__json_dec_buffer(duk_json_dec_ctx *js_ctx);
36395 #endif
36396 DUK_LOCAL_DECL void duk__json_dec_number(duk_json_dec_ctx *js_ctx);
36397 DUK_LOCAL_DECL void duk__json_dec_objarr_entry(duk_json_dec_ctx *js_ctx);
36398 DUK_LOCAL_DECL void duk__json_dec_objarr_exit(duk_json_dec_ctx *js_ctx);
36399 DUK_LOCAL_DECL void duk__json_dec_object(duk_json_dec_ctx *js_ctx);
36400 DUK_LOCAL_DECL void duk__json_dec_array(duk_json_dec_ctx *js_ctx);
36401 DUK_LOCAL_DECL void duk__json_dec_value(duk_json_dec_ctx *js_ctx);
36402 DUK_LOCAL_DECL void duk__json_dec_reviver_walk(duk_json_dec_ctx *js_ctx);
36403 
36404 DUK_LOCAL_DECL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch);
36405 DUK_LOCAL_DECL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2);
36406 DUK_LOCAL_DECL void duk__unemit_1(duk_json_enc_ctx *js_ctx);
36407 DUK_LOCAL_DECL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h);
36408 #if defined(DUK_USE_FASTINT)
36409 DUK_LOCAL_DECL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *p);
36410 #endif
36411 DUK_LOCAL_DECL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx);
36412 DUK_LOCAL_DECL duk_uint8_t *duk__emit_esc_auto_fast(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp, duk_uint8_t *q);
36413 DUK_LOCAL_DECL void duk__json_enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k);
36414 DUK_LOCAL_DECL void duk__json_enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str);
36415 DUK_LOCAL_DECL void duk__json_enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);
36416 DUK_LOCAL_DECL void duk__json_enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);
36417 DUK_LOCAL_DECL void duk__json_enc_object(duk_json_enc_ctx *js_ctx);
36418 DUK_LOCAL_DECL void duk__json_enc_array(duk_json_enc_ctx *js_ctx);
36419 DUK_LOCAL_DECL duk_bool_t duk__json_enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder);
36420 DUK_LOCAL_DECL duk_bool_t duk__json_enc_allow_into_proplist(duk_tval *tv);
36421 DUK_LOCAL_DECL void duk__json_enc_double(duk_json_enc_ctx *js_ctx);
36422 #if defined(DUK_USE_FASTINT)
36423 DUK_LOCAL_DECL void duk__json_enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv);
36424 #endif
36425 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36426 DUK_LOCAL_DECL void duk__json_enc_buffer_jx_jc(duk_json_enc_ctx *js_ctx, duk_hbuffer *h);
36427 DUK_LOCAL_DECL void duk__json_enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr);
36428 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
36429 DUK_LOCAL_DECL void duk__json_enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj);
36430 #endif
36431 #endif
36432 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
36433 DUK_LOCAL_DECL void duk__json_enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h);
36434 #endif
36435 DUK_LOCAL_DECL void duk__json_enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth);
36436 
36437 /*
36438  *  Helper tables
36439  */
36440 
36441 #if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH)
36442 DUK_LOCAL const duk_uint8_t duk__json_quotestr_lookup[256] = {
36443 	/* 0x00 ... 0x7f: as is
36444 	 * 0x80: escape generically
36445 	 * 0x81: slow path
36446 	 * 0xa0 ... 0xff: backslash + one char
36447 	 */
36448 
36449 	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xe2, 0xf4, 0xee, 0x80, 0xe6, 0xf2, 0x80, 0x80,
36450 	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
36451 	0x20, 0x21, 0xa2, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
36452 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
36453 	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
36454 	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0xdc, 0x5d, 0x5e, 0x5f,
36455 	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
36456 	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x81,
36457 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
36458 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
36459 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
36460 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
36461 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
36462 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
36463 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
36464 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81
36465 };
36466 #else  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
36467 DUK_LOCAL const duk_uint8_t duk__json_quotestr_esc[14] = {
36468 	DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL,
36469 	DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL,
36470 	DUK_ASC_LC_B, DUK_ASC_LC_T, DUK_ASC_LC_N, DUK_ASC_NUL,
36471 	DUK_ASC_LC_F, DUK_ASC_LC_R
36472 };
36473 #endif  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
36474 
36475 #if defined(DUK_USE_JSON_DECSTRING_FASTPATH)
36476 DUK_LOCAL const duk_uint8_t duk__json_decstr_lookup[256] = {
36477 	/* 0x00: slow path
36478 	 * other: as is
36479 	 */
36480 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36481 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36482 	0x20, 0x21, 0x00, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
36483 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
36484 	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
36485 	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x00, 0x5d, 0x5e, 0x5f,
36486 	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
36487 	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
36488 	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
36489 	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
36490 	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
36491 	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
36492 	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
36493 	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
36494 	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
36495 	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
36496 };
36497 #endif  /* DUK_USE_JSON_DECSTRING_FASTPATH */
36498 
36499 #if defined(DUK_USE_JSON_EATWHITE_FASTPATH)
36500 DUK_LOCAL const duk_uint8_t duk__json_eatwhite_lookup[256] = {
36501 	/* 0x00: finish (non-white)
36502 	 * 0x01: continue
36503 	 */
36504 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
36505 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36506 	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36507 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36508 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36509 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36510 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36511 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36512 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36513 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36514 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36515 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36516 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36517 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36518 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36519 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
36520 };
36521 #endif  /* DUK_USE_JSON_EATWHITE_FASTPATH */
36522 
36523 #if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)
36524 DUK_LOCAL const duk_uint8_t duk__json_decnumber_lookup[256] = {
36525 	/* 0x00: finish (not part of number)
36526 	 * 0x01: continue
36527 	 */
36528 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36529 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36530 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00,
36531 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36532 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36533 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36534 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36535 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36536 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36537 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36538 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36539 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36540 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36541 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36542 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36543 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
36544 };
36545 #endif  /* DUK_USE_JSON_DECNUMBER_FASTPATH */
36546 
36547 /*
36548  *  Parsing implementation.
36549  *
36550  *  JSON lexer is now separate from duk_lexer.c because there are numerous
36551  *  small differences making it difficult to share the lexer.
36552  *
36553  *  The parser here works with raw bytes directly; this works because all
36554  *  JSON delimiters are ASCII characters.  Invalid xUTF-8 encoded values
36555  *  inside strings will be passed on without normalization; this is not a
36556  *  compliance concern because compliant inputs will always be valid
36557  *  CESU-8 encodings.
36558  */
36559 
duk__json_dec_syntax_error(duk_json_dec_ctx * js_ctx)36560 DUK_LOCAL void duk__json_dec_syntax_error(duk_json_dec_ctx *js_ctx) {
36561 	/* Shared handler to minimize parser size.  Cause will be
36562 	 * hidden, unfortunately, but we'll have an offset which
36563 	 * is often quite enough.
36564 	 */
36565 	DUK_ERROR_FMT1(js_ctx->thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_FMT_INVALID_JSON,
36566 	               (long) (js_ctx->p - js_ctx->p_start));
36567 	DUK_WO_NORETURN(return;);
36568 }
36569 
duk__json_dec_eat_white(duk_json_dec_ctx * js_ctx)36570 DUK_LOCAL void duk__json_dec_eat_white(duk_json_dec_ctx *js_ctx) {
36571 	const duk_uint8_t *p;
36572 	duk_uint8_t t;
36573 
36574 	p = js_ctx->p;
36575 	for (;;) {
36576 		DUK_ASSERT(p <= js_ctx->p_end);
36577 		t = *p;
36578 
36579 #if defined(DUK_USE_JSON_EATWHITE_FASTPATH)
36580 		/* This fast path is pretty marginal in practice.
36581 		 * XXX: candidate for removal.
36582 		 */
36583 		DUK_ASSERT(duk__json_eatwhite_lookup[0x00] == 0x00);  /* end-of-input breaks */
36584 		if (duk__json_eatwhite_lookup[t] == 0) {
36585 			break;
36586 		}
36587 #else  /* DUK_USE_JSON_EATWHITE_FASTPATH */
36588 		if (!(t == 0x20 || t == 0x0a || t == 0x0d || t == 0x09)) {
36589 			/* NUL also comes here.  Comparison order matters, 0x20
36590 			 * is most common whitespace.
36591 			 */
36592 			break;
36593 		}
36594 #endif  /* DUK_USE_JSON_EATWHITE_FASTPATH */
36595 		p++;
36596 	}
36597 	js_ctx->p = p;
36598 }
36599 
36600 #if defined(DUK_USE_JX)
duk__json_dec_peek(duk_json_dec_ctx * js_ctx)36601 DUK_LOCAL duk_uint8_t duk__json_dec_peek(duk_json_dec_ctx *js_ctx) {
36602 	DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
36603 	return *js_ctx->p;
36604 }
36605 #endif
36606 
duk__json_dec_get(duk_json_dec_ctx * js_ctx)36607 DUK_LOCAL duk_uint8_t duk__json_dec_get(duk_json_dec_ctx *js_ctx) {
36608 	DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
36609 	return *js_ctx->p++;
36610 }
36611 
duk__json_dec_get_nonwhite(duk_json_dec_ctx * js_ctx)36612 DUK_LOCAL duk_uint8_t duk__json_dec_get_nonwhite(duk_json_dec_ctx *js_ctx) {
36613 	duk__json_dec_eat_white(js_ctx);
36614 	return duk__json_dec_get(js_ctx);
36615 }
36616 
36617 /* For JX, expressing the whole unsigned 32-bit range matters. */
duk__json_dec_decode_hex_escape(duk_json_dec_ctx * js_ctx,duk_small_uint_t n)36618 DUK_LOCAL duk_uint_fast32_t duk__json_dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n) {
36619 	duk_small_uint_t i;
36620 	duk_uint_fast32_t res = 0;
36621 	duk_uint8_t x;
36622 	duk_small_int_t t;
36623 
36624 	for (i = 0; i < n; i++) {
36625 		/* XXX: share helper from lexer; duk_lexer.c / hexval(). */
36626 
36627 		x = duk__json_dec_get(js_ctx);
36628 		DUK_DDD(DUK_DDDPRINT("decode_hex_escape: i=%ld, n=%ld, res=%ld, x=%ld",
36629 		                     (long) i, (long) n, (long) res, (long) x));
36630 
36631 		/* x == 0x00 (EOF) causes syntax_error */
36632 		DUK_ASSERT(duk_hex_dectab[0] == -1);
36633 		t = duk_hex_dectab[x & 0xff];
36634 		if (DUK_LIKELY(t >= 0)) {
36635 			res = (res * 16) + (duk_uint_fast32_t) t;
36636 		} else {
36637 			/* catches EOF and invalid digits */
36638 			goto syntax_error;
36639 		}
36640 	}
36641 
36642 	DUK_DDD(DUK_DDDPRINT("final hex decoded value: %ld", (long) res));
36643 	return res;
36644 
36645  syntax_error:
36646 	duk__json_dec_syntax_error(js_ctx);
36647 	DUK_UNREACHABLE();
36648 	return 0;
36649 }
36650 
duk__json_dec_req_stridx(duk_json_dec_ctx * js_ctx,duk_small_uint_t stridx)36651 DUK_LOCAL void duk__json_dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx) {
36652 	duk_hstring *h;
36653 	const duk_uint8_t *p;
36654 	duk_uint8_t x, y;
36655 
36656 	/* First character has already been eaten and checked by the caller.
36657 	 * We can scan until a NUL in stridx string because no built-in strings
36658 	 * have internal NULs.
36659 	 */
36660 
36661 	DUK_ASSERT_STRIDX_VALID(stridx);
36662 	h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx);
36663 	DUK_ASSERT(h != NULL);
36664 
36665 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h) + 1;
36666 	DUK_ASSERT(*(js_ctx->p - 1) == *(p - 1));  /* first character has been matched */
36667 
36668 	for (;;) {
36669 		x = *p;
36670 		if (x == 0) {
36671 			break;
36672 		}
36673 		y = duk__json_dec_get(js_ctx);
36674 		if (x != y) {
36675 			/* Catches EOF of JSON input. */
36676 			goto syntax_error;
36677 		}
36678 		p++;
36679 	}
36680 
36681 	return;
36682 
36683  syntax_error:
36684 	duk__json_dec_syntax_error(js_ctx);
36685 	DUK_UNREACHABLE();
36686 }
36687 
duk__json_dec_string_escape(duk_json_dec_ctx * js_ctx,duk_uint8_t ** ext_p)36688 DUK_LOCAL duk_small_int_t duk__json_dec_string_escape(duk_json_dec_ctx *js_ctx, duk_uint8_t **ext_p) {
36689 	duk_uint_fast32_t cp;
36690 
36691 	/* EOF (-1) will be cast to an unsigned value first
36692 	 * and then re-cast for the switch.  In any case, it
36693 	 * will match the default case (syntax error).
36694 	 */
36695 	cp = (duk_uint_fast32_t) duk__json_dec_get(js_ctx);
36696 	switch (cp) {
36697 	case DUK_ASC_BACKSLASH: break;
36698 	case DUK_ASC_DOUBLEQUOTE: break;
36699 	case DUK_ASC_SLASH: break;
36700 	case DUK_ASC_LC_T: cp = 0x09; break;
36701 	case DUK_ASC_LC_N: cp = 0x0a; break;
36702 	case DUK_ASC_LC_R: cp = 0x0d; break;
36703 	case DUK_ASC_LC_F: cp = 0x0c; break;
36704 	case DUK_ASC_LC_B: cp = 0x08; break;
36705 	case DUK_ASC_LC_U: {
36706 		cp = duk__json_dec_decode_hex_escape(js_ctx, 4);
36707 		break;
36708 	}
36709 #if defined(DUK_USE_JX)
36710 	case DUK_ASC_UC_U: {
36711 		if (js_ctx->flag_ext_custom) {
36712 			cp = duk__json_dec_decode_hex_escape(js_ctx, 8);
36713 		} else {
36714 			return 1;  /* syntax error */
36715 		}
36716 		break;
36717 	}
36718 	case DUK_ASC_LC_X: {
36719 		if (js_ctx->flag_ext_custom) {
36720 			cp = duk__json_dec_decode_hex_escape(js_ctx, 2);
36721 		} else {
36722 			return 1;  /* syntax error */
36723 		}
36724 		break;
36725 	}
36726 #endif  /* DUK_USE_JX */
36727 	default:
36728 		/* catches EOF (0x00) */
36729 		return 1;  /* syntax error */
36730 	}
36731 
36732 	DUK_RAW_WRITEINC_XUTF8(*ext_p, cp);
36733 
36734 	return 0;
36735 }
36736 
duk__json_dec_string(duk_json_dec_ctx * js_ctx)36737 DUK_LOCAL void duk__json_dec_string(duk_json_dec_ctx *js_ctx) {
36738 	duk_hthread *thr = js_ctx->thr;
36739 	duk_bufwriter_ctx bw_alloc;
36740 	duk_bufwriter_ctx *bw;
36741 	duk_uint8_t *q;
36742 
36743 	/* '"' was eaten by caller */
36744 
36745 	/* Note that we currently parse -bytes-, not codepoints.
36746 	 * All non-ASCII extended UTF-8 will encode to bytes >= 0x80,
36747 	 * so they'll simply pass through (valid UTF-8 or not).
36748 	 */
36749 
36750 	bw = &bw_alloc;
36751 	DUK_BW_INIT_PUSHBUF(js_ctx->thr, bw, DUK__JSON_DECSTR_BUFSIZE);
36752 	q = DUK_BW_GET_PTR(js_ctx->thr, bw);
36753 
36754 #if defined(DUK_USE_JSON_DECSTRING_FASTPATH)
36755 	for (;;) {
36756 		duk_small_uint_t safe;
36757 		duk_uint8_t b, x;
36758 		const duk_uint8_t *p;
36759 
36760 		/* Select a safe loop count where no output checks are
36761 		 * needed assuming we won't encounter escapes.  Input
36762 		 * bound checks are not necessary as a NUL (guaranteed)
36763 		 * will cause a SyntaxError before we read out of bounds.
36764 		 */
36765 
36766 		safe = DUK__JSON_DECSTR_CHUNKSIZE;
36767 
36768 		/* Ensure space for 1:1 output plus one escape. */
36769 		q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, safe + DUK_UNICODE_MAX_XUTF8_LENGTH, q);
36770 
36771 		p = js_ctx->p;  /* temp copy, write back for next loop */
36772 		for (;;) {
36773 			if (safe == 0) {
36774 				js_ctx->p = p;
36775 				break;
36776 			}
36777 			safe--;
36778 
36779 			/* End of input (NUL) goes through slow path and causes SyntaxError. */
36780 			DUK_ASSERT(duk__json_decstr_lookup[0] == 0x00);
36781 
36782 			b = *p++;
36783 			x = (duk_small_int_t) duk__json_decstr_lookup[b];
36784 			if (DUK_LIKELY(x != 0)) {
36785 				/* Fast path, decode as is. */
36786 				*q++ = b;
36787 			} else if (b == DUK_ASC_DOUBLEQUOTE) {
36788 				js_ctx->p = p;
36789 				goto found_quote;
36790 			} else if (b == DUK_ASC_BACKSLASH) {
36791 				/* We've ensured space for one escaped input; then
36792 				 * bail out and recheck (this makes escape handling
36793 				 * quite slow but it's uncommon).
36794 				 */
36795 				js_ctx->p = p;
36796 				if (duk__json_dec_string_escape(js_ctx, &q) != 0) {
36797 					goto syntax_error;
36798 				}
36799 				break;
36800 			} else {
36801 				js_ctx->p = p;
36802 				goto syntax_error;
36803 			}
36804 		}
36805 	}
36806  found_quote:
36807 #else  /* DUK_USE_JSON_DECSTRING_FASTPATH */
36808 	for (;;) {
36809 		duk_uint8_t x;
36810 
36811 		q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, DUK_UNICODE_MAX_XUTF8_LENGTH, q);
36812 
36813 		x = duk__json_dec_get(js_ctx);
36814 
36815 		if (x == DUK_ASC_DOUBLEQUOTE) {
36816 			break;
36817 		} else if (x == DUK_ASC_BACKSLASH) {
36818 			if (duk__json_dec_string_escape(js_ctx, &q) != 0) {
36819 				goto syntax_error;
36820 			}
36821 		} else if (x < 0x20) {
36822 			/* catches EOF (NUL) */
36823 			goto syntax_error;
36824 		} else {
36825 			*q++ = (duk_uint8_t) x;
36826 		}
36827 	}
36828 #endif  /* DUK_USE_JSON_DECSTRING_FASTPATH */
36829 
36830 	DUK_BW_SETPTR_AND_COMPACT(js_ctx->thr, bw, q);
36831 	(void) duk_buffer_to_string(thr, -1);  /* Safe if input string is safe. */
36832 
36833 	/* [ ... str ] */
36834 
36835 	return;
36836 
36837  syntax_error:
36838 	duk__json_dec_syntax_error(js_ctx);
36839 	DUK_UNREACHABLE();
36840 }
36841 
36842 #if defined(DUK_USE_JX)
36843 /* Decode a plain string consisting entirely of identifier characters.
36844  * Used to parse plain keys (e.g. "foo: 123").
36845  */
duk__json_dec_plain_string(duk_json_dec_ctx * js_ctx)36846 DUK_LOCAL void duk__json_dec_plain_string(duk_json_dec_ctx *js_ctx) {
36847 	duk_hthread *thr = js_ctx->thr;
36848 	const duk_uint8_t *p;
36849 	duk_small_int_t x;
36850 
36851 	/* Caller has already eaten the first char so backtrack one byte. */
36852 
36853 	js_ctx->p--;  /* safe */
36854 	p = js_ctx->p;
36855 
36856 	/* Here again we parse bytes, and non-ASCII UTF-8 will cause end of
36857 	 * parsing (which is correct except if there are non-shortest encodings).
36858 	 * There is also no need to check explicitly for end of input buffer as
36859 	 * the input is NUL padded and NUL will exit the parsing loop.
36860 	 *
36861 	 * Because no unescaping takes place, we can just scan to the end of the
36862 	 * plain string and intern from the input buffer.
36863 	 */
36864 
36865 	for (;;) {
36866 		x = *p;
36867 
36868 		/* There is no need to check the first character specially here
36869 		 * (i.e. reject digits): the caller only accepts valid initial
36870 		 * characters and won't call us if the first character is a digit.
36871 		 * This also ensures that the plain string won't be empty.
36872 		 */
36873 
36874 		if (!duk_unicode_is_identifier_part((duk_codepoint_t) x)) {
36875 			break;
36876 		}
36877 		p++;
36878 	}
36879 
36880 	duk_push_lstring(thr, (const char *) js_ctx->p, (duk_size_t) (p - js_ctx->p));
36881 	js_ctx->p = p;
36882 
36883 	/* [ ... str ] */
36884 }
36885 #endif  /* DUK_USE_JX */
36886 
36887 #if defined(DUK_USE_JX)
duk__json_dec_pointer(duk_json_dec_ctx * js_ctx)36888 DUK_LOCAL void duk__json_dec_pointer(duk_json_dec_ctx *js_ctx) {
36889 	duk_hthread *thr = js_ctx->thr;
36890 	const duk_uint8_t *p;
36891 	duk_small_int_t x;
36892 	void *voidptr;
36893 
36894 	/* Caller has already eaten the first character ('(') which we don't need. */
36895 
36896 	p = js_ctx->p;
36897 
36898 	for (;;) {
36899 		x = *p;
36900 
36901 		/* Assume that the native representation never contains a closing
36902 		 * parenthesis.
36903 		 */
36904 
36905 		if (x == DUK_ASC_RPAREN) {
36906 			break;
36907 		} else if (x <= 0) {
36908 			/* NUL term or -1 (EOF), NUL check would suffice */
36909 			goto syntax_error;
36910 		}
36911 		p++;
36912 	}
36913 
36914 	/* There is no need to NUL delimit the sscanf() call: trailing garbage is
36915 	 * ignored and there is always a NUL terminator which will force an error
36916 	 * if no error is encountered before it.  It's possible that the scan
36917 	 * would scan further than between [js_ctx->p,p[ though and we'd advance
36918 	 * by less than the scanned value.
36919 	 *
36920 	 * Because pointers are platform specific, a failure to scan a pointer
36921 	 * results in a null pointer which is a better placeholder than a missing
36922 	 * value or an error.
36923 	 */
36924 
36925 	voidptr = NULL;
36926 	(void) DUK_SSCANF((const char *) js_ctx->p, DUK_STR_FMT_PTR, &voidptr);
36927 	duk_push_pointer(thr, voidptr);
36928 	js_ctx->p = p + 1;  /* skip ')' */
36929 
36930 	/* [ ... ptr ] */
36931 
36932 	return;
36933 
36934  syntax_error:
36935 	duk__json_dec_syntax_error(js_ctx);
36936 	DUK_UNREACHABLE();
36937 }
36938 #endif  /* DUK_USE_JX */
36939 
36940 #if defined(DUK_USE_JX)
duk__json_dec_buffer(duk_json_dec_ctx * js_ctx)36941 DUK_LOCAL void duk__json_dec_buffer(duk_json_dec_ctx *js_ctx) {
36942 	duk_hthread *thr = js_ctx->thr;
36943 	const duk_uint8_t *p;
36944 	duk_uint8_t *buf;
36945 	duk_size_t src_len;
36946 	duk_small_int_t x;
36947 
36948 	/* Caller has already eaten the first character ('|') which we don't need. */
36949 
36950 	p = js_ctx->p;
36951 
36952 	/* XXX: Would be nice to share the fast path loop from duk_hex_decode()
36953 	 * and avoid creating a temporary buffer.  However, there are some
36954 	 * differences which prevent trivial sharing:
36955 	 *
36956 	 *   - Pipe char detection
36957 	 *   - EOF detection
36958 	 *   - Unknown length of input and output
36959 	 *
36960 	 * The best approach here would be a bufwriter and a reasonaly sized
36961 	 * safe inner loop (e.g. 64 output bytes at a time).
36962 	 */
36963 
36964 	for (;;) {
36965 		x = *p;
36966 
36967 		/* This loop intentionally does not ensure characters are valid
36968 		 * ([0-9a-fA-F]) because the hex decode call below will do that.
36969 		 */
36970 		if (x == DUK_ASC_PIPE) {
36971 			break;
36972 		} else if (x <= 0) {
36973 			/* NUL term or -1 (EOF), NUL check would suffice */
36974 			goto syntax_error;
36975 		}
36976 		p++;
36977 	}
36978 
36979 	/* XXX: this is not very nice; unnecessary copy is made. */
36980 	src_len = (duk_size_t) (p - js_ctx->p);
36981 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, src_len);
36982 	DUK_ASSERT(buf != NULL);
36983 	duk_memcpy((void *) buf, (const void *) js_ctx->p, src_len);
36984 	duk_hex_decode(thr, -1);
36985 
36986 	js_ctx->p = p + 1;  /* skip '|' */
36987 
36988 	/* [ ... buf ] */
36989 
36990 	return;
36991 
36992  syntax_error:
36993 	duk__json_dec_syntax_error(js_ctx);
36994 	DUK_UNREACHABLE();
36995 }
36996 #endif  /* DUK_USE_JX */
36997 
36998 /* Parse a number, other than NaN or +/- Infinity */
duk__json_dec_number(duk_json_dec_ctx * js_ctx)36999 DUK_LOCAL void duk__json_dec_number(duk_json_dec_ctx *js_ctx) {
37000 	duk_hthread *thr = js_ctx->thr;
37001 	const duk_uint8_t *p_start;
37002 	const duk_uint8_t *p;
37003 	duk_uint8_t x;
37004 	duk_small_uint_t s2n_flags;
37005 
37006 	DUK_DDD(DUK_DDDPRINT("parse_number"));
37007 
37008 	p_start = js_ctx->p;
37009 
37010 	/* First pass parse is very lenient (e.g. allows '1.2.3') and extracts a
37011 	 * string for strict number parsing.
37012 	 */
37013 
37014 	p = js_ctx->p;
37015 	for (;;) {
37016 		x = *p;
37017 
37018 		DUK_DDD(DUK_DDDPRINT("parse_number: p_start=%p, p=%p, p_end=%p, x=%ld",
37019 		                     (const void *) p_start, (const void *) p,
37020 		                     (const void *) js_ctx->p_end, (long) x));
37021 
37022 #if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)
37023 		/* This fast path is pretty marginal in practice.
37024 		 * XXX: candidate for removal.
37025 		 */
37026 		DUK_ASSERT(duk__json_decnumber_lookup[0x00] == 0x00);  /* end-of-input breaks */
37027 		if (duk__json_decnumber_lookup[x] == 0) {
37028 			break;
37029 		}
37030 #else  /* DUK_USE_JSON_DECNUMBER_FASTPATH */
37031 		if (!((x >= DUK_ASC_0 && x <= DUK_ASC_9) ||
37032 		      (x == DUK_ASC_PERIOD || x == DUK_ASC_LC_E ||
37033 		       x == DUK_ASC_UC_E || x == DUK_ASC_MINUS || x == DUK_ASC_PLUS))) {
37034 			/* Plus sign must be accepted for positive exponents
37035 			 * (e.g. '1.5e+2').  This clause catches NULs.
37036 			 */
37037 			break;
37038 		}
37039 #endif  /* DUK_USE_JSON_DECNUMBER_FASTPATH */
37040 		p++;  /* safe, because matched (NUL causes a break) */
37041 	}
37042 	js_ctx->p = p;
37043 
37044 	DUK_ASSERT(js_ctx->p > p_start);
37045 	duk_push_lstring(thr, (const char *) p_start, (duk_size_t) (p - p_start));
37046 
37047 	s2n_flags = DUK_S2N_FLAG_ALLOW_EXP |
37048 	            DUK_S2N_FLAG_ALLOW_MINUS |  /* but don't allow leading plus */
37049 	            DUK_S2N_FLAG_ALLOW_FRAC;
37050 
37051 	DUK_DDD(DUK_DDDPRINT("parse_number: string before parsing: %!T",
37052 	                     (duk_tval *) duk_get_tval(thr, -1)));
37053 	duk_numconv_parse(thr, 10 /*radix*/, s2n_flags);
37054 	if (duk_is_nan(thr, -1)) {
37055 		duk__json_dec_syntax_error(js_ctx);
37056 	}
37057 	DUK_ASSERT(duk_is_number(thr, -1));
37058 	DUK_DDD(DUK_DDDPRINT("parse_number: final number: %!T",
37059 	                     (duk_tval *) duk_get_tval(thr, -1)));
37060 
37061 	/* [ ... num ] */
37062 }
37063 
duk__json_dec_objarr_entry(duk_json_dec_ctx * js_ctx)37064 DUK_LOCAL void duk__json_dec_objarr_entry(duk_json_dec_ctx *js_ctx) {
37065 	duk_hthread *thr = js_ctx->thr;
37066 	duk_require_stack(thr, DUK_JSON_DEC_REQSTACK);
37067 
37068 	/* c recursion check */
37069 
37070 	duk_native_stack_check(thr);
37071 
37072 	DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0);  /* unsigned */
37073 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
37074 	if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
37075 		DUK_ERROR_RANGE(thr, DUK_STR_DEC_RECLIMIT);
37076 		DUK_WO_NORETURN(return;);
37077 	}
37078 	js_ctx->recursion_depth++;
37079 }
37080 
duk__json_dec_objarr_exit(duk_json_dec_ctx * js_ctx)37081 DUK_LOCAL void duk__json_dec_objarr_exit(duk_json_dec_ctx *js_ctx) {
37082 	/* c recursion check */
37083 
37084 	DUK_ASSERT(js_ctx->recursion_depth > 0);
37085 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
37086 	js_ctx->recursion_depth--;
37087 }
37088 
duk__json_dec_object(duk_json_dec_ctx * js_ctx)37089 DUK_LOCAL void duk__json_dec_object(duk_json_dec_ctx *js_ctx) {
37090 	duk_hthread *thr = js_ctx->thr;
37091 	duk_int_t key_count;  /* XXX: a "first" flag would suffice */
37092 	duk_uint8_t x;
37093 
37094 	DUK_DDD(DUK_DDDPRINT("parse_object"));
37095 
37096 	duk__json_dec_objarr_entry(js_ctx);
37097 
37098 	duk_push_object(thr);
37099 
37100 	/* Initial '{' has been checked and eaten by caller. */
37101 
37102 	key_count = 0;
37103 	for (;;) {
37104 		x = duk__json_dec_get_nonwhite(js_ctx);
37105 
37106 		DUK_DDD(DUK_DDDPRINT("parse_object: obj=%!T, x=%ld, key_count=%ld",
37107 		                     (duk_tval *) duk_get_tval(thr, -1),
37108 		                     (long) x, (long) key_count));
37109 
37110 		/* handle comma and closing brace */
37111 
37112 		if (x == DUK_ASC_COMMA && key_count > 0) {
37113 			/* accept comma, expect new value */
37114 			x = duk__json_dec_get_nonwhite(js_ctx);
37115 		} else if (x == DUK_ASC_RCURLY) {
37116 			/* eat closing brace */
37117 			break;
37118 		} else if (key_count == 0) {
37119 			/* accept anything, expect first value (EOF will be
37120 			 * caught by key parsing below.
37121 			 */
37122 			;
37123 		} else {
37124 			/* catches EOF (NUL) and initial comma */
37125 			goto syntax_error;
37126 		}
37127 
37128 		/* parse key and value */
37129 
37130 		if (x == DUK_ASC_DOUBLEQUOTE) {
37131 			duk__json_dec_string(js_ctx);
37132 #if defined(DUK_USE_JX)
37133 		} else if (js_ctx->flag_ext_custom &&
37134 		           duk_unicode_is_identifier_start((duk_codepoint_t) x)) {
37135 			duk__json_dec_plain_string(js_ctx);
37136 #endif
37137 		} else {
37138 			goto syntax_error;
37139 		}
37140 
37141 		/* [ ... obj key ] */
37142 
37143 		x = duk__json_dec_get_nonwhite(js_ctx);
37144 		if (x != DUK_ASC_COLON) {
37145 			goto syntax_error;
37146 		}
37147 
37148 		duk__json_dec_value(js_ctx);
37149 
37150 		/* [ ... obj key val ] */
37151 
37152 		duk_xdef_prop_wec(thr, -3);
37153 
37154 		/* [ ... obj ] */
37155 
37156 		key_count++;
37157 	}
37158 
37159 	/* [ ... obj ] */
37160 
37161 	DUK_DDD(DUK_DDDPRINT("parse_object: final object is %!T",
37162 	                     (duk_tval *) duk_get_tval(thr, -1)));
37163 
37164 	duk__json_dec_objarr_exit(js_ctx);
37165 	return;
37166 
37167  syntax_error:
37168 	duk__json_dec_syntax_error(js_ctx);
37169 	DUK_UNREACHABLE();
37170 }
37171 
duk__json_dec_array(duk_json_dec_ctx * js_ctx)37172 DUK_LOCAL void duk__json_dec_array(duk_json_dec_ctx *js_ctx) {
37173 	duk_hthread *thr = js_ctx->thr;
37174 	duk_uarridx_t arr_idx;
37175 	duk_uint8_t x;
37176 
37177 	DUK_DDD(DUK_DDDPRINT("parse_array"));
37178 
37179 	duk__json_dec_objarr_entry(js_ctx);
37180 
37181 	duk_push_array(thr);
37182 
37183 	/* Initial '[' has been checked and eaten by caller. */
37184 
37185 	arr_idx = 0;
37186 	for (;;) {
37187 		x = duk__json_dec_get_nonwhite(js_ctx);
37188 
37189 		DUK_DDD(DUK_DDDPRINT("parse_array: arr=%!T, x=%ld, arr_idx=%ld",
37190 		                     (duk_tval *) duk_get_tval(thr, -1),
37191 		                     (long) x, (long) arr_idx));
37192 
37193 		/* handle comma and closing bracket */
37194 
37195 		if ((x == DUK_ASC_COMMA) && (arr_idx != 0)) {
37196 			/* accept comma, expect new value */
37197 			;
37198 		} else if (x == DUK_ASC_RBRACKET) {
37199 			/* eat closing bracket */
37200 			break;
37201 		} else if (arr_idx == 0) {
37202 			/* accept anything, expect first value (EOF will be
37203 			 * caught by duk__json_dec_value() below.
37204 			 */
37205 			js_ctx->p--;  /* backtrack (safe) */
37206 		} else {
37207 			/* catches EOF (NUL) and initial comma */
37208 			goto syntax_error;
37209 		}
37210 
37211 		/* parse value */
37212 
37213 		duk__json_dec_value(js_ctx);
37214 
37215 		/* [ ... arr val ] */
37216 
37217 		duk_xdef_prop_index_wec(thr, -2, arr_idx);
37218 		arr_idx++;
37219 	}
37220 
37221 	/* Must set 'length' explicitly when using duk_xdef_prop_xxx() to
37222 	 * set the values.
37223 	 */
37224 
37225 	duk_set_length(thr, -1, arr_idx);
37226 
37227 	/* [ ... arr ] */
37228 
37229 	DUK_DDD(DUK_DDDPRINT("parse_array: final array is %!T",
37230 	                     (duk_tval *) duk_get_tval(thr, -1)));
37231 
37232 	duk__json_dec_objarr_exit(js_ctx);
37233 	return;
37234 
37235  syntax_error:
37236 	duk__json_dec_syntax_error(js_ctx);
37237 	DUK_UNREACHABLE();
37238 }
37239 
duk__json_dec_value(duk_json_dec_ctx * js_ctx)37240 DUK_LOCAL void duk__json_dec_value(duk_json_dec_ctx *js_ctx) {
37241 	duk_hthread *thr = js_ctx->thr;
37242 	duk_uint8_t x;
37243 
37244 	x = duk__json_dec_get_nonwhite(js_ctx);
37245 
37246 	DUK_DDD(DUK_DDDPRINT("parse_value: initial x=%ld", (long) x));
37247 
37248 	/* Note: duk__json_dec_req_stridx() backtracks one char */
37249 
37250 	if (x == DUK_ASC_DOUBLEQUOTE) {
37251 		duk__json_dec_string(js_ctx);
37252 	} else if ((x >= DUK_ASC_0 && x <= DUK_ASC_9) || (x == DUK_ASC_MINUS)) {
37253 #if defined(DUK_USE_JX)
37254 		if (js_ctx->flag_ext_custom && x == DUK_ASC_MINUS && duk__json_dec_peek(js_ctx) == DUK_ASC_UC_I) {
37255 			duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_MINUS_INFINITY);  /* "-Infinity", '-' has been eaten */
37256 			duk_push_number(thr, -DUK_DOUBLE_INFINITY);
37257 		} else {
37258 #else
37259 		{  /* unconditional block */
37260 #endif
37261 			/* We already ate 'x', so backup one byte. */
37262 			js_ctx->p--;  /* safe */
37263 			duk__json_dec_number(js_ctx);
37264 		}
37265 	} else if (x == DUK_ASC_LC_T) {
37266 		duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_TRUE);
37267 		duk_push_true(thr);
37268 	} else if (x == DUK_ASC_LC_F) {
37269 		duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_FALSE);
37270 		duk_push_false(thr);
37271 	} else if (x == DUK_ASC_LC_N) {
37272 		duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_LC_NULL);
37273 		duk_push_null(thr);
37274 #if defined(DUK_USE_JX)
37275 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_LC_U) {
37276 		duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_LC_UNDEFINED);
37277 		duk_push_undefined(thr);
37278 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_N) {
37279 		duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_NAN);
37280 		duk_push_nan(thr);
37281 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_I) {
37282 		duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_INFINITY);
37283 		duk_push_number(thr, DUK_DOUBLE_INFINITY);
37284 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_LPAREN) {
37285 		duk__json_dec_pointer(js_ctx);
37286 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_PIPE) {
37287 		duk__json_dec_buffer(js_ctx);
37288 #endif
37289 	} else if (x == DUK_ASC_LCURLY) {
37290 		duk__json_dec_object(js_ctx);
37291 	} else if (x == DUK_ASC_LBRACKET) {
37292 		duk__json_dec_array(js_ctx);
37293 	} else {
37294 		/* catches EOF (NUL) */
37295 		goto syntax_error;
37296 	}
37297 
37298 	duk__json_dec_eat_white(js_ctx);
37299 
37300 	/* [ ... val ] */
37301 	return;
37302 
37303  syntax_error:
37304 	duk__json_dec_syntax_error(js_ctx);
37305 	DUK_UNREACHABLE();
37306 }
37307 
37308 /* Recursive value reviver, implements the Walk() algorithm.  The parsing
37309  * step ensures there is a reasonable depth limit to the input.  However,
37310  * the reviver may create more depth by editing object or array entries, so
37311  * we have both C recursion limit and native stack checks here.
37312  */
37313 DUK_LOCAL void duk__json_dec_reviver_walk(duk_json_dec_ctx *js_ctx) {
37314 	duk_hthread *thr = js_ctx->thr;
37315 	duk_hobject *h;
37316 	duk_uarridx_t i, arr_len;
37317 
37318 	duk__json_dec_objarr_entry(js_ctx);
37319 
37320 	DUK_DDD(DUK_DDDPRINT("walk: top=%ld, holder=%!T, name=%!T",
37321 	                     (long) duk_get_top(thr),
37322 	                     (duk_tval *) duk_get_tval(thr, -2),
37323 	                     (duk_tval *) duk_get_tval(thr, -1)));
37324 
37325 	duk_dup_top(thr);
37326 	duk_get_prop(thr, -3);  /* -> [ ... holder name val ] */
37327 
37328 	h = duk_get_hobject(thr, -1);
37329 	if (h != NULL) {
37330 		if (duk_js_isarray_hobject(h)) {
37331 			arr_len = (duk_uarridx_t) duk_get_length(thr, -1);
37332 			for (i = 0; i < arr_len; i++) {
37333 				/* [ ... holder name val ] */
37334 
37335 				DUK_DDD(DUK_DDDPRINT("walk: array, top=%ld, i=%ld, arr_len=%ld, holder=%!T, name=%!T, val=%!T",
37336 				                     (long) duk_get_top(thr), (long) i, (long) arr_len,
37337 				                     (duk_tval *) duk_get_tval(thr, -3), (duk_tval *) duk_get_tval(thr, -2),
37338 				                     (duk_tval *) duk_get_tval(thr, -1)));
37339 
37340 				duk_dup_top(thr);
37341 				(void) duk_push_uint_to_hstring(thr, (duk_uint_t) i);  /* -> [ ... holder name val val ToString(i) ] */
37342 				duk__json_dec_reviver_walk(js_ctx);  /* -> [ ... holder name val new_elem ] */
37343 
37344 				if (duk_is_undefined(thr, -1)) {
37345 					duk_pop(thr);
37346 					duk_del_prop_index(thr, -1, i);
37347 				} else {
37348 					/* XXX: duk_xdef_prop_index_wec() would be more appropriate
37349 					 * here but it currently makes some assumptions that might
37350 					 * not hold (e.g. that previous property is not an accessor).
37351 					 */
37352 					duk_put_prop_index(thr, -2, i);
37353 				}
37354 			}
37355 		} else {
37356 			/* [ ... holder name val ] */
37357 			duk_enum(thr, -1, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/);
37358 			while (duk_next(thr, -1 /*enum_index*/, 0 /*get_value*/)) {
37359 				DUK_DDD(DUK_DDDPRINT("walk: object, top=%ld, holder=%!T, name=%!T, val=%!T, enum=%!iT, obj_key=%!T",
37360 				                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, -5),
37361 				                     (duk_tval *) duk_get_tval(thr, -4), (duk_tval *) duk_get_tval(thr, -3),
37362 				                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
37363 
37364 				/* [ ... holder name val enum obj_key ] */
37365 				duk_dup_m3(thr);
37366 				duk_dup_m2(thr);
37367 
37368 				/* [ ... holder name val enum obj_key val obj_key ] */
37369 				duk__json_dec_reviver_walk(js_ctx);
37370 
37371 				/* [ ... holder name val enum obj_key new_elem ] */
37372 				if (duk_is_undefined(thr, -1)) {
37373 					duk_pop(thr);
37374 					duk_del_prop(thr, -3);
37375 				} else {
37376 					/* XXX: duk_xdef_prop_index_wec() would be more appropriate
37377 					 * here but it currently makes some assumptions that might
37378 					 * not hold (e.g. that previous property is not an accessor).
37379 					 *
37380 					 * Using duk_put_prop() works incorrectly with '__proto__'
37381 					 * if the own property with that name has been deleted.  This
37382 					 * does not happen normally, but a clever reviver can trigger
37383 					 * that, see complex reviver case in: test-bug-json-parse-__proto__.js.
37384 					 */
37385 					duk_put_prop(thr, -4);
37386 				}
37387 			}
37388 			duk_pop(thr);  /* pop enum */
37389 		}
37390 	}
37391 
37392 	/* [ ... holder name val ] */
37393 
37394 	duk_dup(thr, js_ctx->idx_reviver);
37395 	duk_insert(thr, -4);  /* -> [ ... reviver holder name val ] */
37396 	duk_call_method(thr, 2);  /* -> [ ... res ] */
37397 
37398 	duk__json_dec_objarr_exit(js_ctx);
37399 
37400 	DUK_DDD(DUK_DDDPRINT("walk: top=%ld, result=%!T",
37401 	                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, -1)));
37402 }
37403 
37404 /*
37405  *  Stringify implementation.
37406  */
37407 
37408 #define DUK__EMIT_1(js_ctx,ch)          duk__emit_1((js_ctx), (duk_uint_fast8_t) (ch))
37409 #define DUK__EMIT_2(js_ctx,ch1,ch2)     duk__emit_2((js_ctx), (duk_uint_fast8_t) (ch1), (duk_uint_fast8_t) (ch2))
37410 #define DUK__EMIT_HSTR(js_ctx,h)        duk__emit_hstring((js_ctx), (h))
37411 #if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC)
37412 #define DUK__EMIT_CSTR(js_ctx,p)        duk__emit_cstring((js_ctx), (p))
37413 #endif
37414 #define DUK__EMIT_STRIDX(js_ctx,i)      duk__emit_stridx((js_ctx), (i))
37415 #define DUK__UNEMIT_1(js_ctx)           duk__unemit_1((js_ctx))
37416 
37417 DUK_LOCAL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch) {
37418 	DUK_BW_WRITE_ENSURE_U8(js_ctx->thr, &js_ctx->bw, ch);
37419 }
37420 
37421 DUK_LOCAL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2) {
37422 	DUK_BW_WRITE_ENSURE_U8_2(js_ctx->thr, &js_ctx->bw, ch1, ch2);
37423 }
37424 
37425 DUK_LOCAL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h) {
37426 	DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h);
37427 }
37428 
37429 #if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC)
37430 DUK_LOCAL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *str) {
37431 	DUK_BW_WRITE_ENSURE_CSTRING(js_ctx->thr, &js_ctx->bw, str);
37432 }
37433 #endif
37434 
37435 DUK_LOCAL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx) {
37436 	duk_hstring *h;
37437 
37438 	DUK_ASSERT_STRIDX_VALID(stridx);
37439 	h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx);
37440 	DUK_ASSERT(h != NULL);
37441 
37442 	DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h);
37443 }
37444 
37445 DUK_LOCAL void duk__unemit_1(duk_json_enc_ctx *js_ctx) {
37446 	DUK_ASSERT(DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw) >= 1);
37447 	DUK_BW_ADD_PTR(js_ctx->thr, &js_ctx->bw, -1);
37448 }
37449 
37450 #define DUK__MKESC(nybbles,esc1,esc2)  \
37451 	(((duk_uint_fast32_t) (nybbles)) << 16) | \
37452 	(((duk_uint_fast32_t) (esc1)) << 8) | \
37453 	((duk_uint_fast32_t) (esc2))
37454 
37455 DUK_LOCAL duk_uint8_t *duk__emit_esc_auto_fast(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp, duk_uint8_t *q) {
37456 	duk_uint_fast32_t tmp;
37457 	duk_small_uint_t dig;
37458 
37459 	DUK_UNREF(js_ctx);
37460 
37461 	/* Caller ensures space for at least DUK__JSON_MAX_ESC_LEN. */
37462 
37463 	/* Select appropriate escape format automatically, and set 'tmp' to a
37464 	 * value encoding both the escape format character and the nybble count:
37465 	 *
37466 	 *   (nybble_count << 16) | (escape_char1) | (escape_char2)
37467 	 */
37468 
37469 #if defined(DUK_USE_JX)
37470 	if (DUK_LIKELY(cp < 0x100UL)) {
37471 		if (DUK_UNLIKELY(js_ctx->flag_ext_custom != 0U)) {
37472 			tmp = DUK__MKESC(2, DUK_ASC_BACKSLASH, DUK_ASC_LC_X);
37473 		} else {
37474 			tmp = DUK__MKESC(4, DUK_ASC_BACKSLASH, DUK_ASC_LC_U);
37475 		}
37476 	} else
37477 #endif
37478 	if (DUK_LIKELY(cp < 0x10000UL)) {
37479 		tmp = DUK__MKESC(4, DUK_ASC_BACKSLASH, DUK_ASC_LC_U);
37480 	} else {
37481 #if defined(DUK_USE_JX)
37482 		if (DUK_LIKELY(js_ctx->flag_ext_custom != 0U)) {
37483 			tmp = DUK__MKESC(8, DUK_ASC_BACKSLASH, DUK_ASC_UC_U);
37484 		} else
37485 #endif
37486 		{
37487 			/* In compatible mode and standard JSON mode, output
37488 			 * something useful for non-BMP characters.  This won't
37489 			 * roundtrip but will still be more or less readable and
37490 			 * more useful than an error.
37491 			 */
37492 			tmp = DUK__MKESC(8, DUK_ASC_UC_U, DUK_ASC_PLUS);
37493 		}
37494 	}
37495 
37496 	*q++ = (duk_uint8_t) ((tmp >> 8) & 0xff);
37497 	*q++ = (duk_uint8_t) (tmp & 0xff);
37498 
37499 	tmp = tmp >> 16;
37500 	while (tmp > 0) {
37501 		tmp--;
37502 		dig = (duk_small_uint_t) ((cp >> (4 * tmp)) & 0x0f);
37503 		*q++ = duk_lc_digits[dig];
37504 	}
37505 
37506 	return q;
37507 }
37508 
37509 DUK_LOCAL void duk__json_enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k) {
37510 	const duk_int8_t *p, *p_start, *p_end;  /* Note: intentionally signed. */
37511 	duk_size_t k_len;
37512 	duk_codepoint_t cp;
37513 
37514 	DUK_ASSERT(k != NULL);
37515 
37516 	/* Accept ASCII strings which conform to identifier requirements
37517 	 * as being emitted without key quotes.  Since we only accept ASCII
37518 	 * there's no need for actual decoding: 'p' is intentionally signed
37519 	 * so that bytes >= 0x80 extend to negative values and are rejected
37520 	 * as invalid identifier codepoints.
37521 	 */
37522 
37523 	if (js_ctx->flag_avoid_key_quotes) {
37524 		k_len = DUK_HSTRING_GET_BYTELEN(k);
37525 		p_start = (const duk_int8_t *) DUK_HSTRING_GET_DATA(k);
37526 		p_end = p_start + k_len;
37527 		p = p_start;
37528 
37529 		if (p == p_end) {
37530 			/* Zero length string is not accepted without quotes */
37531 			goto quote_normally;
37532 		}
37533 		cp = (duk_codepoint_t) (*p++);
37534 		if (DUK_UNLIKELY(!duk_unicode_is_identifier_start(cp))) {
37535 			goto quote_normally;
37536 		}
37537 		while (p < p_end) {
37538 			cp = (duk_codepoint_t) (*p++);
37539 			if (DUK_UNLIKELY(!duk_unicode_is_identifier_part(cp))) {
37540 				goto quote_normally;
37541 			}
37542 		}
37543 
37544 		/* This seems faster than emitting bytes one at a time and
37545 		 * then potentially rewinding.
37546 		 */
37547 		DUK__EMIT_HSTR(js_ctx, k);
37548 		return;
37549 	}
37550 
37551  quote_normally:
37552 	duk__json_enc_quote_string(js_ctx, k);
37553 }
37554 
37555 /* The Quote(value) operation: quote a string.
37556  *
37557  * Stack policy: [ ] -> [ ].
37558  */
37559 
37560 DUK_LOCAL void duk__json_enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str) {
37561 	duk_hthread *thr = js_ctx->thr;
37562 	const duk_uint8_t *p, *p_start, *p_end, *p_now, *p_tmp;
37563 	duk_uint8_t *q;
37564 	duk_ucodepoint_t cp;  /* typed for duk_unicode_decode_xutf8() */
37565 
37566 	DUK_DDD(DUK_DDDPRINT("duk__json_enc_quote_string: h_str=%!O", (duk_heaphdr *) h_str));
37567 
37568 	DUK_ASSERT(h_str != NULL);
37569 	p_start = DUK_HSTRING_GET_DATA(h_str);
37570 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_str);
37571 	p = p_start;
37572 
37573 	DUK__EMIT_1(js_ctx, DUK_ASC_DOUBLEQUOTE);
37574 
37575 	/* Encode string in small chunks, estimating the maximum expansion so that
37576 	 * there's no need to ensure space while processing the chunk.
37577 	 */
37578 
37579 	while (p < p_end) {
37580 		duk_size_t left, now, space;
37581 
37582 		left = (duk_size_t) (p_end - p);
37583 		now = (left > DUK__JSON_ENCSTR_CHUNKSIZE ?
37584 		       DUK__JSON_ENCSTR_CHUNKSIZE : left);
37585 
37586 		/* Maximum expansion per input byte is 6:
37587 		 *   - invalid UTF-8 byte causes "\uXXXX" to be emitted (6/1 = 6).
37588 		 *   - 2-byte UTF-8 encodes as "\uXXXX" (6/2 = 3).
37589 		 *   - 4-byte UTF-8 encodes as "\Uxxxxxxxx" (10/4 = 2.5).
37590 		 */
37591 		space = now * 6;
37592 		q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);
37593 
37594 		p_now = p + now;
37595 
37596 		while (p < p_now) {
37597 #if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH)
37598 			duk_uint8_t b;
37599 
37600 			b = duk__json_quotestr_lookup[*p++];
37601 			if (DUK_LIKELY(b < 0x80)) {
37602 				/* Most input bytes go through here. */
37603 				*q++ = b;
37604 			} else if (b >= 0xa0) {
37605 				*q++ = DUK_ASC_BACKSLASH;
37606 				*q++ = (duk_uint8_t) (b - 0x80);
37607 			} else if (b == 0x80) {
37608 				cp = (duk_ucodepoint_t) (*(p - 1));
37609 				q = duk__emit_esc_auto_fast(js_ctx, cp, q);
37610 			} else if (b == 0x7f && js_ctx->flag_ascii_only) {
37611 				/* 0x7F is special */
37612 				DUK_ASSERT(b == 0x81);
37613 				cp = (duk_ucodepoint_t) 0x7f;
37614 				q = duk__emit_esc_auto_fast(js_ctx, cp, q);
37615 			} else {
37616 				DUK_ASSERT(b == 0x81);
37617 				p--;
37618 
37619 				/* slow path is shared */
37620 #else  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
37621 			cp = *p;
37622 
37623 			if (DUK_LIKELY(cp <= 0x7f)) {
37624 				/* ascii fast path: avoid decoding utf-8 */
37625 				p++;
37626 				if (cp == 0x22 || cp == 0x5c) {
37627 					/* double quote or backslash */
37628 					*q++ = DUK_ASC_BACKSLASH;
37629 					*q++ = (duk_uint8_t) cp;
37630 				} else if (cp < 0x20) {
37631 					duk_uint_fast8_t esc_char;
37632 
37633 					/* This approach is a bit shorter than a straight
37634 					 * if-else-ladder and also a bit faster.
37635 					 */
37636 					if (cp < (sizeof(duk__json_quotestr_esc) / sizeof(duk_uint8_t)) &&
37637 					    (esc_char = duk__json_quotestr_esc[cp]) != 0) {
37638 						*q++ = DUK_ASC_BACKSLASH;
37639 						*q++ = (duk_uint8_t) esc_char;
37640 					} else {
37641 						q = duk__emit_esc_auto_fast(js_ctx, cp, q);
37642 					}
37643 				} else if (cp == 0x7f && js_ctx->flag_ascii_only) {
37644 					q = duk__emit_esc_auto_fast(js_ctx, cp, q);
37645 				} else {
37646 					/* any other printable -> as is */
37647 					*q++ = (duk_uint8_t) cp;
37648 				}
37649 			} else {
37650 				/* slow path is shared */
37651 #endif  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
37652 
37653 				/* slow path decode */
37654 
37655 				/* If XUTF-8 decoding fails, treat the offending byte as a codepoint directly
37656 				 * and go forward one byte.  This is of course very lossy, but allows some kind
37657 				 * of output to be produced even for internal strings which don't conform to
37658 				 * XUTF-8.  All standard ECMAScript strings are always CESU-8, so this behavior
37659 				 * does not violate the ECMAScript specification.  The behavior is applied to
37660 				 * all modes, including ECMAScript standard JSON.  Because the current XUTF-8
37661 				 * decoding is not very strict, this behavior only really affects initial bytes
37662 				 * and truncated codepoints.
37663 				 *
37664 				 * Another alternative would be to scan forwards to start of next codepoint
37665 				 * (or end of input) and emit just one replacement codepoint.
37666 				 */
37667 
37668 				p_tmp = p;
37669 				if (!duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {
37670 					/* Decode failed. */
37671 					cp = *p_tmp;
37672 					p = p_tmp + 1;
37673 				}
37674 
37675 #if defined(DUK_USE_NONSTD_JSON_ESC_U2028_U2029)
37676 				if (js_ctx->flag_ascii_only || cp == 0x2028 || cp == 0x2029) {
37677 #else
37678 				if (js_ctx->flag_ascii_only) {
37679 #endif
37680 					q = duk__emit_esc_auto_fast(js_ctx, cp, q);
37681 				} else {
37682 					/* as is */
37683 					DUK_RAW_WRITEINC_XUTF8(q, cp);
37684 				}
37685 			}
37686 		}
37687 
37688 		DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
37689 	}
37690 
37691 	DUK__EMIT_1(js_ctx, DUK_ASC_DOUBLEQUOTE);
37692 }
37693 
37694 /* Encode a double (checked by caller) from stack top.  Stack top may be
37695  * replaced by serialized string but is not popped (caller does that).
37696  */
37697 DUK_LOCAL void duk__json_enc_double(duk_json_enc_ctx *js_ctx) {
37698 	duk_hthread *thr;
37699 	duk_tval *tv;
37700 	duk_double_t d;
37701 	duk_small_int_t c;
37702 	duk_small_int_t s;
37703 	duk_small_uint_t stridx;
37704 	duk_small_uint_t n2s_flags;
37705 	duk_hstring *h_str;
37706 
37707 	DUK_ASSERT(js_ctx != NULL);
37708 	thr = js_ctx->thr;
37709 	DUK_ASSERT(thr != NULL);
37710 
37711 	/* Caller must ensure 'tv' is indeed a double and not a fastint! */
37712 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
37713 	DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
37714 	d = DUK_TVAL_GET_DOUBLE(tv);
37715 
37716 	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
37717 	s = (duk_small_int_t) DUK_SIGNBIT(d);
37718 	DUK_UNREF(s);
37719 
37720 	if (DUK_LIKELY(!(c == DUK_FP_INFINITE || c == DUK_FP_NAN))) {
37721 		DUK_ASSERT(DUK_ISFINITE(d));
37722 
37723 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
37724 		/* Negative zero needs special handling in JX/JC because
37725 		 * it would otherwise serialize to '0', not '-0'.
37726 		 */
37727 		if (DUK_UNLIKELY(c == DUK_FP_ZERO && s != 0 &&
37728 		                 (js_ctx->flag_ext_custom_or_compatible))) {
37729 			duk_push_hstring_stridx(thr, DUK_STRIDX_MINUS_ZERO);  /* '-0' */
37730 		} else
37731 #endif  /* DUK_USE_JX || DUK_USE_JC */
37732 		{
37733 			n2s_flags = 0;
37734 			/* [ ... number ] -> [ ... string ] */
37735 			duk_numconv_stringify(thr, 10 /*radix*/, 0 /*digits*/, n2s_flags);
37736 		}
37737 		h_str = duk_known_hstring(thr, -1);
37738 		DUK__EMIT_HSTR(js_ctx, h_str);
37739 		return;
37740 	}
37741 
37742 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
37743 	if (!(js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
37744 	                       DUK_JSON_FLAG_EXT_COMPATIBLE))) {
37745 		stridx = DUK_STRIDX_LC_NULL;
37746 	} else if (c == DUK_FP_NAN) {
37747 		stridx = js_ctx->stridx_custom_nan;
37748 	} else if (s == 0) {
37749 		stridx = js_ctx->stridx_custom_posinf;
37750 	} else {
37751 		stridx = js_ctx->stridx_custom_neginf;
37752 	}
37753 #else
37754 	stridx = DUK_STRIDX_LC_NULL;
37755 #endif
37756 	DUK__EMIT_STRIDX(js_ctx, stridx);
37757 }
37758 
37759 #if defined(DUK_USE_FASTINT)
37760 /* Encode a fastint from duk_tval ptr, no value stack effects. */
37761 DUK_LOCAL void duk__json_enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
37762 	duk_int64_t v;
37763 
37764 	/* Fastint range is signed 48-bit so longest value is -2^47 = -140737488355328
37765 	 * (16 chars long), longest signed 64-bit value is -2^63 = -9223372036854775808
37766 	 * (20 chars long).  Alloc space for 64-bit range to be safe.
37767 	 */
37768 	duk_uint8_t buf[20 + 1];
37769 
37770 	/* Caller must ensure 'tv' is indeed a fastint! */
37771 	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
37772 	v = DUK_TVAL_GET_FASTINT(tv);
37773 
37774 	/* XXX: There are no format strings in duk_config.h yet, could add
37775 	 * one for formatting duk_int64_t.  For now, assumes "%lld" and that
37776 	 * "long long" type exists.  Could also rely on C99 directly but that
37777 	 * won't work for older MSVC.
37778 	 */
37779 	DUK_SPRINTF((char *) buf, "%lld", (long long) v);
37780 	DUK__EMIT_CSTR(js_ctx, (const char *) buf);
37781 }
37782 #endif
37783 
37784 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
37785 #if defined(DUK_USE_HEX_FASTPATH)
37786 DUK_LOCAL duk_uint8_t *duk__json_enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
37787 	duk_uint8_t *q;
37788 	duk_uint16_t *q16;
37789 	duk_small_uint_t x;
37790 	duk_size_t i, len_safe;
37791 #if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
37792 	duk_bool_t shift_dst;
37793 #endif
37794 
37795 	/* Unlike in duk_hex_encode() 'dst' is not necessarily aligned by 2.
37796 	 * For platforms where unaligned accesses are not allowed, shift 'dst'
37797 	 * ahead by 1 byte to get alignment and then duk_memmove() the result
37798 	 * in place.  The faster encoding loop makes up the difference.
37799 	 * There's always space for one extra byte because a terminator always
37800 	 * follows the hex data and that's been accounted for by the caller.
37801 	 */
37802 
37803 #if defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
37804 	q16 = (duk_uint16_t *) (void *) dst;
37805 #else
37806 	shift_dst = (duk_bool_t) (((duk_size_t) dst) & 0x01U);
37807 	if (shift_dst) {
37808 		DUK_DD(DUK_DDPRINT("unaligned accesses not possible, dst not aligned -> step to dst + 1"));
37809 		q16 = (duk_uint16_t *) (void *) (dst + 1);
37810 	} else {
37811 		DUK_DD(DUK_DDPRINT("unaligned accesses not possible, dst is aligned"));
37812 		q16 = (duk_uint16_t *) (void *) dst;
37813 	}
37814 	DUK_ASSERT((((duk_size_t) q16) & 0x01U) == 0);
37815 #endif
37816 
37817 	len_safe = src_len & ~0x03U;
37818 	for (i = 0; i < len_safe; i += 4) {
37819 		q16[0] = duk_hex_enctab[src[i]];
37820 		q16[1] = duk_hex_enctab[src[i + 1]];
37821 		q16[2] = duk_hex_enctab[src[i + 2]];
37822 		q16[3] = duk_hex_enctab[src[i + 3]];
37823 		q16 += 4;
37824 	}
37825 	q = (duk_uint8_t *) q16;
37826 
37827 #if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
37828 	if (shift_dst) {
37829 		q--;
37830 		duk_memmove((void *) dst, (const void *) (dst + 1), 2 * len_safe);
37831 		DUK_ASSERT(dst + 2 * len_safe == q);
37832 	}
37833 #endif
37834 
37835 	for (; i < src_len; i++) {
37836 		x = src[i];
37837 		*q++ = duk_lc_digits[x >> 4];
37838 		*q++ = duk_lc_digits[x & 0x0f];
37839 	}
37840 
37841 	return q;
37842 }
37843 #else  /* DUK_USE_HEX_FASTPATH */
37844 DUK_LOCAL duk_uint8_t *duk__json_enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
37845 	const duk_uint8_t *p;
37846 	const duk_uint8_t *p_end;
37847 	duk_uint8_t *q;
37848 	duk_small_uint_t x;
37849 
37850 	p = src;
37851 	p_end = src + src_len;
37852 	q = dst;
37853 	while (p != p_end) {
37854 		x = *p++;
37855 		*q++ = duk_lc_digits[x >> 4];
37856 		*q++ = duk_lc_digits[x & 0x0f];
37857 	}
37858 
37859 	return q;
37860 }
37861 #endif  /* DUK_USE_HEX_FASTPATH */
37862 
37863 DUK_LOCAL void duk__json_enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_data, duk_size_t buf_len) {
37864 	duk_hthread *thr;
37865 	duk_uint8_t *q;
37866 	duk_size_t space;
37867 
37868 	thr = js_ctx->thr;
37869 
37870 	DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);  /* caller checks */
37871 	DUK_ASSERT(js_ctx->flag_ext_custom_or_compatible);
37872 
37873 	/* Buffer values are encoded in (lowercase) hex to make the
37874 	 * binary data readable.  Base64 or similar would be more
37875 	 * compact but less readable, and the point of JX/JC
37876 	 * variants is to be as useful to a programmer as possible.
37877 	 */
37878 
37879 	/* The #if defined() clutter here needs to handle the three
37880 	 * cases: (1) JX+JC, (2) JX only, (3) JC only.
37881 	 */
37882 
37883 	/* Note: space must cater for both JX and JC. */
37884 	space = 9 + buf_len * 2 + 2;
37885 	DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7ffffffeUL);
37886 	DUK_ASSERT((space - 2) / 2 >= buf_len);  /* overflow not possible, buffer limits */
37887 	q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);
37888 
37889 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
37890 	if (js_ctx->flag_ext_custom)
37891 #endif
37892 #if defined(DUK_USE_JX)
37893 	{
37894 		*q++ = DUK_ASC_PIPE;
37895 		q = duk__json_enc_buffer_data_hex(buf_data, buf_len, q);
37896 		*q++ = DUK_ASC_PIPE;
37897 
37898 	}
37899 #endif
37900 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
37901 	else
37902 #endif
37903 #if defined(DUK_USE_JC)
37904 	{
37905 		DUK_ASSERT(js_ctx->flag_ext_compatible);
37906 		duk_memcpy((void *) q, (const void *) "{\"_buf\":\"", 9);  /* len: 9 */
37907 		q += 9;
37908 		q = duk__json_enc_buffer_data_hex(buf_data, buf_len, q);
37909 		*q++ = DUK_ASC_DOUBLEQUOTE;
37910 		*q++ = DUK_ASC_RCURLY;
37911 	}
37912 #endif
37913 
37914 	DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
37915 }
37916 
37917 DUK_LOCAL void duk__json_enc_buffer_jx_jc(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) {
37918 	duk__json_enc_buffer_data(js_ctx,
37919 	                     (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h),
37920 	                     (duk_size_t) DUK_HBUFFER_GET_SIZE(h));
37921 }
37922 #endif  /* DUK_USE_JX || DUK_USE_JC */
37923 
37924 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
37925 DUK_LOCAL void duk__json_enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) {
37926 	duk_size_t i, n;
37927 	const duk_uint8_t *buf;
37928 	duk_uint8_t *q;
37929 
37930 	n = DUK_HBUFFER_GET_SIZE(h);
37931 	if (n == 0) {
37932 		DUK__EMIT_2(js_ctx, DUK_ASC_LCURLY, DUK_ASC_RCURLY);
37933 		return;
37934 	}
37935 
37936 	DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
37937 
37938 	/* Maximum encoded length with 32-bit index: 1 + 10 + 2 + 3 + 1 + 1 = 18,
37939 	 * with 64-bit index: 1 + 20 + 2 + 3 + 1 + 1 = 28.  32 has some slack.
37940 	 *
37941 	 * Note that because the output buffer is reallocated from time to time,
37942 	 * side effects (such as finalizers) affecting the buffer 'h' must be
37943 	 * disabled.  This is the case in the JSON.stringify() fast path.
37944 	 */
37945 
37946 	buf = (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h);
37947 	if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
37948 		for (i = 0; i < n; i++) {
37949 			duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth + 1);
37950 			q = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, 32);
37951 			q += DUK_SPRINTF((char *) q, "\"%lu\": %u,", (unsigned long) i, (unsigned int) buf[i]);
37952 			DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, q);
37953 		}
37954 	} else {
37955 		q = DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw);
37956 		for (i = 0; i < n; i++) {
37957 			q = DUK_BW_ENSURE_RAW(js_ctx->thr, &js_ctx->bw, 32, q);
37958 			q += DUK_SPRINTF((char *) q, "\"%lu\":%u,", (unsigned long) i, (unsigned int) buf[i]);
37959 		}
37960 		DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, q);
37961 	}
37962 	DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
37963 
37964 	if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
37965 		duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth);
37966 	}
37967 	DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
37968 }
37969 #endif  /* DUK_USE_JSON_STRINGIFY_FASTPATH */
37970 
37971 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
37972 DUK_LOCAL void duk__json_enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) {
37973 	char buf[64];  /* XXX: how to figure correct size? */
37974 	const char *fmt;
37975 
37976 	DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);  /* caller checks */
37977 	DUK_ASSERT(js_ctx->flag_ext_custom_or_compatible);
37978 
37979 	duk_memzero(buf, sizeof(buf));
37980 
37981 	/* The #if defined() clutter here needs to handle the three
37982 	 * cases: (1) JX+JC, (2) JX only, (3) JC only.
37983 	 */
37984 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
37985 	if (js_ctx->flag_ext_custom)
37986 #endif
37987 #if defined(DUK_USE_JX)
37988 	{
37989 		fmt = ptr ? "(%p)" : "(null)";
37990 	}
37991 #endif
37992 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
37993 	else
37994 #endif
37995 #if defined(DUK_USE_JC)
37996 	{
37997 		DUK_ASSERT(js_ctx->flag_ext_compatible);
37998 		fmt = ptr ? "{\"_ptr\":\"%p\"}" : "{\"_ptr\":\"null\"}";
37999 	}
38000 #endif
38001 
38002 	/* When ptr == NULL, the format argument is unused. */
38003 	DUK_SNPRINTF(buf, sizeof(buf) - 1, fmt, ptr);  /* must not truncate */
38004 	DUK__EMIT_CSTR(js_ctx, buf);
38005 }
38006 #endif  /* DUK_USE_JX || DUK_USE_JC */
38007 
38008 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
38009 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
38010 DUK_LOCAL void duk__json_enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj) {
38011 	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
38012 
38013 	if (h_bufobj->buf == NULL || !DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
38014 		DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
38015 	} else {
38016 		/* Handle both full and partial slice (as long as covered). */
38017 		duk__json_enc_buffer_data(js_ctx,
38018 		                     (duk_uint8_t *) DUK_HBUFOBJ_GET_SLICE_BASE(js_ctx->thr->heap, h_bufobj),
38019 		                     (duk_size_t) h_bufobj->length);
38020 	}
38021 }
38022 #endif  /* DUK_USE_JX || DUK_USE_JC */
38023 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
38024 
38025 /* Indent helper.  Calling code relies on js_ctx->recursion_depth also being
38026  * directly related to indent depth.
38027  */
38028 #if defined(DUK_USE_PREFER_SIZE)
38029 DUK_LOCAL void duk__json_enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth) {
38030 	DUK_ASSERT(js_ctx->h_gap != NULL);
38031 	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0);  /* caller guarantees */
38032 
38033 	DUK__EMIT_1(js_ctx, 0x0a);
38034 	while (depth-- > 0) {
38035 		DUK__EMIT_HSTR(js_ctx, js_ctx->h_gap);
38036 	}
38037 }
38038 #else  /* DUK_USE_PREFER_SIZE */
38039 DUK_LOCAL void duk__json_enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth) {
38040 	const duk_uint8_t *gap_data;
38041 	duk_size_t gap_len;
38042 	duk_size_t avail_bytes;   /* bytes of indent available for copying */
38043 	duk_size_t need_bytes;    /* bytes of indent still needed */
38044 	duk_uint8_t *p_start;
38045 	duk_uint8_t *p;
38046 
38047 	DUK_ASSERT(js_ctx->h_gap != NULL);
38048 	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0);  /* caller guarantees */
38049 
38050 	DUK__EMIT_1(js_ctx, 0x0a);
38051 	if (DUK_UNLIKELY(depth == 0)) {
38052 		return;
38053 	}
38054 
38055 	/* To handle deeper indents efficiently, make use of copies we've
38056 	 * already emitted.  In effect we can emit a sequence of 1, 2, 4,
38057 	 * 8, etc copies, and then finish the last run.  Byte counters
38058 	 * avoid multiply with gap_len on every loop.
38059 	 */
38060 
38061 	gap_data = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(js_ctx->h_gap);
38062 	gap_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap);
38063 	DUK_ASSERT(gap_len > 0);
38064 
38065 	need_bytes = gap_len * depth;
38066 	p = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, need_bytes);
38067 	p_start = p;
38068 
38069 	duk_memcpy((void *) p, (const void *) gap_data, (size_t) gap_len);
38070 	p += gap_len;
38071 	avail_bytes = gap_len;
38072 	DUK_ASSERT(need_bytes >= gap_len);
38073 	need_bytes -= gap_len;
38074 
38075 	while (need_bytes >= avail_bytes) {
38076 		duk_memcpy((void *) p, (const void *) p_start, (size_t) avail_bytes);
38077 		p += avail_bytes;
38078 		need_bytes -= avail_bytes;
38079 		avail_bytes <<= 1;
38080 	}
38081 
38082 	DUK_ASSERT(need_bytes < avail_bytes);  /* need_bytes may be zero */
38083 	duk_memcpy((void *) p, (const void *) p_start, (size_t) need_bytes);
38084 	p += need_bytes;
38085 	/*avail_bytes += need_bytes*/
38086 
38087 	DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, p);
38088 }
38089 #endif  /* DUK_USE_PREFER_SIZE */
38090 
38091 /* Shared entry handling for object/array serialization. */
38092 DUK_LOCAL void duk__json_enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
38093 	duk_hthread *thr = js_ctx->thr;
38094 	duk_hobject *h_target;
38095 	duk_uint_fast32_t i, n;
38096 
38097 	*entry_top = duk_get_top(thr);
38098 
38099 	duk_native_stack_check(thr);
38100 	duk_require_stack(thr, DUK_JSON_ENC_REQSTACK);
38101 
38102 	/* Loop check using a hybrid approach: a fixed-size visited[] array
38103 	 * with overflow in a loop check object.
38104 	 */
38105 
38106 	h_target = duk_known_hobject(thr, -1);  /* object or array */
38107 
38108 	n = js_ctx->recursion_depth;
38109 	if (DUK_UNLIKELY(n > DUK_JSON_ENC_LOOPARRAY)) {
38110 		n = DUK_JSON_ENC_LOOPARRAY;
38111 	}
38112 	for (i = 0; i < n; i++) {
38113 		if (DUK_UNLIKELY(js_ctx->visiting[i] == h_target)) {
38114 			DUK_DD(DUK_DDPRINT("slow path loop detect"));
38115 			DUK_ERROR_TYPE(thr, DUK_STR_CYCLIC_INPUT);
38116 			DUK_WO_NORETURN(return;);
38117 		}
38118 	}
38119 	if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) {
38120 		js_ctx->visiting[js_ctx->recursion_depth] = h_target;
38121 	} else {
38122 		duk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) h_target);
38123 		duk_dup_top(thr);  /* -> [ ... voidp voidp ] */
38124 		if (duk_has_prop(thr, js_ctx->idx_loop)) {
38125 			DUK_ERROR_TYPE(thr, DUK_STR_CYCLIC_INPUT);
38126 			DUK_WO_NORETURN(return;);
38127 		}
38128 		duk_push_true(thr);  /* -> [ ... voidp true ] */
38129 		duk_put_prop(thr, js_ctx->idx_loop);  /* -> [ ... ] */
38130 	}
38131 
38132 	/* C recursion check. */
38133 
38134 	DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0);  /* unsigned */
38135 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
38136 	if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
38137 		DUK_ERROR_RANGE(thr, DUK_STR_ENC_RECLIMIT);
38138 		DUK_WO_NORETURN(return;);
38139 	}
38140 	js_ctx->recursion_depth++;
38141 
38142 	DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
38143 	                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop)));
38144 }
38145 
38146 /* Shared exit handling for object/array serialization. */
38147 DUK_LOCAL void duk__json_enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
38148 	duk_hthread *thr = js_ctx->thr;
38149 	duk_hobject *h_target;
38150 
38151 	/* C recursion check. */
38152 
38153 	DUK_ASSERT(js_ctx->recursion_depth > 0);
38154 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
38155 	js_ctx->recursion_depth--;
38156 
38157 	/* Loop check. */
38158 
38159 	h_target = duk_known_hobject(thr, *entry_top - 1);  /* original target at entry_top - 1 */
38160 
38161 	if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) {
38162 		/* Previous entry was inside visited[], nothing to do. */
38163 	} else {
38164 		duk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) h_target);
38165 		duk_del_prop(thr, js_ctx->idx_loop);  /* -> [ ... ] */
38166 	}
38167 
38168 	/* Restore stack top after unbalanced code paths. */
38169 	duk_set_top(thr, *entry_top);
38170 
38171 	DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
38172 	                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop)));
38173 }
38174 
38175 /* The JO(value) operation: encode object.
38176  *
38177  * Stack policy: [ object ] -> [ object ].
38178  */
38179 DUK_LOCAL void duk__json_enc_object(duk_json_enc_ctx *js_ctx) {
38180 	duk_hthread *thr = js_ctx->thr;
38181 	duk_hstring *h_key;
38182 	duk_idx_t entry_top;
38183 	duk_idx_t idx_obj;
38184 	duk_idx_t idx_keys;
38185 	duk_bool_t emitted;
38186 	duk_uarridx_t arr_len, i;
38187 	duk_size_t prev_size;
38188 
38189 	DUK_DDD(DUK_DDDPRINT("duk__json_enc_object: obj=%!T", (duk_tval *) duk_get_tval(thr, -1)));
38190 
38191 	duk__json_enc_objarr_entry(js_ctx, &entry_top);
38192 
38193 	idx_obj = entry_top - 1;
38194 
38195 	if (js_ctx->idx_proplist >= 0) {
38196 		idx_keys = js_ctx->idx_proplist;
38197 	} else {
38198 		/* XXX: would be nice to enumerate an object at specified index */
38199 		duk_dup(thr, idx_obj);
38200 		(void) duk_hobject_get_enumerated_keys(thr, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/);  /* [ ... target ] -> [ ... target keys ] */
38201 		idx_keys = duk_require_normalize_index(thr, -1);
38202 		/* leave stack unbalanced on purpose */
38203 	}
38204 
38205 	DUK_DDD(DUK_DDDPRINT("idx_keys=%ld, h_keys=%!T",
38206 	                     (long) idx_keys, (duk_tval *) duk_get_tval(thr, idx_keys)));
38207 
38208 	/* Steps 8-10 have been merged to avoid a "partial" variable. */
38209 
38210 	DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
38211 
38212 	/* XXX: keys is an internal object with all keys to be processed
38213 	 * in its (gapless) array part.  Because nobody can touch the keys
38214 	 * object, we could iterate its array part directly (keeping in mind
38215 	 * that it can be reallocated).
38216 	 */
38217 
38218 	arr_len = (duk_uarridx_t) duk_get_length(thr, idx_keys);
38219 	emitted = 0;
38220 	for (i = 0; i < arr_len; i++) {
38221 		duk_get_prop_index(thr, idx_keys, i);  /* -> [ ... key ] */
38222 
38223 		DUK_DDD(DUK_DDDPRINT("object property loop: holder=%!T, key=%!T",
38224 		                     (duk_tval *) duk_get_tval(thr, idx_obj),
38225 		                     (duk_tval *) duk_get_tval(thr, -1)));
38226 
38227 		h_key = duk_known_hstring(thr, -1);
38228 		DUK_ASSERT(h_key != NULL);
38229 		DUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(h_key));  /* proplist filtering; enum options */
38230 
38231 		prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
38232 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
38233 			duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth);
38234 			duk__json_enc_key_autoquote(js_ctx, h_key);
38235 			DUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE);
38236 		} else {
38237 			duk__json_enc_key_autoquote(js_ctx, h_key);
38238 			DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
38239 		}
38240 
38241 		/* [ ... key ] */
38242 
38243 		if (DUK_UNLIKELY(duk__json_enc_value(js_ctx, idx_obj) == 0)) {
38244 			/* Value would yield 'undefined', so skip key altogether.
38245 			 * Side effects have already happened.
38246 			 */
38247 			DUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size);
38248 		} else {
38249 			DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
38250 			emitted = 1;
38251 		}
38252 
38253 		/* [ ... ] */
38254 	}
38255 
38256 	if (emitted) {
38257 		DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
38258 		DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
38259 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
38260 			DUK_ASSERT(js_ctx->recursion_depth >= 1);
38261 			duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
38262 		}
38263 	}
38264 	DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
38265 
38266 	duk__json_enc_objarr_exit(js_ctx, &entry_top);
38267 
38268 	DUK_ASSERT_TOP(thr, entry_top);
38269 }
38270 
38271 /* The JA(value) operation: encode array.
38272  *
38273  * Stack policy: [ array ] -> [ array ].
38274  */
38275 DUK_LOCAL void duk__json_enc_array(duk_json_enc_ctx *js_ctx) {
38276 	duk_hthread *thr = js_ctx->thr;
38277 	duk_idx_t entry_top;
38278 	duk_idx_t idx_arr;
38279 	duk_bool_t emitted;
38280 	duk_uarridx_t i, arr_len;
38281 
38282 	DUK_DDD(DUK_DDDPRINT("duk__json_enc_array: array=%!T",
38283 	                     (duk_tval *) duk_get_tval(thr, -1)));
38284 
38285 	duk__json_enc_objarr_entry(js_ctx, &entry_top);
38286 
38287 	idx_arr = entry_top - 1;
38288 
38289 	/* Steps 8-10 have been merged to avoid a "partial" variable. */
38290 
38291 	DUK__EMIT_1(js_ctx, DUK_ASC_LBRACKET);
38292 
38293 	arr_len = (duk_uarridx_t) duk_get_length(thr, idx_arr);
38294 	emitted = 0;
38295 	for (i = 0; i < arr_len; i++) {
38296 		DUK_DDD(DUK_DDDPRINT("array entry loop: array=%!T, index=%ld, arr_len=%ld",
38297 		                     (duk_tval *) duk_get_tval(thr, idx_arr),
38298 		                     (long) i, (long) arr_len));
38299 
38300 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
38301 			DUK_ASSERT(js_ctx->recursion_depth >= 1);
38302 			duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth);
38303 		}
38304 
38305 		(void) duk_push_uint_to_hstring(thr, (duk_uint_t) i);  /* -> [ ... key ] */
38306 
38307 		/* [ ... key ] */
38308 
38309 		if (DUK_UNLIKELY(duk__json_enc_value(js_ctx, idx_arr) == 0)) {
38310 			/* Value would normally be omitted, replace with 'null'. */
38311 			DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
38312 		} else {
38313 			;
38314 		}
38315 
38316 		/* [ ... ] */
38317 
38318 		DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
38319 		emitted = 1;
38320 	}
38321 
38322 	if (emitted) {
38323 		DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
38324 		DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
38325 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
38326 			DUK_ASSERT(js_ctx->recursion_depth >= 1);
38327 			duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
38328 		}
38329 	}
38330 	DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET);
38331 
38332 	duk__json_enc_objarr_exit(js_ctx, &entry_top);
38333 
38334 	DUK_ASSERT_TOP(thr, entry_top);
38335 }
38336 
38337 /* The Str(key, holder) operation.
38338  *
38339  * Stack policy: [ ... key ] -> [ ... ]
38340  */
38341 DUK_LOCAL duk_bool_t duk__json_enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder) {
38342 	duk_hthread *thr = js_ctx->thr;
38343 	duk_tval *tv;
38344 	duk_tval *tv_holder;
38345 	duk_tval *tv_key;
38346 	duk_small_int_t c;
38347 
38348 	DUK_DDD(DUK_DDDPRINT("duk__json_enc_value: idx_holder=%ld, holder=%!T, key=%!T",
38349 	                     (long) idx_holder, (duk_tval *) duk_get_tval(thr, idx_holder),
38350 	                     (duk_tval *) duk_get_tval(thr, -1)));
38351 
38352 	tv_holder = DUK_GET_TVAL_POSIDX(thr, idx_holder);
38353 	DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_holder));
38354 	tv_key = DUK_GET_TVAL_NEGIDX(thr, -1);
38355 	DUK_ASSERT(DUK_TVAL_IS_STRING(tv_key));
38356 	DUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(DUK_TVAL_GET_STRING(tv_key)));  /* Caller responsible. */
38357 	(void) duk_hobject_getprop(thr, tv_holder, tv_key);
38358 
38359 	/* -> [ ... key val ] */
38360 
38361 	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));
38362 
38363 	/* Standard JSON checks for .toJSON() only for actual objects; for
38364 	 * example, setting Number.prototype.toJSON and then serializing a
38365 	 * number won't invoke the .toJSON() method.  However, lightfuncs and
38366 	 * plain buffers mimic objects so we check for their .toJSON() method.
38367 	 */
38368 	if (duk_check_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT |
38369 	                                 DUK_TYPE_MASK_LIGHTFUNC |
38370 	                                 DUK_TYPE_MASK_BUFFER)) {
38371 		duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_TO_JSON);
38372 		if (duk_is_callable(thr, -1)) {  /* toJSON() can also be a lightfunc */
38373 			DUK_DDD(DUK_DDDPRINT("value is object, has callable toJSON() -> call it"));
38374 			/* XXX: duk_dup_unvalidated(thr, -2) etc. */
38375 			duk_dup_m2(thr);          /* -> [ ... key val toJSON val ] */
38376 			duk_dup_m4(thr);          /* -> [ ... key val toJSON val key ] */
38377 			duk_call_method(thr, 1);  /* -> [ ... key val val' ] */
38378 			duk_remove_m2(thr);       /* -> [ ... key val' ] */
38379 		} else {
38380 			duk_pop(thr);             /* -> [ ... key val ] */
38381 		}
38382 	}
38383 
38384 	/* [ ... key val ] */
38385 
38386 	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));
38387 
38388 	if (js_ctx->h_replacer) {
38389 		/* XXX: Here a "slice copy" would be useful. */
38390 		DUK_DDD(DUK_DDDPRINT("replacer is set, call replacer"));
38391 		duk_push_hobject(thr, js_ctx->h_replacer);  /* -> [ ... key val replacer ] */
38392 		duk_dup(thr, idx_holder);                   /* -> [ ... key val replacer holder ] */
38393 		duk_dup_m4(thr);                            /* -> [ ... key val replacer holder key ] */
38394 		duk_dup_m4(thr);                            /* -> [ ... key val replacer holder key val ] */
38395 		duk_call_method(thr, 2);                    /* -> [ ... key val val' ] */
38396 		duk_remove_m2(thr);                         /* -> [ ... key val' ] */
38397 	}
38398 
38399 	/* [ ... key val ] */
38400 
38401 	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));
38402 
38403 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
38404 	if (DUK_TVAL_IS_OBJECT(tv)) {
38405 		duk_hobject *h;
38406 
38407 		h = DUK_TVAL_GET_OBJECT(tv);
38408 		DUK_ASSERT(h != NULL);
38409 
38410 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
38411 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
38412 		if (DUK_HOBJECT_IS_BUFOBJ(h) &&
38413 		    js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE)) {
38414 			/* With JX/JC a bufferobject gets serialized specially. */
38415 			duk_hbufobj *h_bufobj;
38416 			h_bufobj = (duk_hbufobj *) h;
38417 			DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
38418 			duk__json_enc_bufobj(js_ctx, h_bufobj);
38419 			goto pop2_emitted;
38420 		}
38421 		/* Otherwise bufferobjects get serialized as normal objects. */
38422 #endif  /* JX || JC */
38423 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
38424 		c = (duk_small_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h);
38425 		switch (c) {
38426 		case DUK_HOBJECT_CLASS_NUMBER: {
38427 			DUK_DDD(DUK_DDDPRINT("value is a Number object -> coerce with ToNumber()"));
38428 			duk_to_number_m1(thr);
38429 			/* The coercion potentially invokes user .valueOf() and .toString()
38430 			 * but can't result in a function value because ToPrimitive() would
38431 			 * reject such a result: test-dev-json-stringify-coercion-1.js.
38432 			 */
38433 			DUK_ASSERT(!duk_is_callable(thr, -1));
38434 			break;
38435 		}
38436 		case DUK_HOBJECT_CLASS_STRING: {
38437 			DUK_DDD(DUK_DDDPRINT("value is a String object -> coerce with ToString()"));
38438 			duk_to_string(thr, -1);
38439 			/* Same coercion behavior as for Number. */
38440 			DUK_ASSERT(!duk_is_callable(thr, -1));
38441 			break;
38442 		}
38443 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
38444 		case DUK_HOBJECT_CLASS_POINTER:
38445 #endif
38446 		case DUK_HOBJECT_CLASS_BOOLEAN: {
38447 			DUK_DDD(DUK_DDDPRINT("value is a Boolean/Buffer/Pointer object -> get internal value"));
38448 			duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
38449 			duk_remove_m2(thr);
38450 			break;
38451 		}
38452 		default: {
38453 			/* Normal object which doesn't get automatically coerced to a
38454 			 * primitive value.  Functions are checked for specially.  The
38455 			 * primitive value coercions for Number, String, Pointer, and
38456 			 * Boolean can't result in functions so suffices to check here.
38457 			 * Symbol objects are handled like plain objects (their primitive
38458 			 * value is NOT looked up like for e.g. String objects).
38459 			 */
38460 			DUK_ASSERT(h != NULL);
38461 			if (DUK_HOBJECT_IS_CALLABLE(h)) {
38462 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
38463 				if (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
38464 				                     DUK_JSON_FLAG_EXT_COMPATIBLE)) {
38465 					/* We only get here when doing non-standard JSON encoding */
38466 					DUK_DDD(DUK_DDDPRINT("-> function allowed, serialize to custom format"));
38467 					DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);
38468 					DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
38469 					goto pop2_emitted;
38470 				} else {
38471 					DUK_DDD(DUK_DDDPRINT("-> will result in undefined (function)"));
38472 					goto pop2_undef;
38473 				}
38474 #else  /* DUK_USE_JX || DUK_USE_JC */
38475 				DUK_DDD(DUK_DDDPRINT("-> will result in undefined (function)"));
38476 				goto pop2_undef;
38477 #endif  /* DUK_USE_JX || DUK_USE_JC */
38478 			}
38479 		}
38480 		}  /* end switch */
38481 	}
38482 
38483 	/* [ ... key val ] */
38484 
38485 	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));
38486 
38487 	if (duk_check_type_mask(thr, -1, js_ctx->mask_for_undefined)) {
38488 		/* will result in undefined */
38489 		DUK_DDD(DUK_DDDPRINT("-> will result in undefined (type mask check)"));
38490 		goto pop2_undef;
38491 	}
38492 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
38493 
38494 	switch (DUK_TVAL_GET_TAG(tv)) {
38495 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
38496 	/* When JX/JC not in use, the type mask above will avoid this case if needed. */
38497 	case DUK_TAG_UNDEFINED: {
38498 		DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);
38499 		break;
38500 	}
38501 #endif
38502 	case DUK_TAG_NULL: {
38503 		DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
38504 		break;
38505 	}
38506 	case DUK_TAG_BOOLEAN: {
38507 		DUK__EMIT_STRIDX(js_ctx, DUK_TVAL_GET_BOOLEAN(tv) ?
38508 		                 DUK_STRIDX_TRUE : DUK_STRIDX_FALSE);
38509 		break;
38510 	}
38511 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
38512 	/* When JX/JC not in use, the type mask above will avoid this case if needed. */
38513 	case DUK_TAG_POINTER: {
38514 		duk__json_enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));
38515 		break;
38516 	}
38517 #endif  /* DUK_USE_JX || DUK_USE_JC */
38518 	case DUK_TAG_STRING: {
38519 		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
38520 		DUK_ASSERT(h != NULL);
38521 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
38522 			goto pop2_undef;
38523 		}
38524 		duk__json_enc_quote_string(js_ctx, h);
38525 		break;
38526 	}
38527 	case DUK_TAG_OBJECT: {
38528 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
38529 		DUK_ASSERT(h != NULL);
38530 
38531 		/* Function values are handled completely above (including
38532 		 * coercion results):
38533 		 */
38534 		DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE(h));
38535 
38536 		if (duk_js_isarray_hobject(h)) {
38537 			duk__json_enc_array(js_ctx);
38538 		} else {
38539 			duk__json_enc_object(js_ctx);
38540 		}
38541 		break;
38542 	}
38543 	/* Because plain buffers mimics Uint8Array, they have enumerable
38544 	 * index properties [0,byteLength[.  Because JSON only serializes
38545 	 * enumerable own properties, no properties can be serialized for
38546 	 * plain buffers (all virtual properties are non-enumerable).  However,
38547 	 * there may be a .toJSON() method which was already handled above.
38548 	 */
38549 	case DUK_TAG_BUFFER: {
38550 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
38551 		if (js_ctx->flag_ext_custom_or_compatible) {
38552 			duk__json_enc_buffer_jx_jc(js_ctx, DUK_TVAL_GET_BUFFER(tv));
38553 			break;
38554 		}
38555 #endif
38556 
38557 		/* Could implement a fastpath, but the fast path would need
38558 		 * to handle realloc side effects correctly.
38559 		 */
38560 		duk_to_object(thr, -1);
38561 		duk__json_enc_object(js_ctx);
38562 		break;
38563 	}
38564 	case DUK_TAG_LIGHTFUNC: {
38565 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
38566 		/* We only get here when doing non-standard JSON encoding */
38567 		DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);
38568 		DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
38569 #else
38570 		/* Standard JSON omits functions */
38571 		DUK_UNREACHABLE();
38572 #endif
38573 		break;
38574 	}
38575 #if defined(DUK_USE_FASTINT)
38576 	case DUK_TAG_FASTINT:
38577 		/* Number serialization has a significant impact relative to
38578 		 * other fast path code, so careful fast path for fastints.
38579 		 */
38580 		duk__json_enc_fastint_tval(js_ctx, tv);
38581 		break;
38582 #endif
38583 	default: {
38584 		/* number */
38585 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
38586 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
38587 		/* XXX: A fast path for usual integers would be useful when
38588 		 * fastint support is not enabled.
38589 		 */
38590 		duk__json_enc_double(js_ctx);
38591 		break;
38592 	}
38593 	}
38594 
38595 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
38596  pop2_emitted:
38597 #endif
38598 	duk_pop_2(thr); /* [ ... key val ] -> [ ... ] */
38599 	return 1;  /* emitted */
38600 
38601  pop2_undef:
38602 	duk_pop_2(thr);  /* [ ... key val ] -> [ ... ] */
38603 	return 0;  /* not emitted */
38604 }
38605 
38606 /* E5 Section 15.12.3, main algorithm, step 4.b.ii steps 1-4. */
38607 DUK_LOCAL duk_bool_t duk__json_enc_allow_into_proplist(duk_tval *tv) {
38608 	duk_small_int_t c;
38609 
38610 	/* XXX: some kind of external internal type checker?
38611 	 * - type mask; symbol flag; class mask
38612 	 */
38613 	DUK_ASSERT(tv != NULL);
38614 	if (DUK_TVAL_IS_STRING(tv)) {
38615 		duk_hstring *h;
38616 		h = DUK_TVAL_GET_STRING(tv);
38617 		DUK_ASSERT(h != NULL);
38618 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
38619 			return 0;
38620 		}
38621 		return 1;
38622 	} else if (DUK_TVAL_IS_NUMBER(tv)) {
38623 		return 1;
38624 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
38625 		duk_hobject *h;
38626 		h = DUK_TVAL_GET_OBJECT(tv);
38627 		DUK_ASSERT(h != NULL);
38628 		c = (duk_small_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h);
38629 		if (c == DUK_HOBJECT_CLASS_STRING || c == DUK_HOBJECT_CLASS_NUMBER) {
38630 			return 1;
38631 		}
38632 	}
38633 
38634 	return 0;
38635 }
38636 
38637 /*
38638  *  JSON.stringify() fast path
38639  *
38640  *  Otherwise supports full JSON, JX, and JC features, but bails out on any
38641  *  possible side effect which might change the value being serialized.  The
38642  *  fast path can take advantage of the fact that the value being serialized
38643  *  is unchanged so that we can walk directly through property tables etc.
38644  */
38645 
38646 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
38647 DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
38648 	duk_uint_fast32_t i, n;
38649 
38650 	DUK_DDD(DUK_DDDPRINT("stringify fast: %!T", tv));
38651 
38652 	DUK_ASSERT(js_ctx != NULL);
38653 	DUK_ASSERT(js_ctx->thr != NULL);
38654 
38655 #if 0 /* disabled for now */
38656  restart_match:
38657 #endif
38658 
38659 	DUK_ASSERT(tv != NULL);
38660 
38661 	switch (DUK_TVAL_GET_TAG(tv)) {
38662 	case DUK_TAG_UNDEFINED: {
38663 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
38664 		if (js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible) {
38665 			DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);
38666 			break;
38667 		} else {
38668 			goto emit_undefined;
38669 		}
38670 #else
38671 		goto emit_undefined;
38672 #endif
38673 	}
38674 	case DUK_TAG_NULL: {
38675 		DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
38676 		break;
38677 	}
38678 	case DUK_TAG_BOOLEAN: {
38679 		DUK__EMIT_STRIDX(js_ctx, DUK_TVAL_GET_BOOLEAN(tv) ?
38680 		                 DUK_STRIDX_TRUE : DUK_STRIDX_FALSE);
38681 		break;
38682 	}
38683 	case DUK_TAG_STRING: {
38684 		duk_hstring *h;
38685 		h = DUK_TVAL_GET_STRING(tv);
38686 		DUK_ASSERT(h != NULL);
38687 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
38688 			goto emit_undefined;
38689 		}
38690 		duk__json_enc_quote_string(js_ctx, h);
38691 		break;
38692 	}
38693 	case DUK_TAG_OBJECT: {
38694 		duk_hobject *obj;
38695 		duk_tval *tv_val;
38696 		duk_bool_t emitted = 0;
38697 		duk_uint32_t c_bit, c_all, c_array, c_unbox, c_undef,
38698 		             c_func, c_bufobj, c_object, c_abort;
38699 
38700 		/* For objects JSON.stringify() only looks for own, enumerable
38701 		 * properties which is nice for the fast path here.
38702 		 *
38703 		 * For arrays JSON.stringify() uses [[Get]] so it will actually
38704 		 * inherit properties during serialization!  This fast path
38705 		 * supports gappy arrays as long as there's no actual inherited
38706 		 * property (which might be a getter etc).
38707 		 *
38708 		 * Since recursion only happens for objects, we can have both
38709 		 * recursion and loop checks here.  We use a simple, depth-limited
38710 		 * loop check in the fast path because the object-based tracking
38711 		 * is very slow (when tested, it accounted for 50% of fast path
38712 		 * execution time for input data with a lot of small objects!).
38713 		 */
38714 
38715 		/* XXX: for real world code, could just ignore array inheritance
38716 		 * and only look at array own properties.
38717 		 */
38718 
38719 		/* We rely on a few object flag / class number relationships here,
38720 		 * assert for them.
38721 		 */
38722 
38723 		obj = DUK_TVAL_GET_OBJECT(tv);
38724 		DUK_ASSERT(obj != NULL);
38725 		DUK_HOBJECT_ASSERT_VALID(obj);
38726 
38727 		/* Once recursion depth is increased, exit path must decrease
38728 		 * it (though it's OK to abort the fast path).
38729 		 */
38730 
38731 		DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0);  /* unsigned */
38732 		DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
38733 		if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
38734 			DUK_DD(DUK_DDPRINT("fast path recursion limit"));
38735 			DUK_ERROR_RANGE(js_ctx->thr, DUK_STR_DEC_RECLIMIT);
38736 			DUK_WO_NORETURN(return 0;);
38737 		}
38738 
38739 		for (i = 0, n = (duk_uint_fast32_t) js_ctx->recursion_depth; i < n; i++) {
38740 			if (DUK_UNLIKELY(js_ctx->visiting[i] == obj)) {
38741 				DUK_DD(DUK_DDPRINT("fast path loop detect"));
38742 				DUK_ERROR_TYPE(js_ctx->thr, DUK_STR_CYCLIC_INPUT);
38743 				DUK_WO_NORETURN(return 0;);
38744 			}
38745 		}
38746 
38747 		/* Guaranteed by recursion_limit setup so we don't have to
38748 		 * check twice.
38749 		 */
38750 		DUK_ASSERT(js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY);
38751 		js_ctx->visiting[js_ctx->recursion_depth] = obj;
38752 		js_ctx->recursion_depth++;
38753 
38754 		/* If object has a .toJSON() property, we can't be certain
38755 		 * that it wouldn't mutate any value arbitrarily, so bail
38756 		 * out of the fast path.
38757 		 *
38758 		 * If an object is a Proxy we also can't avoid side effects
38759 		 * so abandon.
38760 		 */
38761 		/* XXX: non-callable .toJSON() doesn't need to cause an abort
38762 		 * but does at the moment, probably not worth fixing.
38763 		 */
38764 		if (duk_hobject_hasprop_raw(js_ctx->thr, obj, DUK_HTHREAD_STRING_TO_JSON(js_ctx->thr)) ||
38765 		    DUK_HOBJECT_IS_PROXY(obj)) {
38766 			DUK_DD(DUK_DDPRINT("object has a .toJSON property or object is a Proxy, abort fast path"));
38767 			goto abort_fastpath;
38768 		}
38769 
38770 		/* We could use a switch-case for the class number but it turns out
38771 		 * a small if-else ladder on class masks is better.  The if-ladder
38772 		 * should be in order of relevancy.
38773 		 */
38774 
38775 		/* XXX: move masks to js_ctx? they don't change during one
38776 		 * fast path invocation.
38777 		 */
38778 		DUK_ASSERT(DUK_HOBJECT_CLASS_MAX <= 31);
38779 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
38780 		if (js_ctx->flag_ext_custom_or_compatible) {
38781 			c_all = DUK_HOBJECT_CMASK_ALL;
38782 			c_array = DUK_HOBJECT_CMASK_ARRAY;
38783 			c_unbox = DUK_HOBJECT_CMASK_NUMBER |
38784 			          DUK_HOBJECT_CMASK_STRING |
38785 			          DUK_HOBJECT_CMASK_BOOLEAN |
38786 			          DUK_HOBJECT_CMASK_POINTER;  /* Symbols are not unboxed. */
38787 			c_func = DUK_HOBJECT_CMASK_FUNCTION;
38788 			c_bufobj = DUK_HOBJECT_CMASK_ALL_BUFOBJS;
38789 			c_undef = 0;
38790 			c_abort = 0;
38791 			c_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef | c_abort);
38792 		}
38793 		else
38794 #endif
38795 		{
38796 			c_all = DUK_HOBJECT_CMASK_ALL;
38797 			c_array = DUK_HOBJECT_CMASK_ARRAY;
38798 			c_unbox = DUK_HOBJECT_CMASK_NUMBER |
38799 			          DUK_HOBJECT_CMASK_STRING |
38800 			          DUK_HOBJECT_CMASK_BOOLEAN;  /* Symbols are not unboxed. */
38801 			c_func = 0;
38802 			c_bufobj = 0;
38803 			c_undef = DUK_HOBJECT_CMASK_FUNCTION |
38804 			          DUK_HOBJECT_CMASK_POINTER;
38805 			/* As the fast path doesn't currently properly support
38806 			 * duk_hbufobj virtual properties, abort fast path if
38807 			 * we encounter them in plain JSON mode.
38808 			 */
38809 			c_abort = DUK_HOBJECT_CMASK_ALL_BUFOBJS;
38810 			c_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef | c_abort);
38811 		}
38812 
38813 		c_bit = (duk_uint32_t) DUK_HOBJECT_GET_CLASS_MASK(obj);
38814 		if (c_bit & c_object) {
38815 			/* All other object types. */
38816 			DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
38817 
38818 			/* A non-Array object should not have an array part in practice.
38819 			 * But since it is supported internally (and perhaps used at some
38820 			 * point), check and abandon if that's the case.
38821 			 */
38822 			if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
38823 				DUK_DD(DUK_DDPRINT("non-Array object has array part, abort fast path"));
38824 				goto abort_fastpath;
38825 			}
38826 
38827 			for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(obj); i++) {
38828 				duk_hstring *k;
38829 				duk_size_t prev_size;
38830 
38831 				k = DUK_HOBJECT_E_GET_KEY(js_ctx->thr->heap, obj, i);
38832 				if (!k) {
38833 					continue;
38834 				}
38835 				if (DUK_HSTRING_HAS_ARRIDX(k)) {
38836 					/* If an object has array index keys we would need
38837 					 * to sort them into the ES2015 enumeration order to
38838 					 * be consistent with the slow path.  Abort the fast
38839 					 * path and handle in the slow path for now.
38840 					 */
38841 					DUK_DD(DUK_DDPRINT("property key is an array index, abort fast path"));
38842 					goto abort_fastpath;
38843 				}
38844 				if (!DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(js_ctx->thr->heap, obj, i)) {
38845 					continue;
38846 				}
38847 				if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(js_ctx->thr->heap, obj, i)) {
38848 					/* Getter might have arbitrary side effects,
38849 					 * so bail out.
38850 					 */
38851 					DUK_DD(DUK_DDPRINT("property is an accessor, abort fast path"));
38852 					goto abort_fastpath;
38853 				}
38854 				if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(k))) {
38855 					continue;
38856 				}
38857 
38858 				tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(js_ctx->thr->heap, obj, i);
38859 
38860 				prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
38861 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
38862 					duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth);
38863 					duk__json_enc_key_autoquote(js_ctx, k);
38864 					DUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE);
38865 				} else {
38866 					duk__json_enc_key_autoquote(js_ctx, k);
38867 					DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
38868 				}
38869 
38870 				if (duk__json_stringify_fast_value(js_ctx, tv_val) == 0) {
38871 					DUK_DD(DUK_DDPRINT("prop value not supported, rewind key and colon"));
38872 					DUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size);
38873 				} else {
38874 					DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
38875 					emitted = 1;
38876 				}
38877 			}
38878 
38879 			/* If any non-Array value had enumerable virtual own
38880 			 * properties, they should be serialized here (actually,
38881 			 * before the explicit properties).  Standard types don't.
38882 			 */
38883 
38884 			if (emitted) {
38885 				DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
38886 				DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
38887 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
38888 					DUK_ASSERT(js_ctx->recursion_depth >= 1);
38889 					duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
38890 				}
38891 			}
38892 			DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
38893 		} else if (c_bit & c_array) {
38894 			duk_uint_fast32_t arr_len;
38895 			duk_uint_fast32_t asize;
38896 
38897 			DUK__EMIT_1(js_ctx, DUK_ASC_LBRACKET);
38898 
38899 			/* Assume arrays are dense in the fast path. */
38900 			if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
38901 				DUK_DD(DUK_DDPRINT("Array object is sparse, abort fast path"));
38902 				goto abort_fastpath;
38903 			}
38904 
38905 			arr_len = (duk_uint_fast32_t) ((duk_harray *) obj)->length;
38906 			asize = (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(obj);
38907 			/* Array part may be larger than 'length'; if so, iterate
38908 			 * only up to array 'length'.  Array part may also be smaller
38909 			 * than 'length' in some cases.
38910 			 */
38911 			for (i = 0; i < arr_len; i++) {
38912 				duk_tval *tv_arrval;
38913 				duk_hstring *h_tmp;
38914 				duk_bool_t has_inherited;
38915 
38916 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
38917 					duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth);
38918 				}
38919 
38920 				if (DUK_LIKELY(i < asize)) {
38921 					tv_arrval = DUK_HOBJECT_A_GET_VALUE_PTR(js_ctx->thr->heap, obj, i);
38922 					if (DUK_LIKELY(!DUK_TVAL_IS_UNUSED(tv_arrval))) {
38923 						/* Expected case: element is present. */
38924 						if (duk__json_stringify_fast_value(js_ctx, tv_arrval) == 0) {
38925 							DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
38926 						}
38927 						goto elem_done;
38928 					}
38929 				}
38930 
38931 				/* Gap in array; check for inherited property,
38932 				 * bail out if one exists.  This should be enough
38933 				 * to support gappy arrays for all practical code.
38934 				 */
38935 
38936 				h_tmp = duk_push_uint_to_hstring(js_ctx->thr, (duk_uint_t) i);
38937 				has_inherited = duk_hobject_hasprop_raw(js_ctx->thr, obj, h_tmp);
38938 				duk_pop(js_ctx->thr);
38939 				if (has_inherited) {
38940 					DUK_D(DUK_DPRINT("gap in array, conflicting inherited property, abort fast path"));
38941 					goto abort_fastpath;
38942 				}
38943 
38944 				/* Ordinary gap, undefined encodes to 'null' in
38945 				 * standard JSON, but JX/JC use their form for
38946 				 * undefined to better preserve the typing.
38947 				 */
38948 				DUK_D(DUK_DPRINT("gap in array, no conflicting inherited property, remain on fast path"));
38949 #if defined(DUK_USE_JX)
38950 				DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);
38951 #else
38952 				DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
38953 #endif
38954 				/* fall through */
38955 
38956 			 elem_done:
38957 				DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
38958 				emitted = 1;
38959 			}
38960 
38961 			if (emitted) {
38962 				DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
38963 				DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
38964 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
38965 					DUK_ASSERT(js_ctx->recursion_depth >= 1);
38966 					duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
38967 				}
38968 			}
38969 			DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET);
38970 		} else if (c_bit & c_unbox) {
38971 			/* Certain boxed types are required to go through
38972 			 * automatic unboxing.  Rely on internal value being
38973 			 * sane (to avoid infinite recursion).
38974 			 */
38975 			DUK_ASSERT((c_bit & DUK_HOBJECT_CMASK_SYMBOL) == 0);  /* Symbols are not unboxed. */
38976 
38977 #if 1
38978 			/* The code below is incorrect if .toString() or .valueOf() have
38979 			 * have been overridden.  The correct approach would be to look up
38980 			 * the method(s) and if they resolve to the built-in function we
38981 			 * can safely bypass it and look up the internal value directly.
38982 			 * Unimplemented for now, abort fast path for boxed values.
38983 			 */
38984 			goto abort_fastpath;
38985 #else  /* disabled */
38986 			/* Disabled until fixed, see above. */
38987 			duk_tval *tv_internal;
38988 
38989 			DUK_DD(DUK_DDPRINT("auto unboxing in fast path"));
38990 
38991 			tv_internal = duk_hobject_get_internal_value_tval_ptr(js_ctx->thr->heap, obj);
38992 			DUK_ASSERT(tv_internal != NULL);
38993 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv_internal) ||
38994 			           DUK_TVAL_IS_NUMBER(tv_internal) ||
38995 			           DUK_TVAL_IS_BOOLEAN(tv_internal) ||
38996 			           DUK_TVAL_IS_POINTER(tv_internal));
38997 
38998 			tv = tv_internal;
38999 			DUK_ASSERT(js_ctx->recursion_depth > 0);
39000 			js_ctx->recursion_depth--;  /* required to keep recursion depth correct */
39001 			goto restart_match;
39002 #endif  /* disabled */
39003 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
39004 		} else if (c_bit & c_func) {
39005 			DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
39006 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
39007 		} else if (c_bit & c_bufobj) {
39008 			duk__json_enc_bufobj(js_ctx, (duk_hbufobj *) obj);
39009 #endif
39010 #endif
39011 		} else if (c_bit & c_abort) {
39012 			DUK_DD(DUK_DDPRINT("abort fast path for unsupported type"));
39013 			goto abort_fastpath;
39014 		} else {
39015 			DUK_ASSERT((c_bit & c_undef) != 0);
39016 
39017 			/* Must decrease recursion depth before returning. */
39018 			DUK_ASSERT(js_ctx->recursion_depth > 0);
39019 			DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
39020 			js_ctx->recursion_depth--;
39021 			goto emit_undefined;
39022 		}
39023 
39024 		DUK_ASSERT(js_ctx->recursion_depth > 0);
39025 		DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
39026 		js_ctx->recursion_depth--;
39027 		break;
39028 	}
39029 	case DUK_TAG_BUFFER: {
39030 		/* Plain buffers are treated like Uint8Arrays: they have
39031 		 * enumerable indices.  Other virtual properties are not
39032 		 * enumerable, and inherited properties are not serialized.
39033 		 * However, there can be a replacer (not relevant here) or
39034 		 * a .toJSON() method (which we need to check for explicitly).
39035 		 */
39036 
39037 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
39038 		if (duk_hobject_hasprop_raw(js_ctx->thr,
39039 		                            js_ctx->thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE],
39040 		                            DUK_HTHREAD_STRING_TO_JSON(js_ctx->thr))) {
39041 			DUK_DD(DUK_DDPRINT("value is a plain buffer and there's an inherited .toJSON, abort fast path"));
39042 			goto abort_fastpath;
39043 		}
39044 #endif
39045 
39046 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
39047 		if (js_ctx->flag_ext_custom_or_compatible) {
39048 			duk__json_enc_buffer_jx_jc(js_ctx, DUK_TVAL_GET_BUFFER(tv));
39049 			break;
39050 		}
39051 #endif
39052 
39053 		/* Plain buffers mimic Uint8Arrays, and have enumerable index
39054 		 * properties.
39055 		 */
39056 		duk__json_enc_buffer_json_fastpath(js_ctx, DUK_TVAL_GET_BUFFER(tv));
39057 		break;
39058 	}
39059 	case DUK_TAG_POINTER: {
39060 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
39061 		if (js_ctx->flag_ext_custom_or_compatible) {
39062 			duk__json_enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));
39063 			break;
39064 		} else {
39065 			goto emit_undefined;
39066 		}
39067 #else
39068 		goto emit_undefined;
39069 #endif
39070 	}
39071 	case DUK_TAG_LIGHTFUNC: {
39072 		/* A lightfunc might also inherit a .toJSON() so just bail out. */
39073 		/* XXX: Could just lookup .toJSON() and continue in fast path,
39074 		 * as it would almost never be defined.
39075 		 */
39076 		DUK_DD(DUK_DDPRINT("value is a lightfunc, abort fast path"));
39077 		goto abort_fastpath;
39078 	}
39079 #if defined(DUK_USE_FASTINT)
39080 	case DUK_TAG_FASTINT: {
39081 		/* Number serialization has a significant impact relative to
39082 		 * other fast path code, so careful fast path for fastints.
39083 		 */
39084 		duk__json_enc_fastint_tval(js_ctx, tv);
39085 		break;
39086 	}
39087 #endif
39088 	default: {
39089 		/* XXX: A fast path for usual integers would be useful when
39090 		 * fastint support is not enabled.
39091 		 */
39092 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
39093 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
39094 
39095 		/* XXX: Stack discipline is annoying, could be changed in numconv. */
39096 		duk_push_tval(js_ctx->thr, tv);
39097 		duk__json_enc_double(js_ctx);
39098 		duk_pop(js_ctx->thr);
39099 
39100 #if 0
39101 		/* Could also rely on native sprintf(), but it will handle
39102 		 * values like NaN, Infinity, -0, exponent notation etc in
39103 		 * a JSON-incompatible way.
39104 		 */
39105 		duk_double_t d;
39106 		char buf[64];
39107 
39108 		DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
39109 		d = DUK_TVAL_GET_DOUBLE(tv);
39110 		DUK_SPRINTF(buf, "%lg", d);
39111 		DUK__EMIT_CSTR(js_ctx, buf);
39112 #endif
39113 	}
39114 	}
39115 	return 1;  /* not undefined */
39116 
39117  emit_undefined:
39118 	return 0;  /* value was undefined/unsupported */
39119 
39120  abort_fastpath:
39121 	/* Error message doesn't matter: the error is ignored anyway. */
39122 	DUK_DD(DUK_DDPRINT("aborting fast path"));
39123 	DUK_ERROR_INTERNAL(js_ctx->thr);
39124 	DUK_WO_NORETURN(return 0;);
39125 }
39126 
39127 DUK_LOCAL duk_ret_t duk__json_stringify_fast(duk_hthread *thr, void *udata) {
39128 	duk_json_enc_ctx *js_ctx;
39129 	duk_tval *tv;
39130 
39131 	DUK_ASSERT(thr != NULL);
39132 	DUK_ASSERT(udata != NULL);
39133 
39134 	js_ctx = (duk_json_enc_ctx *) udata;
39135 	DUK_ASSERT(js_ctx != NULL);
39136 
39137 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
39138 	if (duk__json_stringify_fast_value(js_ctx, tv) == 0) {
39139 		DUK_DD(DUK_DDPRINT("top level value not supported, fail fast path"));
39140 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);  /* Error message is ignored, so doesn't matter. */
39141 	}
39142 
39143 	return 0;
39144 }
39145 #endif  /* DUK_USE_JSON_STRINGIFY_FASTPATH */
39146 
39147 /*
39148  *  Top level wrappers
39149  */
39150 
39151 DUK_INTERNAL
39152 void duk_bi_json_parse_helper(duk_hthread *thr,
39153                               duk_idx_t idx_value,
39154                               duk_idx_t idx_reviver,
39155                               duk_small_uint_t flags) {
39156 	duk_json_dec_ctx js_ctx_alloc;
39157 	duk_json_dec_ctx *js_ctx = &js_ctx_alloc;
39158 	duk_hstring *h_text;
39159 #if defined(DUK_USE_ASSERTIONS)
39160 	duk_idx_t entry_top = duk_get_top(thr);
39161 #endif
39162 
39163 	/* negative top-relative indices not allowed now */
39164 	DUK_ASSERT(idx_value == DUK_INVALID_INDEX || idx_value >= 0);
39165 	DUK_ASSERT(idx_reviver == DUK_INVALID_INDEX || idx_reviver >= 0);
39166 
39167 	DUK_DDD(DUK_DDDPRINT("JSON parse start: text=%!T, reviver=%!T, flags=0x%08lx, stack_top=%ld",
39168 	                     (duk_tval *) duk_get_tval(thr, idx_value),
39169 	                     (duk_tval *) duk_get_tval(thr, idx_reviver),
39170 	                     (unsigned long) flags,
39171 	                     (long) duk_get_top(thr)));
39172 
39173 	duk_memzero(&js_ctx_alloc, sizeof(js_ctx_alloc));
39174 	js_ctx->thr = thr;
39175 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
39176 	/* nothing now */
39177 #endif
39178 	js_ctx->recursion_limit = DUK_USE_JSON_DEC_RECLIMIT;
39179 	DUK_ASSERT(js_ctx->recursion_depth == 0);
39180 
39181 	/* Flag handling currently assumes that flags are consistent.  This is OK
39182 	 * because the call sites are now strictly controlled.
39183 	 */
39184 
39185 	js_ctx->flags = flags;
39186 #if defined(DUK_USE_JX)
39187 	js_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM;
39188 #endif
39189 #if defined(DUK_USE_JC)
39190 	js_ctx->flag_ext_compatible = flags & DUK_JSON_FLAG_EXT_COMPATIBLE;
39191 #endif
39192 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
39193 	js_ctx->flag_ext_custom_or_compatible = flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE);
39194 #endif
39195 
39196 	h_text = duk_to_hstring(thr, idx_value);  /* coerce in-place; rejects Symbols */
39197 	DUK_ASSERT(h_text != NULL);
39198 
39199 	/* JSON parsing code is allowed to read [p_start,p_end]: p_end is
39200 	 * valid and points to the string NUL terminator (which is always
39201 	 * guaranteed for duk_hstrings.
39202 	 */
39203 	js_ctx->p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text);
39204 	js_ctx->p = js_ctx->p_start;
39205 	js_ctx->p_end = ((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text)) +
39206 	                DUK_HSTRING_GET_BYTELEN(h_text);
39207 	DUK_ASSERT(*(js_ctx->p_end) == 0x00);
39208 
39209 	duk__json_dec_value(js_ctx);  /* -> [ ... value ] */
39210 	DUK_ASSERT(js_ctx->recursion_depth == 0);
39211 
39212 	/* Trailing whitespace has been eaten by duk__json_dec_value(), so if
39213 	 * we're not at end of input here, it's a SyntaxError.
39214 	 */
39215 
39216 	if (js_ctx->p != js_ctx->p_end) {
39217 		duk__json_dec_syntax_error(js_ctx);
39218 	}
39219 
39220 	if (duk_is_callable(thr, idx_reviver)) {
39221 		DUK_DDD(DUK_DDDPRINT("applying reviver: %!T",
39222 		                     (duk_tval *) duk_get_tval(thr, idx_reviver)));
39223 
39224 		js_ctx->idx_reviver = idx_reviver;
39225 
39226 		duk_push_object(thr);
39227 		duk_dup_m2(thr);  /* -> [ ... val root val ] */
39228 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_EMPTY_STRING);  /* default attrs ok */
39229 		duk_push_hstring_stridx(thr, DUK_STRIDX_EMPTY_STRING);  /* -> [ ... val root "" ] */
39230 
39231 		DUK_DDD(DUK_DDDPRINT("start reviver walk, root=%!T, name=%!T",
39232 		                     (duk_tval *) duk_get_tval(thr, -2),
39233 		                     (duk_tval *) duk_get_tval(thr, -1)));
39234 
39235 		DUK_ASSERT(js_ctx->recursion_depth == 0);
39236 		duk__json_dec_reviver_walk(js_ctx);  /* [ ... val root "" ] -> [ ... val val' ] */
39237 		DUK_ASSERT(js_ctx->recursion_depth == 0);
39238 		duk_remove_m2(thr);             /* -> [ ... val' ] */
39239 	} else {
39240 		DUK_DDD(DUK_DDDPRINT("reviver does not exist or is not callable: %!T",
39241 		                     (duk_tval *) duk_get_tval(thr, idx_reviver)));
39242 	}
39243 
39244 	/* Final result is at stack top. */
39245 
39246 	DUK_DDD(DUK_DDDPRINT("JSON parse end: text=%!T, reviver=%!T, flags=0x%08lx, result=%!T, stack_top=%ld",
39247 	                     (duk_tval *) duk_get_tval(thr, idx_value),
39248 	                     (duk_tval *) duk_get_tval(thr, idx_reviver),
39249 	                     (unsigned long) flags,
39250 	                     (duk_tval *) duk_get_tval(thr, -1),
39251 	                     (long) duk_get_top(thr)));
39252 
39253 	DUK_ASSERT(duk_get_top(thr) == entry_top + 1);
39254 }
39255 
39256 DUK_INTERNAL
39257 void duk_bi_json_stringify_helper(duk_hthread *thr,
39258                                   duk_idx_t idx_value,
39259                                   duk_idx_t idx_replacer,
39260                                   duk_idx_t idx_space,
39261                                   duk_small_uint_t flags) {
39262 	duk_json_enc_ctx js_ctx_alloc;
39263 	duk_json_enc_ctx *js_ctx = &js_ctx_alloc;
39264 	duk_hobject *h;
39265 	duk_idx_t idx_holder;
39266 	duk_idx_t entry_top;
39267 
39268 	/* negative top-relative indices not allowed now */
39269 	DUK_ASSERT(idx_value == DUK_INVALID_INDEX || idx_value >= 0);
39270 	DUK_ASSERT(idx_replacer == DUK_INVALID_INDEX || idx_replacer >= 0);
39271 	DUK_ASSERT(idx_space == DUK_INVALID_INDEX || idx_space >= 0);
39272 
39273 	DUK_DDD(DUK_DDDPRINT("JSON stringify start: value=%!T, replacer=%!T, space=%!T, flags=0x%08lx, stack_top=%ld",
39274 	                     (duk_tval *) duk_get_tval(thr, idx_value),
39275 	                     (duk_tval *) duk_get_tval(thr, idx_replacer),
39276 	                     (duk_tval *) duk_get_tval(thr, idx_space),
39277 	                     (unsigned long) flags,
39278 	                     (long) duk_get_top(thr)));
39279 
39280 	entry_top = duk_get_top(thr);
39281 
39282 	/*
39283 	 *  Context init
39284 	 */
39285 
39286 	duk_memzero(&js_ctx_alloc, sizeof(js_ctx_alloc));
39287 	js_ctx->thr = thr;
39288 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
39289 	js_ctx->h_replacer = NULL;
39290 	js_ctx->h_gap = NULL;
39291 #endif
39292 	js_ctx->idx_proplist = -1;
39293 
39294 	/* Flag handling currently assumes that flags are consistent.  This is OK
39295 	 * because the call sites are now strictly controlled.
39296 	 */
39297 
39298 	js_ctx->flags = flags;
39299 	js_ctx->flag_ascii_only = flags & DUK_JSON_FLAG_ASCII_ONLY;
39300 	js_ctx->flag_avoid_key_quotes = flags & DUK_JSON_FLAG_AVOID_KEY_QUOTES;
39301 #if defined(DUK_USE_JX)
39302 	js_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM;
39303 #endif
39304 #if defined(DUK_USE_JC)
39305 	js_ctx->flag_ext_compatible = flags & DUK_JSON_FLAG_EXT_COMPATIBLE;
39306 #endif
39307 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
39308 	js_ctx->flag_ext_custom_or_compatible = flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE);
39309 #endif
39310 
39311 	/* The #if defined() clutter here handles the JX/JC enable/disable
39312 	 * combinations properly.
39313 	 */
39314 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
39315 	js_ctx->stridx_custom_undefined = DUK_STRIDX_LC_NULL;  /* standard JSON; array gaps */
39316 #if defined(DUK_USE_JX)
39317 	if (flags & DUK_JSON_FLAG_EXT_CUSTOM) {
39318 		js_ctx->stridx_custom_undefined = DUK_STRIDX_LC_UNDEFINED;
39319 		js_ctx->stridx_custom_nan = DUK_STRIDX_NAN;
39320 		js_ctx->stridx_custom_neginf = DUK_STRIDX_MINUS_INFINITY;
39321 		js_ctx->stridx_custom_posinf = DUK_STRIDX_INFINITY;
39322 		js_ctx->stridx_custom_function =
39323 		        (flags & DUK_JSON_FLAG_AVOID_KEY_QUOTES) ?
39324 		                DUK_STRIDX_JSON_EXT_FUNCTION2 :
39325 		                DUK_STRIDX_JSON_EXT_FUNCTION1;
39326 	}
39327 #endif  /* DUK_USE_JX */
39328 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
39329 	else
39330 #endif  /* DUK_USE_JX && DUK_USE_JC */
39331 #if defined(DUK_USE_JC)
39332 	if (js_ctx->flags & DUK_JSON_FLAG_EXT_COMPATIBLE) {
39333 		js_ctx->stridx_custom_undefined = DUK_STRIDX_JSON_EXT_UNDEFINED;
39334 		js_ctx->stridx_custom_nan = DUK_STRIDX_JSON_EXT_NAN;
39335 		js_ctx->stridx_custom_neginf = DUK_STRIDX_JSON_EXT_NEGINF;
39336 		js_ctx->stridx_custom_posinf = DUK_STRIDX_JSON_EXT_POSINF;
39337 		js_ctx->stridx_custom_function = DUK_STRIDX_JSON_EXT_FUNCTION1;
39338 	}
39339 #endif  /* DUK_USE_JC */
39340 #endif  /* DUK_USE_JX || DUK_USE_JC */
39341 
39342 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
39343 	if (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
39344 	                     DUK_JSON_FLAG_EXT_COMPATIBLE)) {
39345 		DUK_ASSERT(js_ctx->mask_for_undefined == 0);  /* already zero */
39346 	}
39347 	else
39348 #endif  /* DUK_USE_JX || DUK_USE_JC */
39349 	{
39350 		/* Plain buffer is treated like ArrayBuffer and serialized.
39351 		 * Lightfuncs are treated like objects, but JSON explicitly
39352 		 * skips serializing Function objects so we can just reject
39353 		 * lightfuncs here.
39354 		 */
39355 		js_ctx->mask_for_undefined = DUK_TYPE_MASK_UNDEFINED |
39356 		                             DUK_TYPE_MASK_POINTER |
39357 		                             DUK_TYPE_MASK_LIGHTFUNC;
39358 	}
39359 
39360 	DUK_BW_INIT_PUSHBUF(thr, &js_ctx->bw, DUK__JSON_STRINGIFY_BUFSIZE);
39361 
39362 	js_ctx->idx_loop = duk_push_bare_object(thr);
39363 	DUK_ASSERT(js_ctx->idx_loop >= 0);
39364 
39365 	/* [ ... buf loop ] */
39366 
39367 	/*
39368 	 *  Process replacer/proplist (2nd argument to JSON.stringify)
39369 	 */
39370 
39371 	h = duk_get_hobject(thr, idx_replacer);
39372 	if (h != NULL) {
39373 		if (DUK_HOBJECT_IS_CALLABLE(h)) {
39374 			js_ctx->h_replacer = h;
39375 		} else if (duk_js_isarray_hobject(h)) {
39376 			/* Here the specification requires correct array index enumeration
39377 			 * which is a bit tricky for sparse arrays (it is handled by the
39378 			 * enum setup code).  We now enumerate ancestors too, although the
39379 			 * specification is not very clear on whether that is required.
39380 			 */
39381 
39382 			duk_uarridx_t plist_idx = 0;
39383 			duk_small_uint_t enum_flags;
39384 
39385 			js_ctx->idx_proplist = duk_push_bare_array(thr);
39386 
39387 			enum_flags = DUK_ENUM_ARRAY_INDICES_ONLY |
39388 			             DUK_ENUM_SORT_ARRAY_INDICES;  /* expensive flag */
39389 			duk_enum(thr, idx_replacer, enum_flags);
39390 			while (duk_next(thr, -1 /*enum_index*/, 1 /*get_value*/)) {
39391 				/* [ ... proplist enum_obj key val ] */
39392 				if (duk__json_enc_allow_into_proplist(duk_get_tval(thr, -1))) {
39393 					/* XXX: duplicates should be eliminated here */
39394 					DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> accept",
39395 					                     (duk_tval *) duk_get_tval(thr, -2),
39396 					                     (duk_tval *) duk_get_tval(thr, -1)));
39397 					duk_to_string(thr, -1);  /* extra coercion of strings is OK */
39398 					duk_put_prop_index(thr, -4, plist_idx);  /* -> [ ... proplist enum_obj key ] */
39399 					plist_idx++;
39400 					duk_pop(thr);
39401 				} else {
39402 					DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> reject",
39403 					                     (duk_tval *) duk_get_tval(thr, -2),
39404 					                     (duk_tval *) duk_get_tval(thr, -1)));
39405 					duk_pop_2(thr);
39406 				}
39407                         }
39408                         duk_pop(thr);  /* pop enum */
39409 
39410 			/* [ ... proplist ] */
39411 		}
39412 	}
39413 
39414 	/* [ ... buf loop (proplist) ] */
39415 
39416 	/*
39417 	 *  Process space (3rd argument to JSON.stringify)
39418 	 */
39419 
39420 	h = duk_get_hobject(thr, idx_space);
39421 	if (h != NULL) {
39422 		duk_small_uint_t c = DUK_HOBJECT_GET_CLASS_NUMBER(h);
39423 		if (c == DUK_HOBJECT_CLASS_NUMBER) {
39424 			duk_to_number(thr, idx_space);
39425 		} else if (c == DUK_HOBJECT_CLASS_STRING) {
39426 			duk_to_string(thr, idx_space);
39427 		}
39428 	}
39429 
39430 	if (duk_is_number(thr, idx_space)) {
39431 		duk_small_int_t nspace;
39432 		/* spaces[] must be static to allow initializer with old compilers like BCC */
39433 		static const char spaces[10] = {
39434 			DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE,
39435 			DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE,
39436 			DUK_ASC_SPACE, DUK_ASC_SPACE
39437 		};  /* XXX: helper */
39438 
39439 		/* ToInteger() coercion; NaN -> 0, infinities are clamped to 0 and 10 */
39440 		nspace = (duk_small_int_t) duk_to_int_clamped(thr, idx_space, 0 /*minval*/, 10 /*maxval*/);
39441 		DUK_ASSERT(nspace >= 0 && nspace <= 10);
39442 
39443 		duk_push_lstring(thr, spaces, (duk_size_t) nspace);
39444 		js_ctx->h_gap = duk_known_hstring(thr, -1);
39445 		DUK_ASSERT(js_ctx->h_gap != NULL);
39446 	} else if (duk_is_string_notsymbol(thr, idx_space)) {
39447 		duk_dup(thr, idx_space);
39448 		duk_substring(thr, -1, 0, 10);  /* clamp to 10 chars */
39449 		js_ctx->h_gap = duk_known_hstring(thr, -1);
39450 	} else {
39451 		/* nop */
39452 	}
39453 
39454 	if (js_ctx->h_gap != NULL) {
39455 		/* If gap is empty, behave as if not given at all.  Check
39456 		 * against byte length because character length is more
39457 		 * expensive.
39458 		 */
39459 		if (DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) == 0) {
39460 			js_ctx->h_gap = NULL;
39461 		}
39462 	}
39463 
39464 	/* [ ... buf loop (proplist) (gap) ] */
39465 
39466 	/*
39467 	 *  Fast path: assume no mutation, iterate object property tables
39468 	 *  directly; bail out if that assumption doesn't hold.
39469 	 */
39470 
39471 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
39472 	if (js_ctx->h_replacer == NULL &&  /* replacer is a mutation risk */
39473 	    js_ctx->idx_proplist == -1) {  /* proplist is very rare */
39474 		duk_int_t pcall_rc;
39475 		duk_small_uint_t prev_ms_base_flags;
39476 
39477 		DUK_DD(DUK_DDPRINT("try JSON.stringify() fast path"));
39478 
39479 		/* Use recursion_limit to ensure we don't overwrite js_ctx->visiting[]
39480 		 * array so we don't need two counter checks in the fast path.  The
39481 		 * slow path has a much larger recursion limit which we'll use if
39482 		 * necessary.
39483 		 */
39484 		DUK_ASSERT(DUK_USE_JSON_ENC_RECLIMIT >= DUK_JSON_ENC_LOOPARRAY);
39485 		js_ctx->recursion_limit = DUK_JSON_ENC_LOOPARRAY;
39486 		DUK_ASSERT(js_ctx->recursion_depth == 0);
39487 
39488 		/* Execute the fast path in a protected call.  If any error is thrown,
39489 		 * fall back to the slow path.  This includes e.g. recursion limit
39490 		 * because the fast path has a smaller recursion limit (and simpler,
39491 		 * limited loop detection).
39492 		 */
39493 
39494 		duk_dup(thr, idx_value);
39495 
39496 		/* Must prevent finalizers which may have arbitrary side effects. */
39497 		prev_ms_base_flags = thr->heap->ms_base_flags;
39498 		thr->heap->ms_base_flags |=
39499 		        DUK_MS_FLAG_NO_OBJECT_COMPACTION;      /* Avoid attempt to compact any objects. */
39500 		thr->heap->pf_prevent_count++;                 /* Prevent finalizers. */
39501 		DUK_ASSERT(thr->heap->pf_prevent_count != 0);  /* Wrap. */
39502 
39503 		pcall_rc = duk_safe_call(thr, duk__json_stringify_fast, (void *) js_ctx /*udata*/, 1 /*nargs*/, 0 /*nret*/);
39504 
39505 		DUK_ASSERT(thr->heap->pf_prevent_count > 0);
39506 		thr->heap->pf_prevent_count--;
39507 		thr->heap->ms_base_flags = prev_ms_base_flags;
39508 
39509 		if (pcall_rc == DUK_EXEC_SUCCESS) {
39510 			DUK_DD(DUK_DDPRINT("fast path successful"));
39511 			DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw);
39512 			goto replace_finished;
39513 		}
39514 
39515 		/* We come here for actual aborts (like encountering .toJSON())
39516 		 * but also for recursion/loop errors.  Bufwriter size can be
39517 		 * kept because we'll probably need at least as much as we've
39518 		 * allocated so far.
39519 		 */
39520 		DUK_D(DUK_DPRINT("fast path failed, serialize using slow path instead"));
39521 		DUK_BW_RESET_SIZE(thr, &js_ctx->bw);
39522 		js_ctx->recursion_depth = 0;
39523 	}
39524 #endif
39525 
39526 	/*
39527 	 *  Create wrapper object and serialize
39528 	 */
39529 
39530 	idx_holder = duk_push_object(thr);
39531 	duk_dup(thr, idx_value);
39532 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_EMPTY_STRING);
39533 
39534 	DUK_DDD(DUK_DDDPRINT("before: flags=0x%08lx, loop=%!T, replacer=%!O, "
39535 	                     "proplist=%!T, gap=%!O, holder=%!T",
39536 	                     (unsigned long) js_ctx->flags,
39537 	                     (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop),
39538 	                     (duk_heaphdr *) js_ctx->h_replacer,
39539 	                     (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(thr, js_ctx->idx_proplist) : NULL),
39540 	                     (duk_heaphdr *) js_ctx->h_gap,
39541 	                     (duk_tval *) duk_get_tval(thr, -1)));
39542 
39543 	/* serialize the wrapper with empty string key */
39544 
39545 	duk_push_hstring_empty(thr);
39546 
39547 	/* [ ... buf loop (proplist) (gap) holder "" ] */
39548 
39549 	js_ctx->recursion_limit = DUK_USE_JSON_ENC_RECLIMIT;
39550 	DUK_ASSERT(js_ctx->recursion_depth == 0);
39551 
39552 	if (DUK_UNLIKELY(duk__json_enc_value(js_ctx, idx_holder) == 0)) {  /* [ ... holder key ] -> [ ... holder ] */
39553 		/* Result is undefined. */
39554 		duk_push_undefined(thr);
39555 	} else {
39556 		/* Convert buffer to result string. */
39557 		DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw);
39558 	}
39559 
39560 	DUK_DDD(DUK_DDDPRINT("after: flags=0x%08lx, loop=%!T, replacer=%!O, "
39561 	                     "proplist=%!T, gap=%!O, holder=%!T",
39562 	                     (unsigned long) js_ctx->flags,
39563 	                     (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop),
39564 	                     (duk_heaphdr *) js_ctx->h_replacer,
39565 	                     (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(thr, js_ctx->idx_proplist) : NULL),
39566 	                     (duk_heaphdr *) js_ctx->h_gap,
39567 	                     (duk_tval *) duk_get_tval(thr, idx_holder)));
39568 
39569 	/* The stack has a variable shape here, so force it to the
39570 	 * desired one explicitly.
39571 	 */
39572 
39573 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
39574  replace_finished:
39575 #endif
39576 	duk_replace(thr, entry_top);
39577 	duk_set_top(thr, entry_top + 1);
39578 
39579 	DUK_DDD(DUK_DDDPRINT("JSON stringify end: value=%!T, replacer=%!T, space=%!T, "
39580 	                     "flags=0x%08lx, result=%!T, stack_top=%ld",
39581 	                     (duk_tval *) duk_get_tval(thr, idx_value),
39582 	                     (duk_tval *) duk_get_tval(thr, idx_replacer),
39583 	                     (duk_tval *) duk_get_tval(thr, idx_space),
39584 	                     (unsigned long) flags,
39585 	                     (duk_tval *) duk_get_tval(thr, -1),
39586 	                     (long) duk_get_top(thr)));
39587 
39588 	DUK_ASSERT(duk_get_top(thr) == entry_top + 1);
39589 }
39590 
39591 #if defined(DUK_USE_JSON_BUILTIN)
39592 
39593 /*
39594  *  Entry points
39595  */
39596 
39597 DUK_INTERNAL duk_ret_t duk_bi_json_object_parse(duk_hthread *thr) {
39598 	duk_bi_json_parse_helper(thr,
39599 	                         0 /*idx_value*/,
39600 	                         1 /*idx_replacer*/,
39601 	                         0 /*flags*/);
39602 	return 1;
39603 }
39604 
39605 DUK_INTERNAL duk_ret_t duk_bi_json_object_stringify(duk_hthread *thr) {
39606 	duk_bi_json_stringify_helper(thr,
39607 	                             0 /*idx_value*/,
39608 	                             1 /*idx_replacer*/,
39609 	                             2 /*idx_space*/,
39610 	                             0 /*flags*/);
39611 	return 1;
39612 }
39613 
39614 #endif  /* DUK_USE_JSON_BUILTIN */
39615 
39616 #endif  /* DUK_USE_JSON_SUPPORT */
39617 
39618 /* automatic undefs */
39619 #undef DUK__EMIT_1
39620 #undef DUK__EMIT_2
39621 #undef DUK__EMIT_CSTR
39622 #undef DUK__EMIT_HSTR
39623 #undef DUK__EMIT_STRIDX
39624 #undef DUK__JSON_DECSTR_BUFSIZE
39625 #undef DUK__JSON_DECSTR_CHUNKSIZE
39626 #undef DUK__JSON_ENCSTR_CHUNKSIZE
39627 #undef DUK__JSON_MAX_ESC_LEN
39628 #undef DUK__JSON_STRINGIFY_BUFSIZE
39629 #undef DUK__MKESC
39630 #undef DUK__UNEMIT_1
39631 /*
39632  *  Math built-ins
39633  */
39634 
39635 /* #include duk_internal.h -> already included */
39636 
39637 #if defined(DUK_USE_MATH_BUILTIN)
39638 
39639 /*
39640  *  Use static helpers which can work with math.h functions matching
39641  *  the following signatures. This is not portable if any of these math
39642  *  functions is actually a macro.
39643  *
39644  *  Typing here is intentionally 'double' wherever values interact with
39645  *  the standard library APIs.
39646  */
39647 
39648 typedef double (*duk__one_arg_func)(double);
39649 typedef double (*duk__two_arg_func)(double, double);
39650 
39651 DUK_LOCAL duk_ret_t duk__math_minmax(duk_hthread *thr, duk_double_t initial, duk__two_arg_func min_max) {
39652 	duk_idx_t n = duk_get_top(thr);
39653 	duk_idx_t i;
39654 	duk_double_t res = initial;
39655 	duk_double_t t;
39656 
39657 	/*
39658 	 *  Note: fmax() does not match the E5 semantics.  E5 requires
39659 	 *  that if -any- input to Math.max() is a NaN, the result is a
39660 	 *  NaN.  fmax() will return a NaN only if -both- inputs are NaN.
39661 	 *  Same applies to fmin().
39662 	 *
39663 	 *  Note: every input value must be coerced with ToNumber(), even
39664 	 *  if we know the result will be a NaN anyway: ToNumber() may have
39665 	 *  side effects for which even order of evaluation matters.
39666 	 */
39667 
39668 	for (i = 0; i < n; i++) {
39669 		t = duk_to_number(thr, i);
39670 		if (DUK_FPCLASSIFY(t) == DUK_FP_NAN || DUK_FPCLASSIFY(res) == DUK_FP_NAN) {
39671 			/* Note: not normalized, but duk_push_number() will normalize */
39672 			res = (duk_double_t) DUK_DOUBLE_NAN;
39673 		} else {
39674 			res = (duk_double_t) min_max(res, (double) t);
39675 		}
39676 	}
39677 
39678 	duk_push_number(thr, res);
39679 	return 1;
39680 }
39681 
39682 DUK_LOCAL double duk__fmin_fixed(double x, double y) {
39683 	/* fmin() with args -0 and +0 is not guaranteed to return
39684 	 * -0 as ECMAScript requires.
39685 	 */
39686 	if (duk_double_equals(x, 0.0) && duk_double_equals(y, 0.0)) {
39687 		duk_double_union du1, du2;
39688 		du1.d = x;
39689 		du2.d = y;
39690 
39691 		/* Already checked to be zero so these must hold, and allow us
39692 		 * to check for "x is -0 or y is -0" by ORing the high parts
39693 		 * for comparison.
39694 		 */
39695 		DUK_ASSERT(du1.ui[DUK_DBL_IDX_UI0] == 0 || du1.ui[DUK_DBL_IDX_UI0] == 0x80000000UL);
39696 		DUK_ASSERT(du2.ui[DUK_DBL_IDX_UI0] == 0 || du2.ui[DUK_DBL_IDX_UI0] == 0x80000000UL);
39697 
39698 		/* XXX: what's the safest way of creating a negative zero? */
39699 		if ((du1.ui[DUK_DBL_IDX_UI0] | du2.ui[DUK_DBL_IDX_UI0]) != 0) {
39700 			/* Enter here if either x or y (or both) is -0. */
39701 			return -0.0;
39702 		} else {
39703 			return +0.0;
39704 		}
39705 	}
39706 	return duk_double_fmin(x, y);
39707 }
39708 
39709 DUK_LOCAL double duk__fmax_fixed(double x, double y) {
39710 	/* fmax() with args -0 and +0 is not guaranteed to return
39711 	 * +0 as ECMAScript requires.
39712 	 */
39713 	if (duk_double_equals(x, 0.0) && duk_double_equals(y, 0.0)) {
39714 		if (DUK_SIGNBIT(x) == 0 || DUK_SIGNBIT(y) == 0) {
39715 			return +0.0;
39716 		} else {
39717 			return -0.0;
39718 		}
39719 	}
39720 	return duk_double_fmax(x, y);
39721 }
39722 
39723 #if defined(DUK_USE_ES6)
39724 DUK_LOCAL double duk__cbrt(double x) {
39725 	/* cbrt() is C99.  To avoid hassling embedders with the need to provide a
39726 	 * cube root function, we can get by with pow().  The result is not
39727 	 * identical, but that's OK: ES2015 says it's implementation-dependent.
39728 	 */
39729 
39730 #if defined(DUK_CBRT)
39731 	/* cbrt() matches ES2015 requirements. */
39732 	return DUK_CBRT(x);
39733 #else
39734 	duk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);
39735 
39736 	/* pow() does not, however. */
39737 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE || c == DUK_FP_ZERO) {
39738 		return x;
39739 	}
39740 	if (DUK_SIGNBIT(x)) {
39741 		return -DUK_POW(-x, 1.0 / 3.0);
39742 	} else {
39743 		return DUK_POW(x, 1.0 / 3.0);
39744 	}
39745 #endif
39746 }
39747 
39748 DUK_LOCAL double duk__log2(double x) {
39749 #if defined(DUK_LOG2)
39750 	return DUK_LOG2(x);
39751 #else
39752 	return DUK_LOG(x) * DUK_DOUBLE_LOG2E;
39753 #endif
39754 }
39755 
39756 DUK_LOCAL double duk__log10(double x) {
39757 #if defined(DUK_LOG10)
39758 	return DUK_LOG10(x);
39759 #else
39760 	return DUK_LOG(x) * DUK_DOUBLE_LOG10E;
39761 #endif
39762 }
39763 
39764 DUK_LOCAL double duk__trunc(double x) {
39765 #if defined(DUK_TRUNC)
39766 	return DUK_TRUNC(x);
39767 #else
39768 	/* Handles -0 correctly: -0.0 matches 'x >= 0.0' but floor()
39769 	 * is required to return -0 when the argument is -0.
39770 	 */
39771 	return x >= 0.0 ? DUK_FLOOR(x) : DUK_CEIL(x);
39772 #endif
39773 }
39774 #endif  /* DUK_USE_ES6 */
39775 
39776 DUK_LOCAL double duk__round_fixed(double x) {
39777 	/* Numbers half-way between integers must be rounded towards +Infinity,
39778 	 * e.g. -3.5 must be rounded to -3 (not -4).  When rounded to zero, zero
39779 	 * sign must be set appropriately.  E5.1 Section 15.8.2.15.
39780 	 *
39781 	 * Note that ANSI C round() is "round to nearest integer, away from zero",
39782 	 * which is incorrect for negative values.  Here we make do with floor().
39783 	 */
39784 
39785 	duk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);
39786 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE || c == DUK_FP_ZERO) {
39787 		return x;
39788 	}
39789 
39790 	/*
39791 	 *  x is finite and non-zero
39792 	 *
39793 	 *  -1.6 -> floor(-1.1) -> -2
39794 	 *  -1.5 -> floor(-1.0) -> -1  (towards +Inf)
39795 	 *  -1.4 -> floor(-0.9) -> -1
39796 	 *  -0.5 -> -0.0               (special case)
39797 	 *  -0.1 -> -0.0               (special case)
39798 	 *  +0.1 -> +0.0               (special case)
39799 	 *  +0.5 -> floor(+1.0) -> 1   (towards +Inf)
39800 	 *  +1.4 -> floor(+1.9) -> 1
39801 	 *  +1.5 -> floor(+2.0) -> 2   (towards +Inf)
39802 	 *  +1.6 -> floor(+2.1) -> 2
39803 	 */
39804 
39805 	if (x >= -0.5 && x < 0.5) {
39806 		/* +0.5 is handled by floor, this is on purpose */
39807 		if (x < 0.0) {
39808 			return -0.0;
39809 		} else {
39810 			return +0.0;
39811 		}
39812 	}
39813 
39814 	return DUK_FLOOR(x + 0.5);
39815 }
39816 
39817 /* Wrappers for calling standard math library methods.  These may be required
39818  * on platforms where one or more of the math built-ins are defined as macros
39819  * or inline functions and are thus not suitable to be used as function pointers.
39820  */
39821 #if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
39822 DUK_LOCAL double duk__fabs(double x) {
39823 	return DUK_FABS(x);
39824 }
39825 DUK_LOCAL double duk__acos(double x) {
39826 	return DUK_ACOS(x);
39827 }
39828 DUK_LOCAL double duk__asin(double x) {
39829 	return DUK_ASIN(x);
39830 }
39831 DUK_LOCAL double duk__atan(double x) {
39832 	return DUK_ATAN(x);
39833 }
39834 DUK_LOCAL double duk__ceil(double x) {
39835 	return DUK_CEIL(x);
39836 }
39837 DUK_LOCAL double duk__cos(double x) {
39838 	return DUK_COS(x);
39839 }
39840 DUK_LOCAL double duk__exp(double x) {
39841 	return DUK_EXP(x);
39842 }
39843 DUK_LOCAL double duk__floor(double x) {
39844 	return DUK_FLOOR(x);
39845 }
39846 DUK_LOCAL double duk__log(double x) {
39847 	return DUK_LOG(x);
39848 }
39849 DUK_LOCAL double duk__sin(double x) {
39850 	return DUK_SIN(x);
39851 }
39852 DUK_LOCAL double duk__sqrt(double x) {
39853 	return DUK_SQRT(x);
39854 }
39855 DUK_LOCAL double duk__tan(double x) {
39856 	return DUK_TAN(x);
39857 }
39858 DUK_LOCAL double duk__atan2_fixed(double x, double y) {
39859 #if defined(DUK_USE_ATAN2_WORKAROUNDS)
39860 	/* Specific fixes to common atan2() implementation issues:
39861 	 * - test-bug-mingw-math-issues.js
39862 	 */
39863 	if (DUK_ISINF(x) && DUK_ISINF(y)) {
39864 		if (DUK_SIGNBIT(x)) {
39865 			if (DUK_SIGNBIT(y)) {
39866 				return -2.356194490192345;
39867 			} else {
39868 				return -0.7853981633974483;
39869 			}
39870 		} else {
39871 			if (DUK_SIGNBIT(y)) {
39872 				return 2.356194490192345;
39873 			} else {
39874 				return 0.7853981633974483;
39875 			}
39876 		}
39877 	}
39878 #else
39879 	/* Some ISO C assumptions. */
39880 
39881 	DUK_ASSERT(duk_double_equals(DUK_ATAN2(DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY), 0.7853981633974483));
39882 	DUK_ASSERT(duk_double_equals(DUK_ATAN2(-DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY), -0.7853981633974483));
39883 	DUK_ASSERT(duk_double_equals(DUK_ATAN2(DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY), 2.356194490192345));
39884 	DUK_ASSERT(duk_double_equals(DUK_ATAN2(-DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY), -2.356194490192345));
39885 #endif
39886 
39887 	return DUK_ATAN2(x, y);
39888 }
39889 #endif  /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
39890 
39891 /* order must match constants in genbuiltins.py */
39892 DUK_LOCAL const duk__one_arg_func duk__one_arg_funcs[] = {
39893 #if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
39894 	duk__fabs,
39895 	duk__acos,
39896 	duk__asin,
39897 	duk__atan,
39898 	duk__ceil,
39899 	duk__cos,
39900 	duk__exp,
39901 	duk__floor,
39902 	duk__log,
39903 	duk__round_fixed,
39904 	duk__sin,
39905 	duk__sqrt,
39906 	duk__tan,
39907 #if defined(DUK_USE_ES6)
39908 	duk__cbrt,
39909 	duk__log2,
39910 	duk__log10,
39911 	duk__trunc
39912 #endif
39913 #else  /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
39914 	DUK_FABS,
39915 	DUK_ACOS,
39916 	DUK_ASIN,
39917 	DUK_ATAN,
39918 	DUK_CEIL,
39919 	DUK_COS,
39920 	DUK_EXP,
39921 	DUK_FLOOR,
39922 	DUK_LOG,
39923 	duk__round_fixed,
39924 	DUK_SIN,
39925 	DUK_SQRT,
39926 	DUK_TAN,
39927 #if defined(DUK_USE_ES6)
39928 	duk__cbrt,
39929 	duk__log2,
39930 	duk__log10,
39931 	duk__trunc
39932 #endif
39933 #endif  /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
39934 };
39935 
39936 /* order must match constants in genbuiltins.py */
39937 DUK_LOCAL const duk__two_arg_func duk__two_arg_funcs[] = {
39938 #if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
39939 	duk__atan2_fixed,
39940 	duk_js_arith_pow
39941 #else
39942 	duk__atan2_fixed,
39943 	duk_js_arith_pow
39944 #endif
39945 };
39946 
39947 DUK_INTERNAL duk_ret_t duk_bi_math_object_onearg_shared(duk_hthread *thr) {
39948 	duk_small_int_t fun_idx = duk_get_current_magic(thr);
39949 	duk__one_arg_func fun;
39950 	duk_double_t arg1;
39951 
39952 	DUK_ASSERT(fun_idx >= 0);
39953 	DUK_ASSERT(fun_idx < (duk_small_int_t) (sizeof(duk__one_arg_funcs) / sizeof(duk__one_arg_func)));
39954 	arg1 = duk_to_number(thr, 0);
39955 	fun = duk__one_arg_funcs[fun_idx];
39956 	duk_push_number(thr, (duk_double_t) fun((double) arg1));
39957 	return 1;
39958 }
39959 
39960 DUK_INTERNAL duk_ret_t duk_bi_math_object_twoarg_shared(duk_hthread *thr) {
39961 	duk_small_int_t fun_idx = duk_get_current_magic(thr);
39962 	duk__two_arg_func fun;
39963 	duk_double_t arg1;
39964 	duk_double_t arg2;
39965 
39966 	DUK_ASSERT(fun_idx >= 0);
39967 	DUK_ASSERT(fun_idx < (duk_small_int_t) (sizeof(duk__two_arg_funcs) / sizeof(duk__two_arg_func)));
39968 	arg1 = duk_to_number(thr, 0);  /* explicit ordered evaluation to match coercion semantics */
39969 	arg2 = duk_to_number(thr, 1);
39970 	fun = duk__two_arg_funcs[fun_idx];
39971 	duk_push_number(thr, (duk_double_t) fun((double) arg1, (double) arg2));
39972 	return 1;
39973 }
39974 
39975 DUK_INTERNAL duk_ret_t duk_bi_math_object_max(duk_hthread *thr) {
39976 	return duk__math_minmax(thr, -DUK_DOUBLE_INFINITY, duk__fmax_fixed);
39977 }
39978 
39979 DUK_INTERNAL duk_ret_t duk_bi_math_object_min(duk_hthread *thr) {
39980 	return duk__math_minmax(thr, DUK_DOUBLE_INFINITY, duk__fmin_fixed);
39981 }
39982 
39983 DUK_INTERNAL duk_ret_t duk_bi_math_object_random(duk_hthread *thr) {
39984 	duk_push_number(thr, (duk_double_t) DUK_UTIL_GET_RANDOM_DOUBLE(thr));
39985 	return 1;
39986 }
39987 
39988 #if defined(DUK_USE_ES6)
39989 DUK_INTERNAL duk_ret_t duk_bi_math_object_hypot(duk_hthread *thr) {
39990 	/*
39991 	 *  E6 Section 20.2.2.18: Math.hypot
39992 	 *
39993 	 *  - If no arguments are passed, the result is +0.
39994 	 *  - If any argument is +inf, the result is +inf.
39995 	 *  - If any argument is -inf, the result is +inf.
39996 	 *  - If no argument is +inf or -inf, and any argument is NaN, the result is
39997 	 *    NaN.
39998 	 *  - If all arguments are either +0 or -0, the result is +0.
39999 	 */
40000 
40001 	duk_idx_t nargs;
40002 	duk_idx_t i;
40003 	duk_bool_t found_nan;
40004 	duk_double_t max;
40005 	duk_double_t sum, summand;
40006 	duk_double_t comp, prelim;
40007 	duk_double_t t;
40008 
40009 	nargs = duk_get_top(thr);
40010 
40011 	/* Find the highest value.  Also ToNumber() coerces. */
40012 	max = 0.0;
40013 	found_nan = 0;
40014 	for (i = 0; i < nargs; i++) {
40015 		t = DUK_FABS(duk_to_number(thr, i));
40016 		if (DUK_FPCLASSIFY(t) == DUK_FP_NAN) {
40017 			found_nan = 1;
40018 		} else {
40019 			max = duk_double_fmax(max, t);
40020 		}
40021 	}
40022 
40023 	/* Early return cases. */
40024 	if (duk_double_equals(max, DUK_DOUBLE_INFINITY)) {
40025 		duk_push_number(thr, DUK_DOUBLE_INFINITY);
40026 		return 1;
40027 	} else if (found_nan) {
40028 		duk_push_number(thr, DUK_DOUBLE_NAN);
40029 		return 1;
40030 	} else if (duk_double_equals(max, 0.0)) {
40031 		duk_push_number(thr, 0.0);
40032 		/* Otherwise we'd divide by zero. */
40033 		return 1;
40034 	}
40035 
40036 	/* Use Kahan summation and normalize to the highest value to minimize
40037 	 * floating point rounding error and avoid overflow.
40038 	 *
40039 	 * https://en.wikipedia.org/wiki/Kahan_summation_algorithm
40040 	 */
40041 	sum = 0.0;
40042 	comp = 0.0;
40043 	for (i = 0; i < nargs; i++) {
40044 		t = DUK_FABS(duk_get_number(thr, i)) / max;
40045 		summand = (t * t) - comp;
40046 		prelim = sum + summand;
40047 		comp = (prelim - sum) - summand;
40048 		sum = prelim;
40049 	}
40050 
40051 	duk_push_number(thr, (duk_double_t) DUK_SQRT(sum) * max);
40052 	return 1;
40053 }
40054 #endif  /* DUK_USE_ES6 */
40055 
40056 #if defined(DUK_USE_ES6)
40057 DUK_INTERNAL duk_ret_t duk_bi_math_object_sign(duk_hthread *thr) {
40058 	duk_double_t d;
40059 
40060 	d = duk_to_number(thr, 0);
40061 	if (duk_double_is_nan(d)) {
40062 		DUK_ASSERT(duk_is_nan(thr, -1));
40063 		return 1;  /* NaN input -> return NaN */
40064 	}
40065 	if (duk_double_equals(d, 0.0)) {
40066 		/* Zero sign kept, i.e. -0 -> -0, +0 -> +0. */
40067 		return 1;
40068 	}
40069 	duk_push_int(thr, (d > 0.0 ? 1 : -1));
40070 	return 1;
40071 }
40072 #endif  /* DUK_USE_ES6 */
40073 
40074 #if defined(DUK_USE_ES6)
40075 DUK_INTERNAL duk_ret_t duk_bi_math_object_clz32(duk_hthread *thr) {
40076 	duk_uint32_t x;
40077 	duk_small_uint_t i;
40078 
40079 #if defined(DUK_USE_PREFER_SIZE)
40080 	duk_uint32_t mask;
40081 
40082 	x = duk_to_uint32(thr, 0);
40083 	for (i = 0, mask = 0x80000000UL; mask != 0; mask >>= 1) {
40084 		if (x & mask) {
40085 			break;
40086 		}
40087 		i++;
40088 	}
40089 	DUK_ASSERT(i <= 32);
40090 	duk_push_uint(thr, i);
40091 	return 1;
40092 #else  /* DUK_USE_PREFER_SIZE */
40093 	i = 0;
40094 	x = duk_to_uint32(thr, 0);
40095 	if (x & 0xffff0000UL) {
40096 		x >>= 16;
40097 	} else {
40098 		i += 16;
40099 	}
40100 	if (x & 0x0000ff00UL) {
40101 		x >>= 8;
40102 	} else {
40103 		i += 8;
40104 	}
40105 	if (x & 0x000000f0UL) {
40106 		x >>= 4;
40107 	} else {
40108 		i += 4;
40109 	}
40110 	if (x & 0x0000000cUL) {
40111 		x >>= 2;
40112 	} else {
40113 		i += 2;
40114 	}
40115 	if (x & 0x00000002UL) {
40116 		x >>= 1;
40117 	} else {
40118 		i += 1;
40119 	}
40120 	if (x & 0x00000001UL) {
40121 		;
40122 	} else {
40123 		i += 1;
40124 	}
40125 	DUK_ASSERT(i <= 32);
40126 	duk_push_uint(thr, i);
40127 	return 1;
40128 #endif  /* DUK_USE_PREFER_SIZE */
40129 }
40130 #endif  /* DUK_USE_ES6 */
40131 
40132 #if defined(DUK_USE_ES6)
40133 DUK_INTERNAL duk_ret_t duk_bi_math_object_imul(duk_hthread *thr) {
40134 	duk_uint32_t x, y, z;
40135 
40136 	x = duk_to_uint32(thr, 0);
40137 	y = duk_to_uint32(thr, 1);
40138 	z = x * y;
40139 
40140 	/* While arguments are ToUint32() coerced and the multiplication
40141 	 * is unsigned as such, the final result is curiously interpreted
40142 	 * as a signed 32-bit value.
40143 	 */
40144 	duk_push_i32(thr, (duk_int32_t) z);
40145 	return 1;
40146 }
40147 #endif  /* DUK_USE_ES6 */
40148 
40149 #endif  /* DUK_USE_MATH_BUILTIN */
40150 /*
40151  *  Number built-ins
40152  */
40153 
40154 /* #include duk_internal.h -> already included */
40155 
40156 #if defined(DUK_USE_NUMBER_BUILTIN)
40157 
40158 DUK_LOCAL duk_double_t duk__push_this_number_plain(duk_hthread *thr) {
40159 	duk_hobject *h;
40160 
40161 	/* Number built-in accepts a plain number or a Number object (whose
40162 	 * internal value is operated on).  Other types cause TypeError.
40163 	 */
40164 
40165 	duk_push_this(thr);
40166 	if (duk_is_number(thr, -1)) {
40167 		DUK_DDD(DUK_DDDPRINT("plain number value: %!T", (duk_tval *) duk_get_tval(thr, -1)));
40168 		goto done;
40169 	}
40170 	h = duk_get_hobject(thr, -1);
40171 	if (!h ||
40172 	    (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_NUMBER)) {
40173 		DUK_DDD(DUK_DDDPRINT("unacceptable this value: %!T", (duk_tval *) duk_get_tval(thr, -1)));
40174 		DUK_ERROR_TYPE(thr, "number expected");
40175 		DUK_WO_NORETURN(return 0.0;);
40176 	}
40177 	duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
40178 	DUK_ASSERT(duk_is_number(thr, -1));
40179 	DUK_DDD(DUK_DDDPRINT("number object: %!T, internal value: %!T",
40180 	                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
40181 	duk_remove_m2(thr);
40182 
40183  done:
40184 	return duk_get_number(thr, -1);
40185 }
40186 
40187 DUK_INTERNAL duk_ret_t duk_bi_number_constructor(duk_hthread *thr) {
40188 	duk_idx_t nargs;
40189 	duk_hobject *h_this;
40190 
40191 	/*
40192 	 *  The Number constructor uses ToNumber(arg) for number coercion
40193 	 *  (coercing an undefined argument to NaN).  However, if the
40194 	 *  argument is not given at all, +0 must be used instead.  To do
40195 	 *  this, a vararg function is used.
40196 	 */
40197 
40198 	nargs = duk_get_top(thr);
40199 	if (nargs == 0) {
40200 		duk_push_int(thr, 0);
40201 	}
40202 	duk_to_number(thr, 0);
40203 	duk_set_top(thr, 1);
40204 	DUK_ASSERT_TOP(thr, 1);
40205 
40206 	if (!duk_is_constructor_call(thr)) {
40207 		return 1;
40208 	}
40209 
40210 	/*
40211 	 *  E5 Section 15.7.2.1 requires that the constructed object
40212 	 *  must have the original Number.prototype as its internal
40213 	 *  prototype.  However, since Number.prototype is non-writable
40214 	 *  and non-configurable, this doesn't have to be enforced here:
40215 	 *  The default object (bound to 'this') is OK, though we have
40216 	 *  to change its class.
40217 	 *
40218 	 *  Internal value set to ToNumber(arg) or +0; if no arg given,
40219 	 *  ToNumber(undefined) = NaN, so special treatment is needed
40220 	 *  (above).  String internal value is immutable.
40221 	 */
40222 
40223 	/* XXX: helper */
40224 	duk_push_this(thr);
40225 	h_this = duk_known_hobject(thr, -1);
40226 	DUK_HOBJECT_SET_CLASS_NUMBER(h_this, DUK_HOBJECT_CLASS_NUMBER);
40227 
40228 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_this) == thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE]);
40229 	DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_this) == DUK_HOBJECT_CLASS_NUMBER);
40230 	DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h_this));
40231 
40232 	duk_dup_0(thr);  /* -> [ val obj val ] */
40233 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
40234 	return 0;  /* no return value -> don't replace created value */
40235 }
40236 
40237 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_value_of(duk_hthread *thr) {
40238 	(void) duk__push_this_number_plain(thr);
40239 	return 1;
40240 }
40241 
40242 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_string(duk_hthread *thr) {
40243 	duk_small_int_t radix;
40244 	duk_small_uint_t n2s_flags;
40245 
40246 	(void) duk__push_this_number_plain(thr);
40247 	if (duk_is_undefined(thr, 0)) {
40248 		radix = 10;
40249 	} else {
40250 		radix = (duk_small_int_t) duk_to_int_check_range(thr, 0, 2, 36);
40251 	}
40252 	DUK_DDD(DUK_DDDPRINT("radix=%ld", (long) radix));
40253 
40254 	n2s_flags = 0;
40255 
40256 	duk_numconv_stringify(thr,
40257 	                      radix /*radix*/,
40258 	                      0 /*digits*/,
40259 	                      n2s_flags /*flags*/);
40260 	return 1;
40261 }
40262 
40263 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_locale_string(duk_hthread *thr) {
40264 	/* XXX: just use toString() for now; permitted although not recommended.
40265 	 * nargs==1, so radix is passed to toString().
40266 	 */
40267 	return duk_bi_number_prototype_to_string(thr);
40268 }
40269 
40270 /*
40271  *  toFixed(), toExponential(), toPrecision()
40272  */
40273 
40274 /* XXX: shared helper for toFixed(), toExponential(), toPrecision()? */
40275 
40276 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_fixed(duk_hthread *thr) {
40277 	duk_small_int_t frac_digits;
40278 	duk_double_t d;
40279 	duk_small_int_t c;
40280 	duk_small_uint_t n2s_flags;
40281 
40282 	/* In ES5.1 frac_digits is coerced first; in ES2015 the 'this number
40283 	 * value' check is done first.
40284 	 */
40285 	d = duk__push_this_number_plain(thr);
40286 	frac_digits = (duk_small_int_t) duk_to_int_check_range(thr, 0, 0, 20);
40287 
40288 	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
40289 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
40290 		goto use_to_string;
40291 	}
40292 
40293 	if (d >= 1.0e21 || d <= -1.0e21) {
40294 		goto use_to_string;
40295 	}
40296 
40297 	n2s_flags = DUK_N2S_FLAG_FIXED_FORMAT |
40298 	            DUK_N2S_FLAG_FRACTION_DIGITS;
40299 
40300 	duk_numconv_stringify(thr,
40301 	                      10 /*radix*/,
40302 	                      frac_digits /*digits*/,
40303 	                      n2s_flags /*flags*/);
40304 	return 1;
40305 
40306  use_to_string:
40307 	DUK_ASSERT_TOP(thr, 2);
40308 	duk_to_string(thr, -1);
40309 	return 1;
40310 }
40311 
40312 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_exponential(duk_hthread *thr) {
40313 	duk_bool_t frac_undefined;
40314 	duk_small_int_t frac_digits;
40315 	duk_double_t d;
40316 	duk_small_int_t c;
40317 	duk_small_uint_t n2s_flags;
40318 
40319 	d = duk__push_this_number_plain(thr);
40320 
40321 	frac_undefined = duk_is_undefined(thr, 0);
40322 	duk_to_int(thr, 0);  /* for side effects */
40323 
40324 	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
40325 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
40326 		goto use_to_string;
40327 	}
40328 
40329 	frac_digits = (duk_small_int_t) duk_to_int_check_range(thr, 0, 0, 20);
40330 
40331 	n2s_flags = DUK_N2S_FLAG_FORCE_EXP |
40332 	           (frac_undefined ? 0 : DUK_N2S_FLAG_FIXED_FORMAT);
40333 
40334 	duk_numconv_stringify(thr,
40335 	                      10 /*radix*/,
40336 	                      frac_digits + 1 /*leading digit + fractions*/,
40337 	                      n2s_flags /*flags*/);
40338 	return 1;
40339 
40340  use_to_string:
40341 	DUK_ASSERT_TOP(thr, 2);
40342 	duk_to_string(thr, -1);
40343 	return 1;
40344 }
40345 
40346 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_precision(duk_hthread *thr) {
40347 	/* The specification has quite awkward order of coercion and
40348 	 * checks for toPrecision().  The operations below are a bit
40349 	 * reordered, within constraints of observable side effects.
40350 	 */
40351 
40352 	duk_double_t d;
40353 	duk_small_int_t prec;
40354 	duk_small_int_t c;
40355 	duk_small_uint_t n2s_flags;
40356 
40357 	DUK_ASSERT_TOP(thr, 1);
40358 
40359 	d = duk__push_this_number_plain(thr);
40360 	if (duk_is_undefined(thr, 0)) {
40361 		goto use_to_string;
40362 	}
40363 	DUK_ASSERT_TOP(thr, 2);
40364 
40365 	duk_to_int(thr, 0);  /* for side effects */
40366 
40367 	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
40368 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
40369 		goto use_to_string;
40370 	}
40371 
40372 	prec = (duk_small_int_t) duk_to_int_check_range(thr, 0, 1, 21);
40373 
40374 	n2s_flags = DUK_N2S_FLAG_FIXED_FORMAT |
40375 	            DUK_N2S_FLAG_NO_ZERO_PAD;
40376 
40377 	duk_numconv_stringify(thr,
40378 	                      10 /*radix*/,
40379 	                      prec /*digits*/,
40380 	                      n2s_flags /*flags*/);
40381 	return 1;
40382 
40383  use_to_string:
40384 	/* Used when precision is undefined; also used for NaN (-> "NaN"),
40385 	 * and +/- infinity (-> "Infinity", "-Infinity").
40386 	 */
40387 
40388 	DUK_ASSERT_TOP(thr, 2);
40389 	duk_to_string(thr, -1);
40390 	return 1;
40391 }
40392 
40393 /*
40394  *  ES2015 isFinite() etc
40395  */
40396 
40397 #if defined(DUK_USE_ES6)
40398 DUK_INTERNAL duk_ret_t duk_bi_number_check_shared(duk_hthread *thr) {
40399 	duk_int_t magic;
40400 	duk_bool_t ret = 0;
40401 
40402 	if (duk_is_number(thr, 0)) {
40403 		duk_double_t d;
40404 
40405 		magic = duk_get_current_magic(thr);
40406 		d = duk_get_number(thr, 0);
40407 
40408 		switch (magic) {
40409 		case 0:  /* isFinite() */
40410 			ret = duk_double_is_finite(d);
40411 			break;
40412 		case 1:  /* isInteger() */
40413 			ret = duk_double_is_integer(d);
40414 			break;
40415 		case 2:  /* isNaN() */
40416 			ret = duk_double_is_nan(d);
40417 			break;
40418 		default:  /* isSafeInteger() */
40419 			DUK_ASSERT(magic == 3);
40420 			ret = duk_double_is_safe_integer(d);
40421 		}
40422 	}
40423 
40424 	duk_push_boolean(thr, ret);
40425 	return 1;
40426 }
40427 #endif  /* DUK_USE_ES6 */
40428 
40429 #endif  /* DUK_USE_NUMBER_BUILTIN */
40430 /*
40431  *  Object built-ins
40432  */
40433 
40434 /* #include duk_internal.h -> already included */
40435 
40436 /* Needed even when Object built-in disabled. */
40437 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_to_string(duk_hthread *thr) {
40438 	duk_tval *tv;
40439 
40440 	tv = DUK_HTHREAD_THIS_PTR(thr);
40441 	duk_push_class_string_tval(thr, tv, 0 /*avoid_side_effects*/);
40442 	return 1;
40443 }
40444 
40445 #if defined(DUK_USE_OBJECT_BUILTIN)
40446 DUK_INTERNAL duk_ret_t duk_bi_object_constructor(duk_hthread *thr) {
40447 	duk_uint_t arg_mask;
40448 
40449 	arg_mask = duk_get_type_mask(thr, 0);
40450 
40451 	if (!duk_is_constructor_call(thr) &&  /* not a constructor call */
40452 	    ((arg_mask & (DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_UNDEFINED)) == 0)) {  /* and argument not null or undefined */
40453 		duk_to_object(thr, 0);
40454 		return 1;
40455 	}
40456 
40457 	/* Pointer and buffer primitive values are treated like other
40458 	 * primitives values which have a fully fledged object counterpart:
40459 	 * promote to an object value.  Lightfuncs and plain buffers are
40460 	 * coerced with ToObject() even they could also be returned as is.
40461 	 */
40462 	if (arg_mask & (DUK_TYPE_MASK_OBJECT |
40463 	                DUK_TYPE_MASK_STRING |
40464 	                DUK_TYPE_MASK_BOOLEAN |
40465 	                DUK_TYPE_MASK_NUMBER |
40466 	                DUK_TYPE_MASK_POINTER |
40467 	                DUK_TYPE_MASK_BUFFER |
40468 	                DUK_TYPE_MASK_LIGHTFUNC)) {
40469 		/* For DUK_TYPE_OBJECT the coercion is a no-op and could
40470 		 * be checked for explicitly, but Object(obj) calls are
40471 		 * not very common so opt for minimal footprint.
40472 		 */
40473 		duk_to_object(thr, 0);
40474 		return 1;
40475 	}
40476 
40477 	(void) duk_push_object_helper(thr,
40478 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
40479 	                              DUK_HOBJECT_FLAG_FASTREFS |
40480 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
40481 	                              DUK_BIDX_OBJECT_PROTOTYPE);
40482 	return 1;
40483 }
40484 #endif  /* DUK_USE_OBJECT_BUILTIN */
40485 
40486 #if defined(DUK_USE_OBJECT_BUILTIN) && defined(DUK_USE_ES6)
40487 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_assign(duk_hthread *thr) {
40488 	duk_idx_t nargs;
40489 	duk_int_t idx;
40490 
40491 	nargs = duk_get_top_require_min(thr, 1 /*min_top*/);
40492 
40493 	duk_to_object(thr, 0);
40494 	for (idx = 1; idx < nargs; idx++) {
40495 		/* E7 19.1.2.1 (step 4a) */
40496 		if (duk_is_null_or_undefined(thr, idx)) {
40497 			continue;
40498 		}
40499 
40500 		/* duk_enum() respects ES2015+ [[OwnPropertyKeys]] ordering, which is
40501 		 * convenient here.
40502 		 */
40503 		duk_to_object(thr, idx);
40504 		duk_enum(thr, idx, DUK_ENUM_OWN_PROPERTIES_ONLY);
40505 		while (duk_next(thr, -1, 1 /*get_value*/)) {
40506 			/* [ target ... enum key value ] */
40507 			duk_put_prop(thr, 0);
40508 			/* [ target ... enum ] */
40509 		}
40510 		/* Could pop enumerator, but unnecessary because of duk_set_top()
40511 		 * below.
40512 		 */
40513 	}
40514 
40515 	duk_set_top(thr, 1);
40516 	return 1;
40517 }
40518 #endif
40519 
40520 #if defined(DUK_USE_OBJECT_BUILTIN) && defined(DUK_USE_ES6)
40521 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is(duk_hthread *thr) {
40522 	DUK_ASSERT_TOP(thr, 2);
40523 	duk_push_boolean(thr, duk_samevalue(thr, 0, 1));
40524 	return 1;
40525 }
40526 #endif
40527 
40528 #if defined(DUK_USE_OBJECT_BUILTIN)
40529 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_create(duk_hthread *thr) {
40530 	duk_hobject *proto;
40531 
40532 	DUK_ASSERT_TOP(thr, 2);
40533 
40534 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
40535 	duk_hbufobj_promote_plain(thr, 0);
40536 #endif
40537 	proto = duk_require_hobject_accept_mask(thr, 0, DUK_TYPE_MASK_NULL);
40538 	DUK_ASSERT(proto != NULL || duk_is_null(thr, 0));
40539 
40540 	(void) duk_push_object_helper_proto(thr,
40541 	                                    DUK_HOBJECT_FLAG_EXTENSIBLE |
40542 	                                    DUK_HOBJECT_FLAG_FASTREFS |
40543 	                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
40544 	                                    proto);
40545 
40546 	if (!duk_is_undefined(thr, 1)) {
40547 		/* [ O Properties obj ] */
40548 
40549 		duk_replace(thr, 0);
40550 
40551 		/* [ obj Properties ] */
40552 
40553 		/* Just call the "original" Object.defineProperties() to
40554 		 * finish up.
40555 		 */
40556 
40557 		return duk_bi_object_constructor_define_properties(thr);
40558 	}
40559 
40560 	/* [ O Properties obj ] */
40561 
40562 	return 1;
40563 }
40564 #endif  /* DUK_USE_OBJECT_BUILTIN */
40565 
40566 #if defined(DUK_USE_OBJECT_BUILTIN)
40567 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_properties(duk_hthread *thr) {
40568 	duk_small_uint_t pass;
40569 	duk_uint_t defprop_flags;
40570 	duk_hobject *obj;
40571 	duk_idx_t idx_value;
40572 	duk_hobject *get;
40573 	duk_hobject *set;
40574 
40575 	/* Lightfunc and plain buffer handling by ToObject() coercion. */
40576 	obj = duk_require_hobject_promote_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
40577 	DUK_ASSERT(obj != NULL);
40578 
40579 	duk_to_object(thr, 1);        /* properties object */
40580 
40581 	DUK_DDD(DUK_DDDPRINT("target=%!iT, properties=%!iT",
40582 	                     (duk_tval *) duk_get_tval(thr, 0),
40583 	                     (duk_tval *) duk_get_tval(thr, 1)));
40584 
40585 	/*
40586 	 *  Two pass approach to processing the property descriptors.
40587 	 *  On first pass validate and normalize all descriptors before
40588 	 *  any changes are made to the target object.  On second pass
40589 	 *  make the actual modifications to the target object.
40590 	 *
40591 	 *  Right now we'll just use the same normalize/validate helper
40592 	 *  on both passes, ignoring its outputs on the first pass.
40593 	 */
40594 
40595 	for (pass = 0; pass < 2; pass++) {
40596 		duk_set_top(thr, 2);  /* -> [ hobject props ] */
40597 		duk_enum(thr, 1, DUK_ENUM_OWN_PROPERTIES_ONLY | DUK_ENUM_INCLUDE_SYMBOLS /*enum_flags*/);
40598 
40599 		for (;;) {
40600 			duk_hstring *key;
40601 
40602 			/* [ hobject props enum(props) ] */
40603 
40604 			duk_set_top(thr, 3);
40605 
40606 			if (!duk_next(thr, 2, 1 /*get_value*/)) {
40607 				break;
40608 			}
40609 
40610 			DUK_DDD(DUK_DDDPRINT("-> key=%!iT, desc=%!iT",
40611 			                     (duk_tval *) duk_get_tval(thr, -2),
40612 			                     (duk_tval *) duk_get_tval(thr, -1)));
40613 
40614 			/* [ hobject props enum(props) key desc ] */
40615 
40616 			duk_hobject_prepare_property_descriptor(thr,
40617 			                                        4 /*idx_desc*/,
40618 			                                        &defprop_flags,
40619 			                                        &idx_value,
40620 			                                        &get,
40621 			                                        &set);
40622 
40623 			/* [ hobject props enum(props) key desc [multiple values] ] */
40624 
40625 			if (pass == 0) {
40626 				continue;
40627 			}
40628 
40629 			/* This allows symbols on purpose. */
40630 			key = duk_known_hstring(thr, 3);
40631 			DUK_ASSERT(key != NULL);
40632 
40633 			duk_hobject_define_property_helper(thr,
40634 			                                   defprop_flags,
40635 			                                   obj,
40636 			                                   key,
40637 			                                   idx_value,
40638 			                                   get,
40639 			                                   set,
40640 			                                   1 /*throw_flag*/);
40641 		}
40642 	}
40643 
40644 	/*
40645 	 *  Return target object
40646 	 */
40647 
40648 	duk_dup_0(thr);
40649 	return 1;
40650 }
40651 #endif  /* DUK_USE_OBJECT_BUILTIN */
40652 
40653 #if defined(DUK_USE_OBJECT_BUILTIN)
40654 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_hthread *thr) {
40655 	DUK_ASSERT_TOP(thr, 1);
40656 
40657 	duk_seal_freeze_raw(thr, 0, (duk_bool_t) duk_get_current_magic(thr) /*is_freeze*/);
40658 	return 1;
40659 }
40660 #endif  /* DUK_USE_OBJECT_BUILTIN */
40661 
40662 #if defined(DUK_USE_OBJECT_BUILTIN)
40663 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_hthread *thr) {
40664 	duk_hobject *h;
40665 	duk_bool_t is_frozen;
40666 	duk_uint_t mask;
40667 
40668 	is_frozen = (duk_bool_t) duk_get_current_magic(thr);
40669 	mask = duk_get_type_mask(thr, 0);
40670 	if (mask & (DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER)) {
40671 		DUK_ASSERT(is_frozen == 0 || is_frozen == 1);
40672 		duk_push_boolean(thr, (mask & DUK_TYPE_MASK_LIGHTFUNC) ?
40673 		                          1 :               /* lightfunc always frozen and sealed */
40674 		                          (is_frozen ^ 1)); /* buffer sealed but not frozen (index props writable) */
40675 	} else {
40676 		/* ES2015 Sections 19.1.2.12, 19.1.2.13: anything other than an object
40677 		 * is considered to be already sealed and frozen.
40678 		 */
40679 		h = duk_get_hobject(thr, 0);
40680 		duk_push_boolean(thr, (h == NULL) ||
40681 		                      duk_hobject_object_is_sealed_frozen_helper(thr, h, is_frozen /*is_frozen*/));
40682 	}
40683 	return 1;
40684 }
40685 #endif  /* DUK_USE_OBJECT_BUILTIN */
40686 
40687 #if defined(DUK_USE_OBJECT_BUILTIN)
40688 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_to_locale_string(duk_hthread *thr) {
40689 	DUK_ASSERT_TOP(thr, 0);
40690 	(void) duk_push_this_coercible_to_object(thr);
40691 	duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_TO_STRING);
40692 #if 0  /* This is mentioned explicitly in the E5.1 spec, but duk_call_method() checks for it in practice. */
40693 	duk_require_callable(thr, 1);
40694 #endif
40695 	duk_dup_0(thr);  /* -> [ O toString O ] */
40696 	duk_call_method(thr, 0);  /* XXX: call method tail call? */
40697 	return 1;
40698 }
40699 #endif  /* DUK_USE_OBJECT_BUILTIN */
40700 
40701 #if defined(DUK_USE_OBJECT_BUILTIN)
40702 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_value_of(duk_hthread *thr) {
40703 	/* For lightfuncs and plain buffers, returns Object() coerced. */
40704 	(void) duk_push_this_coercible_to_object(thr);
40705 	return 1;
40706 }
40707 #endif  /* DUK_USE_OBJECT_BUILTIN */
40708 
40709 #if defined(DUK_USE_OBJECT_BUILTIN)
40710 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_hthread *thr) {
40711 	duk_hobject *h_v;
40712 	duk_hobject *h_obj;
40713 
40714 	DUK_ASSERT_TOP(thr, 1);
40715 
40716 	h_v = duk_get_hobject(thr, 0);
40717 	if (!h_v) {
40718 		duk_push_false(thr);  /* XXX: tail call: return duk_push_false(thr) */
40719 		return 1;
40720 	}
40721 
40722 	h_obj = duk_push_this_coercible_to_object(thr);
40723 	DUK_ASSERT(h_obj != NULL);
40724 
40725 	/* E5.1 Section 15.2.4.6, step 3.a, lookup proto once before compare.
40726 	 * Prototype loops should cause an error to be thrown.
40727 	 */
40728 	duk_push_boolean(thr, duk_hobject_prototype_chain_contains(thr, DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_v), h_obj, 0 /*ignore_loop*/));
40729 	return 1;
40730 }
40731 #endif  /* DUK_USE_OBJECT_BUILTIN */
40732 
40733 #if defined(DUK_USE_OBJECT_BUILTIN)
40734 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_has_own_property(duk_hthread *thr) {
40735 	return (duk_ret_t) duk_hobject_object_ownprop_helper(thr, 0 /*required_desc_flags*/);
40736 }
40737 #endif  /* DUK_USE_OBJECT_BUILTIN */
40738 
40739 #if defined(DUK_USE_OBJECT_BUILTIN)
40740 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_hthread *thr) {
40741 	return (duk_ret_t) duk_hobject_object_ownprop_helper(thr, DUK_PROPDESC_FLAG_ENUMERABLE /*required_desc_flags*/);
40742 }
40743 #endif  /* DUK_USE_OBJECT_BUILTIN */
40744 
40745 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
40746 /* Shared helper to implement Object.getPrototypeOf,
40747  * Object.prototype.__proto__ getter, and Reflect.getPrototypeOf.
40748  *
40749  * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__
40750  */
40751 DUK_INTERNAL duk_ret_t duk_bi_object_getprototype_shared(duk_hthread *thr) {
40752 	/*
40753 	 *  magic = 0: __proto__ getter
40754 	 *  magic = 1: Object.getPrototypeOf()
40755 	 *  magic = 2: Reflect.getPrototypeOf()
40756 	 */
40757 
40758 	duk_hobject *h;
40759 	duk_hobject *proto;
40760 	duk_tval *tv;
40761 	duk_int_t magic;
40762 
40763 	magic = duk_get_current_magic(thr);
40764 
40765 	if (magic == 0) {
40766 		DUK_ASSERT_TOP(thr, 0);
40767 		duk_push_this_coercible_to_object(thr);
40768 	}
40769 	DUK_ASSERT(duk_get_top(thr) >= 1);
40770 	if (magic < 2) {
40771 		/* ES2015 Section 19.1.2.9, step 1 */
40772 		duk_to_object(thr, 0);
40773 	}
40774 	tv = DUK_GET_TVAL_POSIDX(thr, 0);
40775 
40776 	switch (DUK_TVAL_GET_TAG(tv)) {
40777 	case DUK_TAG_BUFFER:
40778 		proto = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
40779 		break;
40780 	case DUK_TAG_LIGHTFUNC:
40781 		proto = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
40782 		break;
40783 	case DUK_TAG_OBJECT:
40784 		h = DUK_TVAL_GET_OBJECT(tv);
40785 		proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
40786 		break;
40787 	default:
40788 		/* This implicitly handles CheckObjectCoercible() caused
40789 		 * TypeError.
40790 		 */
40791 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
40792 	}
40793 	if (proto != NULL) {
40794 		duk_push_hobject(thr, proto);
40795 	} else {
40796 		duk_push_null(thr);
40797 	}
40798 	return 1;
40799 }
40800 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
40801 
40802 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
40803 /* Shared helper to implement ES2015 Object.setPrototypeOf,
40804  * Object.prototype.__proto__ setter, and Reflect.setPrototypeOf.
40805  *
40806  * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__
40807  * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-object.setprototypeof
40808  */
40809 DUK_INTERNAL duk_ret_t duk_bi_object_setprototype_shared(duk_hthread *thr) {
40810 	/*
40811 	 *  magic = 0: __proto__ setter
40812 	 *  magic = 1: Object.setPrototypeOf()
40813 	 *  magic = 2: Reflect.setPrototypeOf()
40814 	 */
40815 
40816 	duk_hobject *h_obj;
40817 	duk_hobject *h_new_proto;
40818 	duk_hobject *h_curr;
40819 	duk_ret_t ret_success = 1;  /* retval for success path */
40820 	duk_uint_t mask;
40821 	duk_int_t magic;
40822 
40823 	/* Preliminaries for __proto__ and setPrototypeOf (E6 19.1.2.18 steps 1-4). */
40824 	magic = duk_get_current_magic(thr);
40825 	if (magic == 0) {
40826 		duk_push_this_check_object_coercible(thr);
40827 		duk_insert(thr, 0);
40828 		if (!duk_check_type_mask(thr, 1, DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_OBJECT)) {
40829 			return 0;
40830 		}
40831 
40832 		/* __proto__ setter returns 'undefined' on success unlike the
40833 		 * setPrototypeOf() call which returns the target object.
40834 		 */
40835 		ret_success = 0;
40836 	} else {
40837 		if (magic == 1) {
40838 			duk_require_object_coercible(thr, 0);
40839 		} else {
40840 			duk_require_hobject_accept_mask(thr, 0,
40841 			                                DUK_TYPE_MASK_LIGHTFUNC |
40842 			                                DUK_TYPE_MASK_BUFFER);
40843 		}
40844 		duk_require_type_mask(thr, 1, DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_OBJECT);
40845 	}
40846 
40847 	h_new_proto = duk_get_hobject(thr, 1);
40848 	/* h_new_proto may be NULL */
40849 
40850 	mask = duk_get_type_mask(thr, 0);
40851 	if (mask & (DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER)) {
40852 		duk_hobject *curr_proto;
40853 		curr_proto = thr->builtins[(mask & DUK_TYPE_MASK_LIGHTFUNC) ?
40854 		                               DUK_BIDX_FUNCTION_PROTOTYPE :
40855 		                               DUK_BIDX_UINT8ARRAY_PROTOTYPE];
40856 		if (h_new_proto == curr_proto) {
40857 			goto skip;
40858 		}
40859 		goto fail_nonextensible;
40860 	}
40861 	h_obj = duk_get_hobject(thr, 0);
40862 	if (h_obj == NULL) {
40863 		goto skip;
40864 	}
40865 	DUK_ASSERT(h_obj != NULL);
40866 
40867 	/* [[SetPrototypeOf]] standard behavior, E6 9.1.2. */
40868 	/* TODO: implement Proxy object support here */
40869 
40870 	if (h_new_proto == DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_obj)) {
40871 		goto skip;
40872 	}
40873 	if (!DUK_HOBJECT_HAS_EXTENSIBLE(h_obj)) {
40874 		goto fail_nonextensible;
40875 	}
40876 	for (h_curr = h_new_proto; h_curr != NULL; h_curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_curr)) {
40877 		/* Loop prevention. */
40878 		if (h_curr == h_obj) {
40879 			goto fail_loop;
40880 		}
40881 	}
40882 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h_obj, h_new_proto);
40883 	/* fall thru */
40884 
40885  skip:
40886 	duk_set_top(thr, 1);
40887 	if (magic == 2) {
40888 		duk_push_true(thr);
40889 	}
40890 	return ret_success;
40891 
40892  fail_nonextensible:
40893  fail_loop:
40894 	if (magic != 2) {
40895 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
40896 	} else {
40897 		duk_push_false(thr);
40898 		return 1;
40899 	}
40900 }
40901 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
40902 
40903 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
40904 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_property(duk_hthread *thr) {
40905 	/*
40906 	 *  magic = 0: Object.defineProperty()
40907 	 *  magic = 1: Reflect.defineProperty()
40908 	 */
40909 
40910 	duk_hobject *obj;
40911 	duk_hstring *key;
40912 	duk_hobject *get;
40913 	duk_hobject *set;
40914 	duk_idx_t idx_value;
40915 	duk_uint_t defprop_flags;
40916 	duk_small_uint_t magic;
40917 	duk_bool_t throw_flag;
40918 	duk_bool_t ret;
40919 
40920 	DUK_ASSERT(thr != NULL);
40921 
40922 	DUK_DDD(DUK_DDDPRINT("Object.defineProperty(): ctx=%p obj=%!T key=%!T desc=%!T",
40923 	                     (void *) thr,
40924 	                     (duk_tval *) duk_get_tval(thr, 0),
40925 	                     (duk_tval *) duk_get_tval(thr, 1),
40926 	                     (duk_tval *) duk_get_tval(thr, 2)));
40927 
40928 	/* [ obj key desc ] */
40929 
40930 	magic = (duk_small_uint_t) duk_get_current_magic(thr);
40931 
40932 	/* Lightfuncs are currently supported by coercing to a temporary
40933 	 * Function object; changes will be allowed (the coerced value is
40934 	 * extensible) but will be lost.  Same for plain buffers.
40935 	 */
40936 	obj = duk_require_hobject_promote_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
40937 	DUK_ASSERT(obj != NULL);
40938 	key = duk_to_property_key_hstring(thr, 1);
40939 	(void) duk_require_hobject(thr, 2);
40940 
40941 	DUK_ASSERT(obj != NULL);
40942 	DUK_ASSERT(key != NULL);
40943 	DUK_ASSERT(duk_get_hobject(thr, 2) != NULL);
40944 
40945 	/*
40946 	 *  Validate and convert argument property descriptor (an ECMAScript
40947 	 *  object) into a set of defprop_flags and possibly property value,
40948 	 *  getter, and/or setter values on the value stack.
40949 	 *
40950 	 *  Lightfunc set/get values are coerced to full Functions.
40951 	 */
40952 
40953 	duk_hobject_prepare_property_descriptor(thr,
40954 	                                        2 /*idx_desc*/,
40955 	                                        &defprop_flags,
40956 	                                        &idx_value,
40957 	                                        &get,
40958 	                                        &set);
40959 
40960 	/*
40961 	 *  Use Object.defineProperty() helper for the actual operation.
40962 	 */
40963 
40964 	DUK_ASSERT(magic == 0U || magic == 1U);
40965 	throw_flag = magic ^ 1U;
40966 	ret = duk_hobject_define_property_helper(thr,
40967 	                                         defprop_flags,
40968 	                                         obj,
40969 	                                         key,
40970 	                                         idx_value,
40971 	                                         get,
40972 	                                         set,
40973 	                                         throw_flag);
40974 
40975 	/* Ignore the normalize/validate helper outputs on the value stack,
40976 	 * they're popped automatically.
40977 	 */
40978 
40979 	if (magic == 0U) {
40980 		/* Object.defineProperty(): return target object. */
40981 		duk_push_hobject(thr, obj);
40982 	} else {
40983 		/* Reflect.defineProperty(): return success/fail. */
40984 		duk_push_boolean(thr, ret);
40985 	}
40986 	return 1;
40987 }
40988 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
40989 
40990 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
40991 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_hthread *thr) {
40992 	DUK_ASSERT_TOP(thr, 2);
40993 
40994 	/* ES2015 Section 19.1.2.6, step 1 */
40995 	if (duk_get_current_magic(thr) == 0) {
40996 		duk_to_object(thr, 0);
40997 	}
40998 
40999 	/* [ obj key ] */
41000 
41001 	duk_hobject_object_get_own_property_descriptor(thr, -2);
41002 	return 1;
41003 }
41004 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
41005 
41006 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
41007 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_extensible(duk_hthread *thr) {
41008 	/*
41009 	 *  magic = 0: Object.isExtensible()
41010 	 *  magic = 1: Reflect.isExtensible()
41011 	 */
41012 
41013 	duk_hobject *h;
41014 
41015 	if (duk_get_current_magic(thr) == 0) {
41016 		h = duk_get_hobject(thr, 0);
41017 	} else {
41018 		/* Reflect.isExtensible(): throw if non-object, but we accept lightfuncs
41019 		 * and plain buffers here because they pretend to be objects.
41020 		 */
41021 		h = duk_require_hobject_accept_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
41022 	}
41023 
41024 	duk_push_boolean(thr, (h != NULL) && DUK_HOBJECT_HAS_EXTENSIBLE(h));
41025 	return 1;
41026 }
41027 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
41028 
41029 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
41030 /* Shared helper for various key/symbol listings, magic:
41031  * 0=Object.keys()
41032  * 1=Object.getOwnPropertyNames(),
41033  * 2=Object.getOwnPropertySymbols(),
41034  * 3=Reflect.ownKeys()
41035  */
41036 DUK_LOCAL const duk_small_uint_t duk__object_keys_enum_flags[4] = {
41037 	/* Object.keys() */
41038 	DUK_ENUM_OWN_PROPERTIES_ONLY |
41039 	    DUK_ENUM_NO_PROXY_BEHAVIOR,
41040 
41041 	/* Object.getOwnPropertyNames() */
41042 	DUK_ENUM_INCLUDE_NONENUMERABLE |
41043 	    DUK_ENUM_OWN_PROPERTIES_ONLY |
41044 	    DUK_ENUM_NO_PROXY_BEHAVIOR,
41045 
41046 	/* Object.getOwnPropertySymbols() */
41047 	DUK_ENUM_INCLUDE_SYMBOLS |
41048 	    DUK_ENUM_OWN_PROPERTIES_ONLY |
41049 	    DUK_ENUM_EXCLUDE_STRINGS |
41050 	    DUK_ENUM_INCLUDE_NONENUMERABLE |
41051 	    DUK_ENUM_NO_PROXY_BEHAVIOR,
41052 
41053 	/* Reflect.ownKeys() */
41054 	DUK_ENUM_INCLUDE_SYMBOLS |
41055 	    DUK_ENUM_OWN_PROPERTIES_ONLY |
41056 	    DUK_ENUM_INCLUDE_NONENUMERABLE |
41057 	    DUK_ENUM_NO_PROXY_BEHAVIOR
41058 };
41059 
41060 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_keys_shared(duk_hthread *thr) {
41061 	duk_hobject *obj;
41062 #if defined(DUK_USE_ES6_PROXY)
41063 	duk_hobject *h_proxy_target;
41064 	duk_hobject *h_proxy_handler;
41065 	duk_hobject *h_trap_result;
41066 #endif
41067 	duk_small_uint_t enum_flags;
41068 	duk_int_t magic;
41069 
41070 	DUK_ASSERT_TOP(thr, 1);
41071 
41072 	magic = duk_get_current_magic(thr);
41073 	if (magic == 3) {
41074 		/* ES2015 Section 26.1.11 requires a TypeError for non-objects.  Lightfuncs
41075 		 * and plain buffers pretend to be objects, so accept those too.
41076 		 */
41077 		obj = duk_require_hobject_promote_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
41078 	} else {
41079 		/* ES2015: ToObject coerce. */
41080 		obj = duk_to_hobject(thr, 0);
41081 	}
41082 	DUK_ASSERT(obj != NULL);
41083 	DUK_UNREF(obj);
41084 
41085 	/* XXX: proxy chains */
41086 
41087 #if defined(DUK_USE_ES6_PROXY)
41088 	/* XXX: better sharing of code between proxy target call sites */
41089 	if (DUK_LIKELY(!duk_hobject_proxy_check(obj,
41090 	                                        &h_proxy_target,
41091 	                                        &h_proxy_handler))) {
41092 		goto skip_proxy;
41093 	}
41094 
41095 	duk_push_hobject(thr, h_proxy_handler);
41096 	if (!duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_OWN_KEYS)) {
41097 		/* Careful with reachability here: don't pop 'obj' before pushing
41098 		 * proxy target.
41099 		 */
41100 		DUK_DDD(DUK_DDDPRINT("no ownKeys trap, get keys of target instead"));
41101 		duk_pop_2(thr);
41102 		duk_push_hobject(thr, h_proxy_target);
41103 		duk_replace(thr, 0);
41104 		DUK_ASSERT_TOP(thr, 1);
41105 		goto skip_proxy;
41106 	}
41107 
41108 	/* [ obj handler trap ] */
41109 	duk_insert(thr, -2);
41110 	duk_push_hobject(thr, h_proxy_target);  /* -> [ obj trap handler target ] */
41111 	duk_call_method(thr, 1 /*nargs*/);      /* -> [ obj trap_result ] */
41112 	h_trap_result = duk_require_hobject(thr, -1);
41113 	DUK_UNREF(h_trap_result);
41114 
41115 	magic = duk_get_current_magic(thr);
41116 	DUK_ASSERT(magic >= 0 && magic < (duk_int_t) (sizeof(duk__object_keys_enum_flags) / sizeof(duk_small_uint_t)));
41117 	enum_flags = duk__object_keys_enum_flags[magic];
41118 
41119 	duk_proxy_ownkeys_postprocess(thr, h_proxy_target, enum_flags);
41120 	return 1;
41121 
41122  skip_proxy:
41123 #endif  /* DUK_USE_ES6_PROXY */
41124 
41125 	DUK_ASSERT_TOP(thr, 1);
41126 	magic = duk_get_current_magic(thr);
41127 	DUK_ASSERT(magic >= 0 && magic < (duk_int_t) (sizeof(duk__object_keys_enum_flags) / sizeof(duk_small_uint_t)));
41128 	enum_flags = duk__object_keys_enum_flags[magic];
41129 	return duk_hobject_get_enumerated_keys(thr, enum_flags);
41130 }
41131 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
41132 
41133 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
41134 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_hthread *thr) {
41135 	/*
41136 	 *  magic = 0: Object.preventExtensions()
41137 	 *  magic = 1: Reflect.preventExtensions()
41138 	 */
41139 
41140 	duk_hobject *h;
41141 	duk_uint_t mask;
41142 	duk_int_t magic;
41143 
41144 	magic = duk_get_current_magic(thr);
41145 
41146 	/* Silent success for lightfuncs and plain buffers always. */
41147 	mask = DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER;
41148 
41149 	/* Object.preventExtensions() silent success for non-object. */
41150 	if (magic == 0) {
41151 		mask |= DUK_TYPE_MASK_UNDEFINED |
41152 		        DUK_TYPE_MASK_NULL |
41153 		        DUK_TYPE_MASK_BOOLEAN |
41154 		        DUK_TYPE_MASK_NUMBER |
41155 		        DUK_TYPE_MASK_STRING |
41156 		        DUK_TYPE_MASK_POINTER;
41157 	}
41158 
41159 	if (duk_check_type_mask(thr, 0, mask)) {
41160 		/* Not an object, already non-extensible so always success. */
41161 		goto done;
41162 	}
41163 	h = duk_require_hobject(thr, 0);
41164 	DUK_ASSERT(h != NULL);
41165 
41166 	DUK_HOBJECT_CLEAR_EXTENSIBLE(h);
41167 
41168 	/* A non-extensible object cannot gain any more properties,
41169 	 * so this is a good time to compact.
41170 	 */
41171 	duk_hobject_compact_props(thr, h);
41172 
41173  done:
41174 	if (magic == 1) {
41175 		duk_push_true(thr);
41176 	}
41177 	return 1;
41178 }
41179 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
41180 
41181 /*
41182  *  __defineGetter__, __defineSetter__, __lookupGetter__, __lookupSetter__
41183  */
41184 
41185 #if defined(DUK_USE_ES8)
41186 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_defineaccessor(duk_hthread *thr) {
41187 	duk_push_this(thr);
41188 	duk_insert(thr, 0);
41189 	duk_to_object(thr, 0);
41190 	duk_require_callable(thr, 2);
41191 
41192 	/* [ ToObject(this) key getter/setter ] */
41193 
41194 	/* ToPropertyKey() coercion is not needed, duk_def_prop() does it. */
41195 	duk_def_prop(thr, 0, DUK_DEFPROP_SET_ENUMERABLE |
41196 	                     DUK_DEFPROP_SET_CONFIGURABLE |
41197 	                     (duk_get_current_magic(thr) ? DUK_DEFPROP_HAVE_SETTER : DUK_DEFPROP_HAVE_GETTER));
41198 	return 0;
41199 }
41200 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_lookupaccessor(duk_hthread *thr) {
41201 	duk_uint_t sanity;
41202 
41203 	duk_push_this(thr);
41204 	duk_to_object(thr, -1);
41205 
41206 	/* XXX: Prototype walk (with sanity) should be a core property
41207 	 * operation, could add a flag to e.g. duk_get_prop_desc().
41208 	 */
41209 
41210 	/* ToPropertyKey() coercion is not needed, duk_get_prop_desc() does it. */
41211 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
41212 	while (!duk_is_undefined(thr, -1)) {
41213 		/* [ key obj ] */
41214 		duk_dup(thr, 0);
41215 		duk_get_prop_desc(thr, 1, 0 /*flags*/);
41216 		if (!duk_is_undefined(thr, -1)) {
41217 			duk_get_prop_stridx(thr, -1, (duk_get_current_magic(thr) != 0 ? DUK_STRIDX_SET : DUK_STRIDX_GET));
41218 			return 1;
41219 		}
41220 		duk_pop(thr);
41221 
41222 		if (DUK_UNLIKELY(sanity-- == 0)) {
41223 			DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
41224 			DUK_WO_NORETURN(return 0;);
41225 		}
41226 
41227 		duk_get_prototype(thr, -1);
41228 		duk_remove(thr, -2);
41229 	}
41230 	return 1;
41231 }
41232 #endif  /* DUK_USE_ES8 */
41233 /*
41234  *  High resolution time API (performance.now() et al)
41235  *
41236  *  API specification: https://encoding.spec.whatwg.org/#ap://www.w3.org/TR/hr-time/
41237  */
41238 
41239 /* #include duk_internal.h -> already included */
41240 
41241 #if defined(DUK_USE_PERFORMANCE_BUILTIN)
41242 DUK_INTERNAL duk_ret_t duk_bi_performance_now(duk_hthread *thr) {
41243 	/* From API spec:
41244 	 * The DOMHighResTimeStamp type is used to store a time value in
41245 	 * milliseconds, measured relative from the time origin, global
41246 	 * monotonic clock, or a time value that represents a duration
41247 	 * between two DOMHighResTimeStamp's.
41248 	 */
41249 	duk_push_number(thr, duk_time_get_monotonic_time(thr));
41250 	return 1;
41251 }
41252 
41253 #if 0  /* Missing until semantics decided. */
41254 DUK_INTERNAL duk_ret_t duk_bi_performance_timeorigin_getter(duk_hthread *thr) {
41255 	/* No decision yet how to handle timeOrigins, e.g. should one be
41256 	 * initialized per heap, or per global object set.  See
41257 	 * https://www.w3.org/TR/hr-time/#time-origin.
41258 	 */
41259 	duk_push_uint(thr, 0);
41260 	return 1;
41261 }
41262 #endif  /* 0 */
41263 #endif  /* DUK_USE_PERFORMANCE_BUILTIN */
41264 /*
41265  *  Pointer built-ins
41266  */
41267 
41268 /* #include duk_internal.h -> already included */
41269 
41270 /*
41271  *  Constructor
41272  */
41273 
41274 DUK_INTERNAL duk_ret_t duk_bi_pointer_constructor(duk_hthread *thr) {
41275 	/* XXX: this behavior is quite useless now; it would be nice to be able
41276 	 * to create pointer values from e.g. numbers or strings.  Numbers are
41277 	 * problematic on 64-bit platforms though.  Hex encoded strings?
41278 	 */
41279 	if (duk_get_top(thr) == 0) {
41280 		duk_push_pointer(thr, NULL);
41281 	} else {
41282 		duk_to_pointer(thr, 0);
41283 	}
41284 	DUK_ASSERT(duk_is_pointer(thr, 0));
41285 	duk_set_top(thr, 1);
41286 
41287 	if (duk_is_constructor_call(thr)) {
41288 		(void) duk_push_object_helper(thr,
41289 		                              DUK_HOBJECT_FLAG_EXTENSIBLE |
41290 		                              DUK_HOBJECT_FLAG_FASTREFS |
41291 		                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER),
41292 		                              DUK_BIDX_POINTER_PROTOTYPE);
41293 
41294 		/* Pointer object internal value is immutable. */
41295 		duk_dup_0(thr);
41296 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
41297 	}
41298 	/* Note: unbalanced stack on purpose */
41299 
41300 	return 1;
41301 }
41302 
41303 /*
41304  *  toString(), valueOf()
41305  */
41306 
41307 DUK_INTERNAL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_hthread *thr) {
41308 	duk_tval *tv;
41309 	duk_small_int_t to_string = duk_get_current_magic(thr);
41310 
41311 	duk_push_this(thr);
41312 	tv = duk_require_tval(thr, -1);
41313 	DUK_ASSERT(tv != NULL);
41314 
41315 	if (DUK_TVAL_IS_POINTER(tv)) {
41316 		/* nop */
41317 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
41318 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
41319 		DUK_ASSERT(h != NULL);
41320 
41321 		/* Must be a "pointer object", i.e. class "Pointer" */
41322 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_POINTER) {
41323 			goto type_error;
41324 		}
41325 
41326 		duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
41327 	} else {
41328 		goto type_error;
41329 	}
41330 
41331 	if (to_string) {
41332 		duk_to_string(thr, -1);
41333 	}
41334 	return 1;
41335 
41336  type_error:
41337 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
41338 }
41339 /*
41340  *  Promise built-in
41341  */
41342 
41343 /* #include duk_internal.h -> already included */
41344 
41345 #if defined(DUK_USE_PROMISE_BUILTIN)
41346 
41347 DUK_INTERNAL duk_ret_t duk_bi_promise_constructor(duk_hthread *thr) {
41348 	DUK_ERROR_TYPE(thr, "unimplemented");
41349 	DUK_WO_NORETURN(return 0;);
41350 }
41351 
41352 DUK_INTERNAL duk_ret_t duk_bi_promise_all(duk_hthread *thr) {
41353 	DUK_ERROR_TYPE(thr, "unimplemented");
41354 	DUK_WO_NORETURN(return 0;);
41355 }
41356 
41357 DUK_INTERNAL duk_ret_t duk_bi_promise_race(duk_hthread *thr) {
41358 	DUK_ERROR_TYPE(thr, "unimplemented");
41359 	DUK_WO_NORETURN(return 0;);
41360 }
41361 
41362 DUK_INTERNAL duk_ret_t duk_bi_promise_reject(duk_hthread *thr) {
41363 	DUK_ERROR_TYPE(thr, "unimplemented");
41364 	DUK_WO_NORETURN(return 0;);
41365 }
41366 
41367 DUK_INTERNAL duk_ret_t duk_bi_promise_resolve(duk_hthread *thr) {
41368 	DUK_ERROR_TYPE(thr, "unimplemented");
41369 	DUK_WO_NORETURN(return 0;);
41370 }
41371 
41372 DUK_INTERNAL duk_ret_t duk_bi_promise_catch(duk_hthread *thr) {
41373 	DUK_ERROR_TYPE(thr, "unimplemented");
41374 	DUK_WO_NORETURN(return 0;);
41375 }
41376 
41377 DUK_INTERNAL duk_ret_t duk_bi_promise_then(duk_hthread *thr) {
41378 	DUK_ERROR_TYPE(thr, "unimplemented");
41379 	DUK_WO_NORETURN(return 0;);
41380 }
41381 
41382 #endif  /* DUK_USE_PROMISE_BUILTIN */
41383 /*
41384  *  Proxy built-in (ES2015)
41385  */
41386 
41387 /* #include duk_internal.h -> already included */
41388 
41389 #if defined(DUK_USE_ES6_PROXY)
41390 /* Post-process a Proxy ownKeys() result at stack top.  Push a cleaned up
41391  * array of valid result keys (strings or symbols).  TypeError for invalid
41392  * values.  Flags are shared with duk_enum().
41393  */
41394 DUK_INTERNAL void duk_proxy_ownkeys_postprocess(duk_hthread *thr, duk_hobject *h_proxy_target, duk_uint_t flags) {
41395 	duk_uarridx_t i, len, idx;
41396 	duk_propdesc desc;
41397 
41398 	DUK_CTX_ASSERT_VALID(thr);
41399 	DUK_ASSERT(h_proxy_target != NULL);
41400 
41401 	len = (duk_uarridx_t) duk_get_length(thr, -1);
41402 	idx = 0;
41403 	duk_push_array(thr);
41404 	/* XXX: preallocated dense array, fill in directly */
41405 	for (i = 0; i < len; i++) {
41406 		duk_hstring *h;
41407 
41408 		/* [ obj trap_result res_arr ] */
41409 		(void) duk_get_prop_index(thr, -2, i);
41410 		h = duk_get_hstring(thr, -1);
41411 		if (h == NULL) {
41412 			DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr);
41413 			DUK_WO_NORETURN(return;);
41414 		}
41415 
41416 		if (!(flags & DUK_ENUM_INCLUDE_NONENUMERABLE)) {
41417 			/* No support for 'getOwnPropertyDescriptor' trap yet,
41418 			 * so check enumerability always from target object
41419 			 * descriptor.
41420 			 */
41421 			if (duk_hobject_get_own_propdesc(thr, h_proxy_target, duk_known_hstring(thr, -1), &desc, 0 /*flags*/)) {
41422 				if ((desc.flags & DUK_PROPDESC_FLAG_ENUMERABLE) == 0) {
41423 					DUK_DDD(DUK_DDDPRINT("ignore non-enumerable property: %!T", duk_get_tval(thr, -1)));
41424 					goto skip_key;
41425 				}
41426 			} else {
41427 				DUK_DDD(DUK_DDDPRINT("ignore non-existent property: %!T", duk_get_tval(thr, -1)));
41428 				goto skip_key;
41429 			}
41430 		}
41431 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
41432 			if (!(flags & DUK_ENUM_INCLUDE_SYMBOLS)) {
41433 				DUK_DDD(DUK_DDDPRINT("ignore symbol property: %!T", duk_get_tval(thr, -1)));
41434 				goto skip_key;
41435 			}
41436 			if (DUK_HSTRING_HAS_HIDDEN(h) && !(flags & DUK_ENUM_INCLUDE_HIDDEN)) {
41437 				DUK_DDD(DUK_DDDPRINT("ignore hidden symbol property: %!T", duk_get_tval(thr, -1)));
41438 				goto skip_key;
41439 			}
41440 		} else {
41441 			if (flags & DUK_ENUM_EXCLUDE_STRINGS) {
41442 				DUK_DDD(DUK_DDDPRINT("ignore string property: %!T", duk_get_tval(thr, -1)));
41443 				goto skip_key;
41444 			}
41445 		}
41446 
41447 		/* [ obj trap_result res_arr propname ] */
41448 		duk_push_uarridx(thr, idx++);
41449 		duk_insert(thr, -2);
41450 		duk_def_prop(thr, -3, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_SET_WEC);
41451 		continue;
41452 
41453 	 skip_key:
41454 		duk_pop(thr);
41455 		continue;
41456 	}
41457 
41458 	/* XXX: Missing trap result validation for non-configurable target keys
41459 	 * (must be present), for non-extensible target all target keys must be
41460 	 * present and no extra keys can be present.
41461 	 * http://www.ecma-international.org/ecma-262/6.0/#sec-proxy-object-internal-methods-and-internal-slots-ownpropertykeys
41462 	 */
41463 
41464 	/* XXX: The key enumerability check should trigger the "getOwnPropertyDescriptor"
41465 	 * trap which has not yet been implemented.  In the absence of such a trap,
41466 	 * the enumerability should be checked from the target object; this is
41467 	 * handled above.
41468 	 */
41469 }
41470 #endif  /* DUK_USE_ES6_PROXY */
41471 
41472 #if defined(DUK_USE_ES6_PROXY)
41473 DUK_INTERNAL duk_ret_t duk_bi_proxy_constructor(duk_hthread *thr) {
41474 	DUK_ASSERT_TOP(thr, 2);  /* [ target handler ] */
41475 
41476 	duk_require_constructor_call(thr);
41477 	duk_push_proxy(thr, 0 /*flags*/);  /* [ target handler ] -> [ proxy ] */
41478 	return 1;  /* replacement */
41479 }
41480 #endif  /* DUK_USE_ES6_PROXY */
41481 /*
41482  *  'Reflect' built-in (ES2016 Section 26.1)
41483  *  http://www.ecma-international.org/ecma-262/7.0/#sec-reflect-object
41484  *
41485  *  Many Reflect built-in functions are provided by shared helpers in
41486  *  duk_bi_object.c or duk_bi_function.c.
41487  */
41488 
41489 /* #include duk_internal.h -> already included */
41490 
41491 #if defined(DUK_USE_REFLECT_BUILTIN)
41492 DUK_INTERNAL duk_ret_t duk_bi_reflect_object_delete_property(duk_hthread *thr) {
41493 	duk_tval *tv_obj;
41494 	duk_tval *tv_key;
41495 	duk_bool_t ret;
41496 
41497 	DUK_ASSERT_TOP(thr, 2);
41498 	(void) duk_require_hobject(thr, 0);
41499 	(void) duk_to_string(thr, 1);
41500 
41501 	/* [ target key ] */
41502 
41503 	DUK_ASSERT(thr != NULL);
41504 	tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
41505 	tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
41506 	ret = duk_hobject_delprop(thr, tv_obj, tv_key, 0 /*throw_flag*/);
41507 	duk_push_boolean(thr, ret);
41508 	return 1;
41509 }
41510 
41511 DUK_INTERNAL duk_ret_t duk_bi_reflect_object_get(duk_hthread *thr) {
41512 	duk_tval *tv_obj;
41513 	duk_tval *tv_key;
41514 	duk_idx_t nargs;
41515 
41516 	DUK_ASSERT(thr != NULL);
41517 	nargs = duk_get_top_require_min(thr, 2 /*min_top*/);
41518 	(void) duk_require_hobject(thr, 0);
41519 	(void) duk_to_string(thr, 1);
41520 	if (nargs >= 3 && !duk_strict_equals(thr, 0, 2)) {
41521 		/* XXX: [[Get]] receiver currently unsupported */
41522 		DUK_ERROR_UNSUPPORTED(thr);
41523 		DUK_WO_NORETURN(return 0;);
41524 	}
41525 
41526 	/* [ target key receiver? ...? ] */
41527 
41528 	tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
41529 	tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
41530 	(void) duk_hobject_getprop(thr, tv_obj, tv_key);  /* This could also be a duk_get_prop(). */
41531 	return 1;
41532 }
41533 
41534 DUK_INTERNAL duk_ret_t duk_bi_reflect_object_has(duk_hthread *thr) {
41535 	duk_tval *tv_obj;
41536 	duk_tval *tv_key;
41537 	duk_bool_t ret;
41538 
41539 	DUK_ASSERT(thr != NULL);
41540 	DUK_ASSERT_TOP(thr, 2);
41541 	(void) duk_require_hobject(thr, 0);
41542 	(void) duk_to_string(thr, 1);
41543 
41544 	/* [ target key ] */
41545 
41546 	tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
41547 	tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
41548 	ret = duk_hobject_hasprop(thr, tv_obj, tv_key);
41549 	duk_push_boolean(thr, ret);
41550 	return 1;
41551 }
41552 
41553 DUK_INTERNAL duk_ret_t duk_bi_reflect_object_set(duk_hthread *thr) {
41554 	duk_tval *tv_obj;
41555 	duk_tval *tv_key;
41556 	duk_tval *tv_val;
41557 	duk_idx_t nargs;
41558 	duk_bool_t ret;
41559 
41560 	DUK_ASSERT(thr != NULL);
41561 	nargs = duk_get_top_require_min(thr, 3 /*min_top*/);
41562 	(void) duk_require_hobject(thr, 0);
41563 	(void) duk_to_string(thr, 1);
41564 	if (nargs >= 4 && !duk_strict_equals(thr, 0, 3)) {
41565 		/* XXX: [[Set]] receiver currently unsupported */
41566 		DUK_ERROR_UNSUPPORTED(thr);
41567 		DUK_WO_NORETURN(return 0;);
41568 	}
41569 
41570 	/* [ target key value receiver? ...? ] */
41571 
41572 	tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
41573 	tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
41574 	tv_val = DUK_GET_TVAL_POSIDX(thr, 2);
41575 	ret = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, 0 /*throw_flag*/);
41576 	duk_push_boolean(thr, ret);
41577 	return 1;
41578 }
41579 #endif  /* DUK_USE_REFLECT_BUILTIN */
41580 /*
41581  *  RegExp built-ins
41582  */
41583 
41584 /* #include duk_internal.h -> already included */
41585 
41586 #if defined(DUK_USE_REGEXP_SUPPORT)
41587 
41588 DUK_LOCAL void duk__get_this_regexp(duk_hthread *thr) {
41589 	duk_hobject *h;
41590 
41591 	duk_push_this(thr);
41592 	h = duk_require_hobject_with_class(thr, -1, DUK_HOBJECT_CLASS_REGEXP);
41593 	DUK_ASSERT(h != NULL);
41594 	DUK_UNREF(h);
41595 	duk_insert(thr, 0);  /* prepend regexp to valstack 0 index */
41596 }
41597 
41598 /* XXX: much to improve (code size) */
41599 DUK_INTERNAL duk_ret_t duk_bi_regexp_constructor(duk_hthread *thr) {
41600 	duk_hobject *h_pattern;
41601 
41602 	DUK_ASSERT_TOP(thr, 2);
41603 	h_pattern = duk_get_hobject(thr, 0);
41604 
41605 	if (!duk_is_constructor_call(thr) &&
41606 	    h_pattern != NULL &&
41607 	    DUK_HOBJECT_GET_CLASS_NUMBER(h_pattern) == DUK_HOBJECT_CLASS_REGEXP &&
41608 	    duk_is_undefined(thr, 1)) {
41609 		/* Called as a function, pattern has [[Class]] "RegExp" and
41610 		 * flags is undefined -> return object as is.
41611 		 */
41612 		/* XXX: ES2015 has a NewTarget SameValue() check which is not
41613 		 * yet implemented.
41614 		 */
41615 		duk_dup_0(thr);
41616 		return 1;
41617 	}
41618 
41619 	/* Else functionality is identical for function call and constructor
41620 	 * call.
41621 	 */
41622 
41623 	if (h_pattern != NULL &&
41624 	    DUK_HOBJECT_GET_CLASS_NUMBER(h_pattern) == DUK_HOBJECT_CLASS_REGEXP) {
41625 		duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_SOURCE);
41626 		if (duk_is_undefined(thr, 1)) {
41627 			/* In ES5 one would need to read the flags individually;
41628 			 * in ES2015 just read .flags.
41629 			 */
41630 			duk_get_prop_stridx(thr, 0, DUK_STRIDX_FLAGS);
41631 		} else {
41632 			/* In ES2015 allowed; overrides argument RegExp flags. */
41633 			duk_dup_1(thr);
41634 		}
41635 	} else {
41636 		if (duk_is_undefined(thr, 0)) {
41637 			duk_push_hstring_empty(thr);
41638 		} else {
41639 			duk_dup_0(thr);
41640 			duk_to_string(thr, -1);  /* Rejects Symbols. */
41641 		}
41642 		if (duk_is_undefined(thr, 1)) {
41643 			duk_push_hstring_empty(thr);
41644 		} else {
41645 			duk_dup_1(thr);
41646 			duk_to_string(thr, -1);  /* Rejects Symbols. */
41647 		}
41648 
41649 		/* [ ... pattern flags ] */
41650 	}
41651 
41652 	DUK_DDD(DUK_DDDPRINT("RegExp constructor/function call, pattern=%!T, flags=%!T",
41653 	                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
41654 
41655 	/* [ ... pattern flags ] (both uncoerced) */
41656 
41657 	duk_to_string(thr, -2);
41658 	duk_to_string(thr, -1);
41659 	duk_regexp_compile(thr);
41660 
41661 	/* [ ... bytecode escaped_source ] */
41662 
41663 	duk_regexp_create_instance(thr);
41664 
41665 	/* [ ... RegExp ] */
41666 
41667 	return 1;
41668 }
41669 
41670 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_exec(duk_hthread *thr) {
41671 	duk__get_this_regexp(thr);
41672 
41673 	/* [ regexp input ] */
41674 
41675 	duk_regexp_match(thr);
41676 
41677 	/* [ result ] */
41678 
41679 	return 1;
41680 }
41681 
41682 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_test(duk_hthread *thr) {
41683 	duk__get_this_regexp(thr);
41684 
41685 	/* [ regexp input ] */
41686 
41687 	/* result object is created and discarded; wasteful but saves code space */
41688 	duk_regexp_match(thr);
41689 
41690 	/* [ result ] */
41691 
41692 	duk_push_boolean(thr, (duk_is_null(thr, -1) ? 0 : 1));
41693 
41694 	return 1;
41695 }
41696 
41697 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_tostring(duk_hthread *thr) {
41698 	/* This must be generic in ES2015 and later. */
41699 	DUK_ASSERT_TOP(thr, 0);
41700 	duk_push_this(thr);
41701 	duk_push_literal(thr, "/");
41702 	duk_get_prop_stridx(thr, 0, DUK_STRIDX_SOURCE);
41703 	duk_dup_m2(thr);  /* another "/" */
41704 	duk_get_prop_stridx(thr, 0, DUK_STRIDX_FLAGS);
41705 	duk_concat(thr, 4);
41706 	return 1;
41707 }
41708 
41709 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_flags(duk_hthread *thr) {
41710 	/* .flags is ES2015 but present even when ES2015 bindings are
41711 	 * disabled because the constructor relies on it.
41712 	 */
41713 	duk_uint8_t buf[8];  /* enough for all flags + NUL */
41714 	duk_uint8_t *p = buf;
41715 
41716 	/* .flags is generic and works on any object. */
41717 	duk_push_this(thr);
41718 	(void) duk_require_hobject(thr, -1);
41719 	if (duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_GLOBAL, NULL)) {
41720 		*p++ = DUK_ASC_LC_G;
41721 	}
41722 	if (duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_IGNORE_CASE, NULL)) {
41723 		*p++ = DUK_ASC_LC_I;
41724 	}
41725 	if (duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_MULTILINE, NULL)) {
41726 		*p++ = DUK_ASC_LC_M;
41727 	}
41728 	/* .unicode: to be added */
41729 	/* .sticky: to be added */
41730 	*p++ = DUK_ASC_NUL;
41731 	DUK_ASSERT((duk_size_t) (p - buf) <= sizeof(buf));
41732 
41733 	duk_push_string(thr, (const char *) buf);
41734 	return 1;
41735 }
41736 
41737 /* Shared helper for providing .source, .global, .multiline, etc getters. */
41738 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_shared_getter(duk_hthread *thr) {
41739 	duk_hstring *h_bc;
41740 	duk_small_uint_t re_flags;
41741 	duk_hobject *h;
41742 	duk_int_t magic;
41743 
41744 	DUK_ASSERT_TOP(thr, 0);
41745 
41746 	duk_push_this(thr);
41747 	h = duk_require_hobject(thr, -1);
41748 	magic = duk_get_current_magic(thr);
41749 
41750 	if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_REGEXP) {
41751 		duk_xget_owndataprop_stridx_short(thr, 0, DUK_STRIDX_INT_SOURCE);
41752 		duk_xget_owndataprop_stridx_short(thr, 0, DUK_STRIDX_INT_BYTECODE);
41753 		h_bc = duk_require_hstring(thr, -1);
41754 		re_flags = (duk_small_uint_t) DUK_HSTRING_GET_DATA(h_bc)[0];  /* Safe even if h_bc length is 0 (= NUL) */
41755 		duk_pop(thr);
41756 	} else if (h == thr->builtins[DUK_BIDX_REGEXP_PROTOTYPE]) {
41757 		/* In ES2015 and ES2016 a TypeError would be thrown here.
41758 		 * However, this had real world issues so ES2017 draft
41759 		 * allows RegExp.prototype specifically, returning '(?:)'
41760 		 * for .source and undefined for all flags.
41761 		 */
41762 		if (magic != 16 /* .source */) {
41763 			return 0;
41764 		}
41765 		duk_push_literal(thr, "(?:)");  /* .source handled by switch-case */
41766 		re_flags = 0;
41767 	} else {
41768 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
41769 	}
41770 
41771 	/* [ regexp source ] */
41772 
41773 	switch (magic) {
41774 	case 0: {  /* global */
41775 		duk_push_boolean(thr, (re_flags & DUK_RE_FLAG_GLOBAL));
41776 		break;
41777 	}
41778 	case 1: {  /* ignoreCase */
41779 		duk_push_boolean(thr, (re_flags & DUK_RE_FLAG_IGNORE_CASE));
41780 		break;
41781 	}
41782 	case 2: {  /* multiline */
41783 		duk_push_boolean(thr, (re_flags & DUK_RE_FLAG_MULTILINE));
41784 		break;
41785 	}
41786 #if 0
41787 	/* Don't provide until implemented to avoid interfering with feature
41788 	 * detection in user code.
41789 	 */
41790 	case 3:    /* sticky */
41791 	case 4: {  /* unicode */
41792 		duk_push_false(thr);
41793 		break;
41794 	}
41795 #endif
41796 	default: {  /* source */
41797 		/* leave 'source' on top */
41798 		break;
41799 	}
41800 	}
41801 
41802 	return 1;
41803 }
41804 
41805 #endif  /* DUK_USE_REGEXP_SUPPORT */
41806 /*
41807  *  String built-ins
41808  *
41809  *  Most String built-ins must only accept strings (or String objects).
41810  *  Symbols, represented internally as strings, must be generally rejected.
41811  *  The duk_push_this_coercible_to_string() helper does this automatically.
41812  */
41813 
41814 /* XXX: There are several limitations in the current implementation for
41815  * strings with >= 0x80000000UL characters.  In some cases one would need
41816  * to be able to represent the range [-0xffffffff,0xffffffff] and so on.
41817  * Generally character and byte length are assumed to fit into signed 32
41818  * bits (< 0x80000000UL).  Places with issues are not marked explicitly
41819  * below in all cases, look for signed type usage (duk_int_t etc) for
41820  * offsets/lengths.
41821  */
41822 
41823 /* #include duk_internal.h -> already included */
41824 
41825 #if defined(DUK_USE_STRING_BUILTIN)
41826 
41827 /*
41828  *  Helpers
41829  */
41830 
41831 DUK_LOCAL duk_hstring *duk__str_tostring_notregexp(duk_hthread *thr, duk_idx_t idx) {
41832 	duk_hstring *h;
41833 
41834 	if (duk_get_class_number(thr, idx) == DUK_HOBJECT_CLASS_REGEXP) {
41835 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
41836 		DUK_WO_NORETURN(return NULL;);
41837 	}
41838 	h = duk_to_hstring(thr, idx);
41839 	DUK_ASSERT(h != NULL);
41840 
41841 	return h;
41842 }
41843 
41844 DUK_LOCAL duk_int_t duk__str_search_shared(duk_hthread *thr, duk_hstring *h_this, duk_hstring *h_search, duk_int_t start_cpos, duk_bool_t backwards) {
41845 	duk_int_t cpos;
41846 	duk_int_t bpos;
41847 	const duk_uint8_t *p_start, *p_end, *p;
41848 	const duk_uint8_t *q_start;
41849 	duk_int_t q_blen;
41850 	duk_uint8_t firstbyte;
41851 	duk_uint8_t t;
41852 
41853 	cpos = start_cpos;
41854 
41855 	/* Empty searchstring always matches; cpos must be clamped here.
41856 	 * (If q_blen were < 0 due to clamped coercion, it would also be
41857 	 * caught here.)
41858 	 */
41859 	q_start = DUK_HSTRING_GET_DATA(h_search);
41860 	q_blen = (duk_int_t) DUK_HSTRING_GET_BYTELEN(h_search);
41861 	if (q_blen <= 0) {
41862 		return cpos;
41863 	}
41864 	DUK_ASSERT(q_blen > 0);
41865 
41866 	bpos = (duk_int_t) duk_heap_strcache_offset_char2byte(thr, h_this, (duk_uint32_t) cpos);
41867 
41868 	p_start = DUK_HSTRING_GET_DATA(h_this);
41869 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_this);
41870 	p = p_start + bpos;
41871 
41872 	/* This loop is optimized for size.  For speed, there should be
41873 	 * two separate loops, and we should ensure that memcmp() can be
41874 	 * used without an extra "will searchstring fit" check.  Doing
41875 	 * the preconditioning for 'p' and 'p_end' is easy but cpos
41876 	 * must be updated if 'p' is wound back (backward scanning).
41877 	 */
41878 
41879 	firstbyte = q_start[0];  /* leading byte of match string */
41880 	while (p <= p_end && p >= p_start) {
41881 		t = *p;
41882 
41883 		/* For ECMAScript strings, this check can only match for
41884 		 * initial UTF-8 bytes (not continuation bytes).  For other
41885 		 * strings all bets are off.
41886 		 */
41887 
41888 		if ((t == firstbyte) && ((duk_size_t) (p_end - p) >= (duk_size_t) q_blen)) {
41889 			DUK_ASSERT(q_blen > 0);
41890 			if (duk_memcmp((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
41891 				return cpos;
41892 			}
41893 		}
41894 
41895 		/* track cpos while scanning */
41896 		if (backwards) {
41897 			/* when going backwards, we decrement cpos 'early';
41898 			 * 'p' may point to a continuation byte of the char
41899 			 * at offset 'cpos', but that's OK because we'll
41900 			 * backtrack all the way to the initial byte.
41901 			 */
41902 			if ((t & 0xc0) != 0x80) {
41903 				cpos--;
41904 			}
41905 			p--;
41906 		} else {
41907 			if ((t & 0xc0) != 0x80) {
41908 				cpos++;
41909 			}
41910 			p++;
41911 		}
41912 	}
41913 
41914 	/* Not found.  Empty string case is handled specially above. */
41915 	return -1;
41916 }
41917 
41918 /*
41919  *  Constructor
41920  */
41921 
41922 DUK_INTERNAL duk_ret_t duk_bi_string_constructor(duk_hthread *thr) {
41923 	duk_hstring *h;
41924 	duk_uint_t flags;
41925 
41926 	/* String constructor needs to distinguish between an argument not given at all
41927 	 * vs. given as 'undefined'.  We're a vararg function to handle this properly.
41928 	 */
41929 
41930 	/* XXX: copy current activation flags to thr, including current magic,
41931 	 * is_constructor_call etc.  This takes a few bytes in duk_hthread but
41932 	 * makes call sites smaller (there are >30 is_constructor_call and get
41933 	 * current magic call sites.
41934 	 */
41935 
41936 	if (duk_get_top(thr) == 0) {
41937 		duk_push_hstring_empty(thr);
41938 	} else {
41939 		h = duk_to_hstring_acceptsymbol(thr, 0);
41940 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h) && !duk_is_constructor_call(thr))) {
41941 			duk_push_symbol_descriptive_string(thr, h);
41942 			duk_replace(thr, 0);
41943 		}
41944 	}
41945 	duk_to_string(thr, 0);  /* catches symbol argument for constructor call */
41946 	DUK_ASSERT(duk_is_string(thr, 0));
41947 	duk_set_top(thr, 1);  /* Top may be 1 or larger. */
41948 
41949 	if (duk_is_constructor_call(thr)) {
41950 		/* String object internal value is immutable */
41951 		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
41952 		        DUK_HOBJECT_FLAG_FASTREFS |
41953 		        DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ |
41954 		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_STRING);
41955 		duk_push_object_helper(thr, flags, DUK_BIDX_STRING_PROTOTYPE);
41956 		duk_dup_0(thr);
41957 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
41958 	}
41959 	/* Note: unbalanced stack on purpose */
41960 
41961 	return 1;
41962 }
41963 
41964 DUK_LOCAL duk_ret_t duk__construct_from_codepoints(duk_hthread *thr, duk_bool_t nonbmp) {
41965 	duk_bufwriter_ctx bw_alloc;
41966 	duk_bufwriter_ctx *bw;
41967 	duk_idx_t i, n;
41968 	duk_ucodepoint_t cp;
41969 
41970 	/* XXX: It would be nice to build the string directly but ToUint16()
41971 	 * coercion is needed so a generic helper would not be very
41972 	 * helpful (perhaps coerce the value stack first here and then
41973 	 * build a string from a duk_tval number sequence in one go?).
41974 	 */
41975 
41976 	n = duk_get_top(thr);
41977 
41978 	bw = &bw_alloc;
41979 	DUK_BW_INIT_PUSHBUF(thr, bw, (duk_size_t) n);  /* initial estimate for ASCII only codepoints */
41980 
41981 	for (i = 0; i < n; i++) {
41982 		/* XXX: could improve bufwriter handling to write multiple codepoints
41983 		 * with one ensure call but the relative benefit would be quite small.
41984 		 */
41985 
41986 		if (nonbmp) {
41987 			/* ES2015 requires that (1) SameValue(cp, ToInteger(cp)) and
41988 			 * (2) cp >= 0 and cp <= 0x10ffff.  This check does not
41989 			 * implement the steps exactly but the outcome should be
41990 			 * the same.
41991 			 */
41992 			duk_int32_t i32 = 0;
41993 			if (!duk_is_whole_get_int32(duk_to_number(thr, i), &i32) ||
41994 			    i32 < 0 || i32 > 0x10ffffL) {
41995 				DUK_DCERROR_RANGE_INVALID_ARGS(thr);
41996 			}
41997 			DUK_ASSERT(i32 >= 0 && i32 <= 0x10ffffL);
41998 			cp = (duk_ucodepoint_t) i32;
41999 			DUK_BW_WRITE_ENSURE_CESU8(thr, bw, cp);
42000 		} else {
42001 #if defined(DUK_USE_NONSTD_STRING_FROMCHARCODE_32BIT)
42002 			/* ToUint16() coercion is mandatory in the E5.1 specification, but
42003 			 * this non-compliant behavior makes more sense because we support
42004 			 * non-BMP codepoints.  Don't use CESU-8 because that'd create
42005 			 * surrogate pairs.
42006 			 */
42007 			cp = (duk_ucodepoint_t) duk_to_uint32(thr, i);
42008 			DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp);
42009 #else
42010 			cp = (duk_ucodepoint_t) duk_to_uint16(thr, i);
42011 			DUK_ASSERT(cp >= 0 && cp <= 0x10ffffL);
42012 			DUK_BW_WRITE_ENSURE_CESU8(thr, bw, cp);
42013 #endif
42014 		}
42015 	}
42016 
42017 	DUK_BW_COMPACT(thr, bw);
42018 	(void) duk_buffer_to_string(thr, -1);  /* Safe, extended UTF-8 or CESU-8 encoded. */
42019 	return 1;
42020 }
42021 
42022 DUK_INTERNAL duk_ret_t duk_bi_string_constructor_from_char_code(duk_hthread *thr) {
42023 	return duk__construct_from_codepoints(thr, 0 /*nonbmp*/);
42024 }
42025 
42026 #if defined(DUK_USE_ES6)
42027 DUK_INTERNAL duk_ret_t duk_bi_string_constructor_from_code_point(duk_hthread *thr) {
42028 	return duk__construct_from_codepoints(thr, 1 /*nonbmp*/);
42029 }
42030 #endif
42031 
42032 /*
42033  *  toString(), valueOf()
42034  */
42035 
42036 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_to_string(duk_hthread *thr) {
42037 	duk_tval *tv;
42038 
42039 	duk_push_this(thr);
42040 	tv = duk_require_tval(thr, -1);
42041 	DUK_ASSERT(tv != NULL);
42042 
42043 	if (DUK_TVAL_IS_STRING(tv)) {
42044 		/* return as is */
42045 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
42046 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
42047 		DUK_ASSERT(h != NULL);
42048 
42049 		/* Must be a "string object", i.e. class "String" */
42050 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_STRING) {
42051 			goto type_error;
42052 		}
42053 
42054 		duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
42055 		DUK_ASSERT(duk_is_string(thr, -1));
42056 	} else {
42057 		goto type_error;
42058 	}
42059 
42060 	(void) duk_require_hstring_notsymbol(thr, -1);  /* Reject symbols (and wrapped symbols). */
42061 	return 1;
42062 
42063  type_error:
42064 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
42065 }
42066 
42067 /*
42068  *  Character and charcode access
42069  */
42070 
42071 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_char_at(duk_hthread *thr) {
42072 	duk_hstring *h;
42073 	duk_int_t pos;
42074 
42075 	/* XXX: faster implementation */
42076 
42077 	h = duk_push_this_coercible_to_string(thr);
42078 	DUK_ASSERT(h != NULL);
42079 
42080 	pos = duk_to_int(thr, 0);
42081 
42082 	if (sizeof(duk_size_t) >= sizeof(duk_uint_t)) {
42083 		/* Cast to duk_size_t works in this case:
42084 		 * - If pos < 0, (duk_size_t) pos will always be
42085 		 *   >= max_charlen, and result will be the empty string
42086 		 *   (see duk_substring()).
42087 		 * - If pos >= 0, pos + 1 cannot wrap.
42088 		 */
42089 		DUK_ASSERT((duk_size_t) DUK_INT_MIN >= DUK_HSTRING_MAX_BYTELEN);
42090 		DUK_ASSERT((duk_size_t) DUK_INT_MAX + 1U > (duk_size_t) DUK_INT_MAX);
42091 		duk_substring(thr, -1, (duk_size_t) pos, (duk_size_t) pos + 1U);
42092 	} else {
42093 		/* If size_t is smaller than int, explicit bounds checks
42094 		 * are needed because an int may wrap multiple times.
42095 		 */
42096 		if (DUK_UNLIKELY(pos < 0 || (duk_uint_t) pos >= (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h))) {
42097 			duk_push_hstring_empty(thr);
42098 		} else {
42099 			duk_substring(thr, -1, (duk_size_t) pos, (duk_size_t) pos + 1U);
42100 		}
42101 	}
42102 
42103 	return 1;
42104 }
42105 
42106 /* Magic: 0=charCodeAt, 1=codePointAt */
42107 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_char_code_at(duk_hthread *thr) {
42108 	duk_int_t pos;
42109 	duk_hstring *h;
42110 	duk_bool_t clamped;
42111 	duk_uint32_t cp;
42112 	duk_int_t magic;
42113 
42114 	/* XXX: faster implementation */
42115 
42116 	DUK_DDD(DUK_DDDPRINT("arg=%!T", (duk_tval *) duk_get_tval(thr, 0)));
42117 
42118 	h = duk_push_this_coercible_to_string(thr);
42119 	DUK_ASSERT(h != NULL);
42120 
42121 	pos = duk_to_int_clamped_raw(thr,
42122 	                             0 /*index*/,
42123 	                             0 /*min(incl)*/,
42124 	                             (duk_int_t) DUK_HSTRING_GET_CHARLEN(h) - 1 /*max(incl)*/,
42125 	                             &clamped /*out_clamped*/);
42126 #if defined(DUK_USE_ES6)
42127 	magic = duk_get_current_magic(thr);
42128 #else
42129 	DUK_ASSERT(duk_get_current_magic(thr) == 0);
42130 	magic = 0;
42131 #endif
42132 	if (clamped) {
42133 		/* For out-of-bounds indices .charCodeAt() returns NaN and
42134 		 * .codePointAt() returns undefined.
42135 		 */
42136 		if (magic != 0) {
42137 			return 0;
42138 		}
42139 		duk_push_nan(thr);
42140 	} else {
42141 		DUK_ASSERT(pos >= 0);
42142 		cp = (duk_uint32_t) duk_hstring_char_code_at_raw(thr, h, (duk_uint_t) pos, (duk_bool_t) magic /*surrogate_aware*/);
42143 		duk_push_u32(thr, cp);
42144 	}
42145 	return 1;
42146 }
42147 
42148 /*
42149  *  substring(), substr(), slice()
42150  */
42151 
42152 /* XXX: any chance of merging these three similar but still slightly
42153  * different algorithms so that footprint would be reduced?
42154  */
42155 
42156 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_substring(duk_hthread *thr) {
42157 	duk_hstring *h;
42158 	duk_int_t start_pos, end_pos;
42159 	duk_int_t len;
42160 
42161 	h = duk_push_this_coercible_to_string(thr);
42162 	DUK_ASSERT(h != NULL);
42163 	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
42164 
42165 	/* [ start end str ] */
42166 
42167 	start_pos = duk_to_int_clamped(thr, 0, 0, len);
42168 	if (duk_is_undefined(thr, 1)) {
42169 		end_pos = len;
42170 	} else {
42171 		end_pos = duk_to_int_clamped(thr, 1, 0, len);
42172 	}
42173 	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
42174 	DUK_ASSERT(end_pos >= 0 && end_pos <= len);
42175 
42176 	if (start_pos > end_pos) {
42177 		duk_int_t tmp = start_pos;
42178 		start_pos = end_pos;
42179 		end_pos = tmp;
42180 	}
42181 
42182 	DUK_ASSERT(end_pos >= start_pos);
42183 
42184 	duk_substring(thr, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
42185 	return 1;
42186 }
42187 
42188 #if defined(DUK_USE_SECTION_B)
42189 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_substr(duk_hthread *thr) {
42190 	duk_hstring *h;
42191 	duk_int_t start_pos, end_pos;
42192 	duk_int_t len;
42193 
42194 	/* Unlike non-obsolete String calls, substr() algorithm in E5.1
42195 	 * specification will happily coerce undefined and null to strings
42196 	 * ("undefined" and "null").
42197 	 */
42198 	duk_push_this(thr);
42199 	h = duk_to_hstring_m1(thr);  /* Reject Symbols. */
42200 	DUK_ASSERT(h != NULL);
42201 	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
42202 
42203 	/* [ start length str ] */
42204 
42205 	/* The implementation for computing of start_pos and end_pos differs
42206 	 * from the standard algorithm, but is intended to result in the exactly
42207 	 * same behavior.  This is not always obvious.
42208 	 */
42209 
42210 	/* combines steps 2 and 5; -len ensures max() not needed for step 5 */
42211 	start_pos = duk_to_int_clamped(thr, 0, -len, len);
42212 	if (start_pos < 0) {
42213 		start_pos = len + start_pos;
42214 	}
42215 	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
42216 
42217 	/* combines steps 3, 6; step 7 is not needed */
42218 	if (duk_is_undefined(thr, 1)) {
42219 		end_pos = len;
42220 	} else {
42221 		DUK_ASSERT(start_pos <= len);
42222 		end_pos = start_pos + duk_to_int_clamped(thr, 1, 0, len - start_pos);
42223 	}
42224 	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
42225 	DUK_ASSERT(end_pos >= 0 && end_pos <= len);
42226 	DUK_ASSERT(end_pos >= start_pos);
42227 
42228 	duk_substring(thr, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
42229 	return 1;
42230 }
42231 #endif  /* DUK_USE_SECTION_B */
42232 
42233 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_slice(duk_hthread *thr) {
42234 	duk_hstring *h;
42235 	duk_int_t start_pos, end_pos;
42236 	duk_int_t len;
42237 
42238 	h = duk_push_this_coercible_to_string(thr);
42239 	DUK_ASSERT(h != NULL);
42240 	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
42241 
42242 	/* [ start end str ] */
42243 
42244 	start_pos = duk_to_int_clamped(thr, 0, -len, len);
42245 	if (start_pos < 0) {
42246 		start_pos = len + start_pos;
42247 	}
42248 	if (duk_is_undefined(thr, 1)) {
42249 		end_pos = len;
42250 	} else {
42251 		end_pos = duk_to_int_clamped(thr, 1, -len, len);
42252 		if (end_pos < 0) {
42253 			end_pos = len + end_pos;
42254 		}
42255 	}
42256 	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
42257 	DUK_ASSERT(end_pos >= 0 && end_pos <= len);
42258 
42259 	if (end_pos < start_pos) {
42260 		end_pos = start_pos;
42261 	}
42262 
42263 	DUK_ASSERT(end_pos >= start_pos);
42264 
42265 	duk_substring(thr, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
42266 	return 1;
42267 }
42268 
42269 /*
42270  *  Case conversion
42271  */
42272 
42273 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_caseconv_shared(duk_hthread *thr) {
42274 	duk_small_int_t uppercase = duk_get_current_magic(thr);
42275 
42276 	(void) duk_push_this_coercible_to_string(thr);
42277 	duk_unicode_case_convert_string(thr, (duk_bool_t) uppercase);
42278 	return 1;
42279 }
42280 
42281 /*
42282  *  indexOf() and lastIndexOf()
42283  */
42284 
42285 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_indexof_shared(duk_hthread *thr) {
42286 	duk_hstring *h_this;
42287 	duk_hstring *h_search;
42288 	duk_int_t clen_this;
42289 	duk_int_t cpos;
42290 	duk_small_uint_t is_lastindexof = (duk_small_uint_t) duk_get_current_magic(thr);  /* 0=indexOf, 1=lastIndexOf */
42291 
42292 	h_this = duk_push_this_coercible_to_string(thr);
42293 	DUK_ASSERT(h_this != NULL);
42294 	clen_this = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h_this);
42295 
42296 	h_search = duk_to_hstring(thr, 0);
42297 	DUK_ASSERT(h_search != NULL);
42298 
42299 	duk_to_number(thr, 1);
42300 	if (duk_is_nan(thr, 1) && is_lastindexof) {
42301 		/* indexOf: NaN should cause pos to be zero.
42302 		 * lastIndexOf: NaN should cause pos to be +Infinity
42303 		 * (and later be clamped to len).
42304 		 */
42305 		cpos = clen_this;
42306 	} else {
42307 		cpos = duk_to_int_clamped(thr, 1, 0, clen_this);
42308 	}
42309 
42310 	cpos = duk__str_search_shared(thr, h_this, h_search, cpos, is_lastindexof /*backwards*/);
42311 	duk_push_int(thr, cpos);
42312 	return 1;
42313 }
42314 
42315 /*
42316  *  replace()
42317  */
42318 
42319 /* XXX: the current implementation works but is quite clunky; it compiles
42320  * to almost 1,4kB of x86 code so it needs to be simplified (better approach,
42321  * shared helpers, etc).  Some ideas for refactoring:
42322  *
42323  * - a primitive to convert a string into a regexp matcher (reduces matching
42324  *   code at the cost of making matching much slower)
42325  * - use replace() as a basic helper for match() and split(), which are both
42326  *   much simpler
42327  * - API call to get_prop and to_boolean
42328  */
42329 
42330 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_hthread *thr) {
42331 	duk_hstring *h_input;
42332 	duk_hstring *h_match;
42333 	duk_hstring *h_search;
42334 	duk_hobject *h_re;
42335 	duk_bufwriter_ctx bw_alloc;
42336 	duk_bufwriter_ctx *bw;
42337 #if defined(DUK_USE_REGEXP_SUPPORT)
42338 	duk_bool_t is_regexp;
42339 	duk_bool_t is_global;
42340 #endif
42341 	duk_bool_t is_repl_func;
42342 	duk_uint32_t match_start_coff, match_start_boff;
42343 #if defined(DUK_USE_REGEXP_SUPPORT)
42344 	duk_int_t match_caps;
42345 #endif
42346 	duk_uint32_t prev_match_end_boff;
42347 	const duk_uint8_t *r_start, *r_end, *r;   /* repl string scan */
42348 	duk_size_t tmp_sz;
42349 
42350 	DUK_ASSERT_TOP(thr, 2);
42351 	h_input = duk_push_this_coercible_to_string(thr);
42352 	DUK_ASSERT(h_input != NULL);
42353 
42354 	bw = &bw_alloc;
42355 	DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));  /* input size is good output starting point */
42356 
42357 	DUK_ASSERT_TOP(thr, 4);
42358 
42359 	/* stack[0] = search value
42360 	 * stack[1] = replace value
42361 	 * stack[2] = input string
42362 	 * stack[3] = result buffer
42363 	 */
42364 
42365 	h_re = duk_get_hobject_with_class(thr, 0, DUK_HOBJECT_CLASS_REGEXP);
42366 	if (h_re) {
42367 #if defined(DUK_USE_REGEXP_SUPPORT)
42368 		is_regexp = 1;
42369 		is_global = duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_GLOBAL, NULL);
42370 
42371 		if (is_global) {
42372 			/* start match from beginning */
42373 			duk_push_int(thr, 0);
42374 			duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
42375 		}
42376 #else  /* DUK_USE_REGEXP_SUPPORT */
42377 		DUK_DCERROR_UNSUPPORTED(thr);
42378 #endif  /* DUK_USE_REGEXP_SUPPORT */
42379 	} else {
42380 		duk_to_string(thr, 0);  /* rejects symbols */
42381 #if defined(DUK_USE_REGEXP_SUPPORT)
42382 		is_regexp = 0;
42383 		is_global = 0;
42384 #endif
42385 	}
42386 
42387 	if (duk_is_function(thr, 1)) {
42388 		is_repl_func = 1;
42389 		r_start = NULL;
42390 		r_end = NULL;
42391 	} else {
42392 		duk_hstring *h_repl;
42393 
42394 		is_repl_func = 0;
42395 		h_repl = duk_to_hstring(thr, 1);  /* reject symbols */
42396 		DUK_ASSERT(h_repl != NULL);
42397 		r_start = DUK_HSTRING_GET_DATA(h_repl);
42398 		r_end = r_start + DUK_HSTRING_GET_BYTELEN(h_repl);
42399 	}
42400 
42401 	prev_match_end_boff = 0;
42402 
42403 	for (;;) {
42404 		/*
42405 		 *  If matching with a regexp:
42406 		 *    - non-global RegExp: lastIndex not touched on a match, zeroed
42407 		 *      on a non-match
42408 		 *    - global RegExp: on match, lastIndex will be updated by regexp
42409 		 *      executor to point to next char after the matching part (so that
42410 		 *      characters in the matching part are not matched again)
42411 		 *
42412 		 *  If matching with a string:
42413 		 *    - always non-global match, find first occurrence
42414 		 *
42415 		 *  We need:
42416 		 *    - The character offset of start-of-match for the replacer function
42417 		 *    - The byte offsets for start-of-match and end-of-match to implement
42418 		 *      the replacement values $&, $`, and $', and to copy non-matching
42419 		 *      input string portions (including header and trailer) verbatim.
42420 		 *
42421 		 *  NOTE: the E5.1 specification is a bit vague how the RegExp should
42422 		 *  behave in the replacement process; e.g. is matching done first for
42423 		 *  all matches (in the global RegExp case) before any replacer calls
42424 		 *  are made?  See: test-bi-string-proto-replace.js for discussion.
42425 		 */
42426 
42427 		DUK_ASSERT_TOP(thr, 4);
42428 
42429 #if defined(DUK_USE_REGEXP_SUPPORT)
42430 		if (is_regexp) {
42431 			duk_dup_0(thr);
42432 			duk_dup_2(thr);
42433 			duk_regexp_match(thr);  /* [ ... regexp input ] -> [ res_obj ] */
42434 			if (!duk_is_object(thr, -1)) {
42435 				duk_pop(thr);
42436 				break;
42437 			}
42438 
42439 			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INDEX);
42440 			DUK_ASSERT(duk_is_number(thr, -1));
42441 			match_start_coff = duk_get_uint(thr, -1);
42442 			duk_pop(thr);
42443 
42444 			duk_get_prop_index(thr, -1, 0);
42445 			DUK_ASSERT(duk_is_string(thr, -1));
42446 			h_match = duk_known_hstring(thr, -1);
42447 			duk_pop(thr);  /* h_match is borrowed, remains reachable through match_obj */
42448 
42449 			if (DUK_HSTRING_GET_BYTELEN(h_match) == 0) {
42450 				/* This should be equivalent to match() algorithm step 8.f.iii.2:
42451 				 * detect an empty match and allow it, but don't allow it twice.
42452 				 */
42453 				duk_uint32_t last_index;
42454 
42455 				duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
42456 				last_index = (duk_uint32_t) duk_get_uint(thr, -1);
42457 				DUK_DDD(DUK_DDDPRINT("empty match, bump lastIndex: %ld -> %ld",
42458 				                     (long) last_index, (long) (last_index + 1)));
42459 				duk_pop(thr);
42460 				duk_push_uint(thr, (duk_uint_t) (last_index + 1));
42461 				duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
42462 			}
42463 
42464 			DUK_ASSERT(duk_get_length(thr, -1) <= DUK_INT_MAX);  /* string limits */
42465 			match_caps = (duk_int_t) duk_get_length(thr, -1);
42466 		} else {
42467 #else  /* DUK_USE_REGEXP_SUPPORT */
42468 		{  /* unconditionally */
42469 #endif  /* DUK_USE_REGEXP_SUPPORT */
42470 			const duk_uint8_t *p_start, *p_end, *p;   /* input string scan */
42471 			const duk_uint8_t *q_start;               /* match string */
42472 			duk_size_t p_blen;
42473 			duk_size_t q_blen;
42474 
42475 #if defined(DUK_USE_REGEXP_SUPPORT)
42476 			DUK_ASSERT(!is_global);  /* single match always */
42477 #endif
42478 
42479 			p_start = DUK_HSTRING_GET_DATA(h_input);
42480 			p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
42481 			p_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_input);
42482 			p = p_start;
42483 
42484 			h_search = duk_known_hstring(thr, 0);
42485 			q_start = DUK_HSTRING_GET_DATA(h_search);
42486 			q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_search);
42487 
42488 			if (q_blen > p_blen) {
42489 				break;  /* no match */
42490 			}
42491 
42492 			p_end -= q_blen;  /* ensure full memcmp() fits in while */
42493 			DUK_ASSERT(p_end >= p);
42494 
42495 			match_start_coff = 0;
42496 
42497 			while (p <= p_end) {
42498 				DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
42499 				if (duk_memcmp((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
42500 					duk_dup_0(thr);
42501 					h_match = duk_known_hstring(thr, -1);
42502 #if defined(DUK_USE_REGEXP_SUPPORT)
42503 					match_caps = 0;
42504 #endif
42505 					goto found;
42506 				}
42507 
42508 				/* track utf-8 non-continuation bytes */
42509 				if ((p[0] & 0xc0) != 0x80) {
42510 					match_start_coff++;
42511 				}
42512 				p++;
42513 			}
42514 
42515 			/* not found */
42516 			break;
42517 		}
42518 	 found:
42519 
42520 		/* stack[0] = search value
42521 		 * stack[1] = replace value
42522 		 * stack[2] = input string
42523 		 * stack[3] = result buffer
42524 		 * stack[4] = regexp match OR match string
42525 		 */
42526 
42527 		match_start_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);
42528 
42529 		tmp_sz = (duk_size_t) (match_start_boff - prev_match_end_boff);
42530 		DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);
42531 
42532 		prev_match_end_boff = match_start_boff + DUK_HSTRING_GET_BYTELEN(h_match);
42533 
42534 		if (is_repl_func) {
42535 			duk_idx_t idx_args;
42536 			duk_hstring *h_repl;
42537 
42538 			/* regexp res_obj is at index 4 */
42539 
42540 			duk_dup_1(thr);
42541 			idx_args = duk_get_top(thr);
42542 
42543 #if defined(DUK_USE_REGEXP_SUPPORT)
42544 			if (is_regexp) {
42545 				duk_int_t idx;
42546 				duk_require_stack(thr, match_caps + 2);
42547 				for (idx = 0; idx < match_caps; idx++) {
42548 					/* match followed by capture(s) */
42549 					duk_get_prop_index(thr, 4, (duk_uarridx_t) idx);
42550 				}
42551 			} else {
42552 #else  /* DUK_USE_REGEXP_SUPPORT */
42553 			{  /* unconditionally */
42554 #endif  /* DUK_USE_REGEXP_SUPPORT */
42555 				/* match == search string, by definition */
42556 				duk_dup_0(thr);
42557 			}
42558 			duk_push_uint(thr, (duk_uint_t) match_start_coff);
42559 			duk_dup_2(thr);
42560 
42561 			/* [ ... replacer match [captures] match_char_offset input ] */
42562 
42563 			duk_call(thr, duk_get_top(thr) - idx_args);
42564 			h_repl = duk_to_hstring_m1(thr);  /* -> [ ... repl_value ] */
42565 			DUK_ASSERT(h_repl != NULL);
42566 
42567 			DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_repl);
42568 
42569 			duk_pop(thr);  /* repl_value */
42570 		} else {
42571 			r = r_start;
42572 
42573 			while (r < r_end) {
42574 				duk_int_t ch1;
42575 				duk_int_t ch2;
42576 #if defined(DUK_USE_REGEXP_SUPPORT)
42577 				duk_int_t ch3;
42578 #endif
42579 				duk_size_t left;
42580 
42581 				ch1 = *r++;
42582 				if (ch1 != DUK_ASC_DOLLAR) {
42583 					goto repl_write;
42584 				}
42585 				DUK_ASSERT(r <= r_end);
42586 				left = (duk_size_t) (r_end - r);
42587 
42588 				if (left <= 0) {
42589 					goto repl_write;
42590 				}
42591 
42592 				ch2 = r[0];
42593 				switch (ch2) {
42594 				case DUK_ASC_DOLLAR: {
42595 					ch1 = (1 << 8) + DUK_ASC_DOLLAR;
42596 					goto repl_write;
42597 				}
42598 				case DUK_ASC_AMP: {
42599 					DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_match);
42600 					r++;
42601 					continue;
42602 				}
42603 				case DUK_ASC_GRAVE: {
42604 					tmp_sz = (duk_size_t) match_start_boff;
42605 					DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input), tmp_sz);
42606 					r++;
42607 					continue;
42608 				}
42609 				case DUK_ASC_SINGLEQUOTE: {
42610 					duk_uint32_t match_end_boff;
42611 
42612 					/* Use match charlen instead of bytelen, just in case the input and
42613 					 * match codepoint encodings would have different lengths.
42614 					 */
42615 					/* XXX: charlen computed here, and also in char2byte helper. */
42616 					match_end_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr,
42617 					                                                                   h_input,
42618 					                                                                   match_start_coff + (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h_match));
42619 
42620 					tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - match_end_boff);
42621 					DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + match_end_boff, tmp_sz);
42622 					r++;
42623 					continue;
42624 				}
42625 				default: {
42626 #if defined(DUK_USE_REGEXP_SUPPORT)
42627 					duk_int_t capnum, captmp, capadv;
42628 					/* XXX: optional check, match_caps is zero if no regexp,
42629 					 * so dollar will be interpreted literally anyway.
42630 					 */
42631 
42632 					if (!is_regexp) {
42633 						goto repl_write;
42634 					}
42635 
42636 					if (!(ch2 >= DUK_ASC_0 && ch2 <= DUK_ASC_9)) {
42637 						goto repl_write;
42638 					}
42639 					capnum = ch2 - DUK_ASC_0;
42640 					capadv = 1;
42641 
42642 					if (left >= 2) {
42643 						ch3 = r[1];
42644 						if (ch3 >= DUK_ASC_0 && ch3 <= DUK_ASC_9) {
42645 							captmp = capnum * 10 + (ch3 - DUK_ASC_0);
42646 							if (captmp < match_caps) {
42647 								capnum = captmp;
42648 								capadv = 2;
42649 							}
42650 						}
42651 					}
42652 
42653 					if (capnum > 0 && capnum < match_caps) {
42654 						DUK_ASSERT(is_regexp != 0);  /* match_caps == 0 without regexps */
42655 
42656 						/* regexp res_obj is at offset 4 */
42657 						duk_get_prop_index(thr, 4, (duk_uarridx_t) capnum);
42658 						if (duk_is_string(thr, -1)) {
42659 							duk_hstring *h_tmp_str;
42660 
42661 							h_tmp_str = duk_known_hstring(thr, -1);
42662 
42663 							DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_tmp_str);
42664 						} else {
42665 							/* undefined -> skip (replaced with empty) */
42666 						}
42667 						duk_pop(thr);
42668 						r += capadv;
42669 						continue;
42670 					} else {
42671 						goto repl_write;
42672 					}
42673 #else  /* DUK_USE_REGEXP_SUPPORT */
42674 					goto repl_write;  /* unconditionally */
42675 #endif  /* DUK_USE_REGEXP_SUPPORT */
42676 				}  /* default case */
42677 				}  /* switch (ch2) */
42678 
42679 			 repl_write:
42680 				/* ch1 = (r_increment << 8) + byte */
42681 
42682 				DUK_BW_WRITE_ENSURE_U8(thr, bw, (duk_uint8_t) (ch1 & 0xff));
42683 				r += ch1 >> 8;
42684 			}  /* while repl */
42685 		}  /* if (is_repl_func) */
42686 
42687 		duk_pop(thr);  /* pop regexp res_obj or match string */
42688 
42689 #if defined(DUK_USE_REGEXP_SUPPORT)
42690 		if (!is_global) {
42691 #else
42692 		{  /* unconditionally; is_global==0 */
42693 #endif
42694 			break;
42695 		}
42696 	}
42697 
42698 	/* trailer */
42699 	tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff);
42700 	DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);
42701 
42702 	DUK_ASSERT_TOP(thr, 4);
42703 	DUK_BW_COMPACT(thr, bw);
42704 	(void) duk_buffer_to_string(thr, -1);  /* Safe if inputs are safe. */
42705 	return 1;
42706 }
42707 
42708 /*
42709  *  split()
42710  */
42711 
42712 /* XXX: very messy now, but works; clean up, remove unused variables (nomimally
42713  * used so compiler doesn't complain).
42714  */
42715 
42716 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_split(duk_hthread *thr) {
42717 	duk_hstring *h_input;
42718 	duk_hstring *h_sep;
42719 	duk_uint32_t limit;
42720 	duk_uint32_t arr_idx;
42721 #if defined(DUK_USE_REGEXP_SUPPORT)
42722 	duk_bool_t is_regexp;
42723 #endif
42724 	duk_bool_t matched;  /* set to 1 if any match exists (needed for empty input special case) */
42725 	duk_uint32_t prev_match_end_coff, prev_match_end_boff;
42726 	duk_uint32_t match_start_boff, match_start_coff;
42727 	duk_uint32_t match_end_boff, match_end_coff;
42728 
42729 	h_input = duk_push_this_coercible_to_string(thr);
42730 	DUK_ASSERT(h_input != NULL);
42731 
42732 	duk_push_array(thr);
42733 
42734 	if (duk_is_undefined(thr, 1)) {
42735 		limit = 0xffffffffUL;
42736 	} else {
42737 		limit = duk_to_uint32(thr, 1);
42738 	}
42739 
42740 	if (limit == 0) {
42741 		return 1;
42742 	}
42743 
42744 	/* If the separator is a RegExp, make a "clone" of it.  The specification
42745 	 * algorithm calls [[Match]] directly for specific indices; we emulate this
42746 	 * by tweaking lastIndex and using a "force global" variant of duk_regexp_match()
42747 	 * which will use global-style matching even when the RegExp itself is non-global.
42748 	 */
42749 
42750 	if (duk_is_undefined(thr, 0)) {
42751 		/* The spec algorithm first does "R = ToString(separator)" before checking
42752 		 * whether separator is undefined.  Since this is side effect free, we can
42753 		 * skip the ToString() here.
42754 		 */
42755 		duk_dup_2(thr);
42756 		duk_put_prop_index(thr, 3, 0);
42757 		return 1;
42758 	} else if (duk_get_hobject_with_class(thr, 0, DUK_HOBJECT_CLASS_REGEXP) != NULL) {
42759 #if defined(DUK_USE_REGEXP_SUPPORT)
42760 		duk_push_hobject_bidx(thr, DUK_BIDX_REGEXP_CONSTRUCTOR);
42761 		duk_dup_0(thr);
42762 		duk_new(thr, 1);  /* [ ... RegExp val ] -> [ ... res ] */
42763 		duk_replace(thr, 0);
42764 		/* lastIndex is initialized to zero by new RegExp() */
42765 		is_regexp = 1;
42766 #else
42767 		DUK_DCERROR_UNSUPPORTED(thr);
42768 #endif
42769 	} else {
42770 		duk_to_string(thr, 0);
42771 #if defined(DUK_USE_REGEXP_SUPPORT)
42772 		is_regexp = 0;
42773 #endif
42774 	}
42775 
42776 	/* stack[0] = separator (string or regexp)
42777 	 * stack[1] = limit
42778 	 * stack[2] = input string
42779 	 * stack[3] = result array
42780 	 */
42781 
42782 	prev_match_end_boff = 0;
42783 	prev_match_end_coff = 0;
42784 	arr_idx = 0;
42785 	matched = 0;
42786 
42787 	for (;;) {
42788 		/*
42789 		 *  The specification uses RegExp [[Match]] to attempt match at specific
42790 		 *  offsets.  We don't have such a primitive, so we use an actual RegExp
42791 		 *  and tweak lastIndex.  Since the RegExp may be non-global, we use a
42792 		 *  special variant which forces global-like behavior for matching.
42793 		 */
42794 
42795 		DUK_ASSERT_TOP(thr, 4);
42796 
42797 #if defined(DUK_USE_REGEXP_SUPPORT)
42798 		if (is_regexp) {
42799 			duk_dup_0(thr);
42800 			duk_dup_2(thr);
42801 			duk_regexp_match_force_global(thr);  /* [ ... regexp input ] -> [ res_obj ] */
42802 			if (!duk_is_object(thr, -1)) {
42803 				duk_pop(thr);
42804 				break;
42805 			}
42806 			matched = 1;
42807 
42808 			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INDEX);
42809 			DUK_ASSERT(duk_is_number(thr, -1));
42810 			match_start_coff = duk_get_uint(thr, -1);
42811 			match_start_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);
42812 			duk_pop(thr);
42813 
42814 			if (match_start_coff == DUK_HSTRING_GET_CHARLEN(h_input)) {
42815 				/* don't allow an empty match at the end of the string */
42816 				duk_pop(thr);
42817 				break;
42818 			}
42819 
42820 			duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
42821 			DUK_ASSERT(duk_is_number(thr, -1));
42822 			match_end_coff = duk_get_uint(thr, -1);
42823 			match_end_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h_input, match_end_coff);
42824 			duk_pop(thr);
42825 
42826 			/* empty match -> bump and continue */
42827 			if (prev_match_end_boff == match_end_boff) {
42828 				duk_push_uint(thr, (duk_uint_t) (match_end_coff + 1));
42829 				duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
42830 				duk_pop(thr);
42831 				continue;
42832 			}
42833 		} else {
42834 #else  /* DUK_USE_REGEXP_SUPPORT */
42835 		{  /* unconditionally */
42836 #endif  /* DUK_USE_REGEXP_SUPPORT */
42837 			const duk_uint8_t *p_start, *p_end, *p;   /* input string scan */
42838 			const duk_uint8_t *q_start;               /* match string */
42839 			duk_size_t q_blen, q_clen;
42840 
42841 			p_start = DUK_HSTRING_GET_DATA(h_input);
42842 			p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
42843 			p = p_start + prev_match_end_boff;
42844 
42845 			h_sep = duk_known_hstring(thr, 0);  /* symbol already rejected above */
42846 			q_start = DUK_HSTRING_GET_DATA(h_sep);
42847 			q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sep);
42848 			q_clen = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_sep);
42849 
42850 			p_end -= q_blen;  /* ensure full memcmp() fits in while */
42851 
42852 			match_start_coff = prev_match_end_coff;
42853 
42854 			if (q_blen == 0) {
42855 				/* Handle empty separator case: it will always match, and always
42856 				 * triggers the check in step 13.c.iii initially.  Note that we
42857 				 * must skip to either end of string or start of first codepoint,
42858 				 * skipping over any continuation bytes!
42859 				 *
42860 				 * Don't allow an empty string to match at the end of the input.
42861 				 */
42862 
42863 				matched = 1;  /* empty separator can always match */
42864 
42865 				match_start_coff++;
42866 				p++;
42867 				while (p < p_end) {
42868 					if ((p[0] & 0xc0) != 0x80) {
42869 						goto found;
42870 					}
42871 					p++;
42872 				}
42873 				goto not_found;
42874 			}
42875 
42876 			DUK_ASSERT(q_blen > 0 && q_clen > 0);
42877 			while (p <= p_end) {
42878 				DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
42879 				DUK_ASSERT(q_blen > 0);  /* no issues with empty memcmp() */
42880 				if (duk_memcmp((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
42881 					/* never an empty match, so step 13.c.iii can't be triggered */
42882 					goto found;
42883 				}
42884 
42885 				/* track utf-8 non-continuation bytes */
42886 				if ((p[0] & 0xc0) != 0x80) {
42887 					match_start_coff++;
42888 				}
42889 				p++;
42890 			}
42891 
42892 		 not_found:
42893 			/* not found */
42894 			break;
42895 
42896 		 found:
42897 			matched = 1;
42898 			match_start_boff = (duk_uint32_t) (p - p_start);
42899 			match_end_coff = (duk_uint32_t) (match_start_coff + q_clen);  /* constrained by string length */
42900 			match_end_boff = (duk_uint32_t) (match_start_boff + q_blen);  /* ditto */
42901 
42902 			/* empty match (may happen with empty separator) -> bump and continue */
42903 			if (prev_match_end_boff == match_end_boff) {
42904 				prev_match_end_boff++;
42905 				prev_match_end_coff++;
42906 				continue;
42907 			}
42908 		}  /* if (is_regexp) */
42909 
42910 		/* stack[0] = separator (string or regexp)
42911 		 * stack[1] = limit
42912 		 * stack[2] = input string
42913 		 * stack[3] = result array
42914 		 * stack[4] = regexp res_obj (if is_regexp)
42915 		 */
42916 
42917 		DUK_DDD(DUK_DDDPRINT("split; match_start b=%ld,c=%ld, match_end b=%ld,c=%ld, prev_end b=%ld,c=%ld",
42918 		                     (long) match_start_boff, (long) match_start_coff,
42919 		                     (long) match_end_boff, (long) match_end_coff,
42920 		                     (long) prev_match_end_boff, (long) prev_match_end_coff));
42921 
42922 		duk_push_lstring(thr,
42923 		                 (const char *) (DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff),
42924 		                 (duk_size_t) (match_start_boff - prev_match_end_boff));
42925 		duk_put_prop_index(thr, 3, arr_idx);
42926 		arr_idx++;
42927 		if (arr_idx >= limit) {
42928 			goto hit_limit;
42929 		}
42930 
42931 #if defined(DUK_USE_REGEXP_SUPPORT)
42932 		if (is_regexp) {
42933 			duk_size_t i, len;
42934 
42935 			len = duk_get_length(thr, 4);
42936 			for (i = 1; i < len; i++) {
42937 				DUK_ASSERT(i <= DUK_UARRIDX_MAX);  /* cannot have >4G captures */
42938 				duk_get_prop_index(thr, 4, (duk_uarridx_t) i);
42939 				duk_put_prop_index(thr, 3, arr_idx);
42940 				arr_idx++;
42941 				if (arr_idx >= limit) {
42942 					goto hit_limit;
42943 				}
42944 			}
42945 
42946 			duk_pop(thr);
42947 			/* lastIndex already set up for next match */
42948 		} else {
42949 #else  /* DUK_USE_REGEXP_SUPPORT */
42950 		{  /* unconditionally */
42951 #endif  /* DUK_USE_REGEXP_SUPPORT */
42952 			/* no action */
42953 		}
42954 
42955 		prev_match_end_boff = match_end_boff;
42956 		prev_match_end_coff = match_end_coff;
42957 		continue;
42958 	}  /* for */
42959 
42960 	/* Combined step 11 (empty string special case) and 14-15. */
42961 
42962 	DUK_DDD(DUK_DDDPRINT("split trailer; prev_end b=%ld,c=%ld",
42963 	                     (long) prev_match_end_boff, (long) prev_match_end_coff));
42964 
42965 	if (DUK_HSTRING_GET_BYTELEN(h_input) > 0 || !matched) {
42966 		/* Add trailer if:
42967 		 *   a) non-empty input
42968 		 *   b) empty input and no (zero size) match found (step 11)
42969 		 */
42970 
42971 		duk_push_lstring(thr,
42972 		                 (const char *) DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff,
42973 		                 (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff));
42974 		duk_put_prop_index(thr, 3, arr_idx);
42975 		/* No arr_idx update or limit check */
42976 	}
42977 
42978 	return 1;
42979 
42980  hit_limit:
42981 #if defined(DUK_USE_REGEXP_SUPPORT)
42982 	if (is_regexp) {
42983 		duk_pop(thr);
42984 	}
42985 #endif
42986 
42987 	return 1;
42988 }
42989 
42990 /*
42991  *  Various
42992  */
42993 
42994 #if defined(DUK_USE_REGEXP_SUPPORT)
42995 DUK_LOCAL void duk__to_regexp_helper(duk_hthread *thr, duk_idx_t idx, duk_bool_t force_new) {
42996 	duk_hobject *h;
42997 
42998 	/* Shared helper for match() steps 3-4, search() steps 3-4. */
42999 
43000 	DUK_ASSERT(idx >= 0);
43001 
43002 	if (force_new) {
43003 		goto do_new;
43004 	}
43005 
43006 	h = duk_get_hobject_with_class(thr, idx, DUK_HOBJECT_CLASS_REGEXP);
43007 	if (!h) {
43008 		goto do_new;
43009 	}
43010 	return;
43011 
43012  do_new:
43013 	duk_push_hobject_bidx(thr, DUK_BIDX_REGEXP_CONSTRUCTOR);
43014 	duk_dup(thr, idx);
43015 	duk_new(thr, 1);  /* [ ... RegExp val ] -> [ ... res ] */
43016 	duk_replace(thr, idx);
43017 }
43018 #endif  /* DUK_USE_REGEXP_SUPPORT */
43019 
43020 #if defined(DUK_USE_REGEXP_SUPPORT)
43021 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_search(duk_hthread *thr) {
43022 	/* Easiest way to implement the search required by the specification
43023 	 * is to do a RegExp test() with lastIndex forced to zero.  To avoid
43024 	 * side effects on the argument, "clone" the RegExp if a RegExp was
43025 	 * given as input.
43026 	 *
43027 	 * The global flag of the RegExp should be ignored; setting lastIndex
43028 	 * to zero (which happens when "cloning" the RegExp) should have an
43029 	 * equivalent effect.
43030 	 */
43031 
43032 	DUK_ASSERT_TOP(thr, 1);
43033 	(void) duk_push_this_coercible_to_string(thr);  /* at index 1 */
43034 	duk__to_regexp_helper(thr, 0 /*index*/, 1 /*force_new*/);
43035 
43036 	/* stack[0] = regexp
43037 	 * stack[1] = string
43038 	 */
43039 
43040 	/* Avoid using RegExp.prototype methods, as they're writable and
43041 	 * configurable and may have been changed.
43042 	 */
43043 
43044 	duk_dup_0(thr);
43045 	duk_dup_1(thr);  /* [ ... re_obj input ] */
43046 	duk_regexp_match(thr);  /* -> [ ... res_obj ] */
43047 
43048 	if (!duk_is_object(thr, -1)) {
43049 		duk_push_int(thr, -1);
43050 		return 1;
43051 	}
43052 
43053 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INDEX);
43054 	DUK_ASSERT(duk_is_number(thr, -1));
43055 	return 1;
43056 }
43057 #endif  /* DUK_USE_REGEXP_SUPPORT */
43058 
43059 #if defined(DUK_USE_REGEXP_SUPPORT)
43060 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_match(duk_hthread *thr) {
43061 	duk_bool_t global;
43062 	duk_int_t prev_last_index;
43063 	duk_int_t this_index;
43064 	duk_int_t arr_idx;
43065 
43066 	DUK_ASSERT_TOP(thr, 1);
43067 	(void) duk_push_this_coercible_to_string(thr);
43068 	duk__to_regexp_helper(thr, 0 /*index*/, 0 /*force_new*/);
43069 	global = duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_GLOBAL, NULL);
43070 	DUK_ASSERT_TOP(thr, 2);
43071 
43072 	/* stack[0] = regexp
43073 	 * stack[1] = string
43074 	 */
43075 
43076 	if (!global) {
43077 		duk_regexp_match(thr);  /* -> [ res_obj ] */
43078 		return 1;  /* return 'res_obj' */
43079 	}
43080 
43081 	/* Global case is more complex. */
43082 
43083 	/* [ regexp string ] */
43084 
43085 	duk_push_int(thr, 0);
43086 	duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
43087 	duk_push_array(thr);
43088 
43089 	/* [ regexp string res_arr ] */
43090 
43091 	prev_last_index = 0;
43092 	arr_idx = 0;
43093 
43094 	for (;;) {
43095 		DUK_ASSERT_TOP(thr, 3);
43096 
43097 		duk_dup_0(thr);
43098 		duk_dup_1(thr);
43099 		duk_regexp_match(thr);  /* -> [ ... regexp string ] -> [ ... res_obj ] */
43100 
43101 		if (!duk_is_object(thr, -1)) {
43102 			duk_pop(thr);
43103 			break;
43104 		}
43105 
43106 		duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
43107 		DUK_ASSERT(duk_is_number(thr, -1));
43108 		this_index = duk_get_int(thr, -1);
43109 		duk_pop(thr);
43110 
43111 		if (this_index == prev_last_index) {
43112 			this_index++;
43113 			duk_push_int(thr, this_index);
43114 			duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
43115 		}
43116 		prev_last_index = this_index;
43117 
43118 		duk_get_prop_index(thr, -1, 0);  /* match string */
43119 		duk_put_prop_index(thr, 2, (duk_uarridx_t) arr_idx);
43120 		arr_idx++;
43121 		duk_pop(thr);  /* res_obj */
43122 	}
43123 
43124 	if (arr_idx == 0) {
43125 		duk_push_null(thr);
43126 	}
43127 
43128 	return 1;  /* return 'res_arr' or 'null' */
43129 }
43130 #endif  /* DUK_USE_REGEXP_SUPPORT */
43131 
43132 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_concat(duk_hthread *thr) {
43133 	/* duk_concat() coerces arguments with ToString() in correct order */
43134 	(void) duk_push_this_coercible_to_string(thr);
43135 	duk_insert(thr, 0);  /* this is relatively expensive */
43136 	duk_concat(thr, duk_get_top(thr));
43137 	return 1;
43138 }
43139 
43140 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_trim(duk_hthread *thr) {
43141 	DUK_ASSERT_TOP(thr, 0);
43142 	(void) duk_push_this_coercible_to_string(thr);
43143 	duk_trim(thr, 0);
43144 	DUK_ASSERT_TOP(thr, 1);
43145 	return 1;
43146 }
43147 
43148 #if defined(DUK_USE_ES6)
43149 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_repeat(duk_hthread *thr) {
43150 	duk_hstring *h_input;
43151 	duk_size_t input_blen;
43152 	duk_size_t result_len;
43153 	duk_int_t count_signed;
43154 	duk_uint_t count;
43155 	const duk_uint8_t *src;
43156 	duk_uint8_t *buf;
43157 	duk_uint8_t *p;
43158 	duk_double_t d;
43159 #if !defined(DUK_USE_PREFER_SIZE)
43160 	duk_size_t copy_size;
43161 	duk_uint8_t *p_end;
43162 #endif
43163 
43164 	DUK_ASSERT_TOP(thr, 1);
43165 	h_input = duk_push_this_coercible_to_string(thr);
43166 	DUK_ASSERT(h_input != NULL);
43167 	input_blen = DUK_HSTRING_GET_BYTELEN(h_input);
43168 
43169 	/* Count is ToNumber() coerced; +Infinity must be always rejected
43170 	 * (even if input string is zero length), as well as negative values
43171 	 * and -Infinity.  -Infinity doesn't require an explicit check
43172 	 * because duk_get_int() clamps it to DUK_INT_MIN which gets rejected
43173 	 * as a negative value (regardless of input string length).
43174 	 */
43175 	d = duk_to_number(thr, 0);
43176 	if (duk_double_is_posinf(d)) {
43177 		goto fail_range;
43178 	}
43179 	count_signed = duk_get_int(thr, 0);
43180 	if (count_signed < 0) {
43181 		goto fail_range;
43182 	}
43183 	count = (duk_uint_t) count_signed;
43184 
43185 	/* Overflow check for result length. */
43186 	result_len = count * input_blen;
43187 	if (count != 0 && result_len / count != input_blen) {
43188 		goto fail_range;
43189 	}
43190 
43191 	/* Temporary fixed buffer, later converted to string. */
43192 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, result_len);
43193 	DUK_ASSERT(buf != NULL);
43194 	src = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
43195 	DUK_ASSERT(src != NULL);
43196 
43197 #if defined(DUK_USE_PREFER_SIZE)
43198 	p = buf;
43199 	while (count-- > 0) {
43200 		duk_memcpy((void *) p, (const void *) src, input_blen);  /* copy size may be zero, but pointers are valid */
43201 		p += input_blen;
43202 	}
43203 #else  /* DUK_USE_PREFER_SIZE */
43204 	/* Take advantage of already copied pieces to speed up the process
43205 	 * especially for small repeated strings.
43206 	 */
43207 	p = buf;
43208 	p_end = p + result_len;
43209 	copy_size = input_blen;
43210 	for (;;) {
43211 		duk_size_t remain = (duk_size_t) (p_end - p);
43212 		DUK_DDD(DUK_DDDPRINT("remain=%ld, copy_size=%ld, input_blen=%ld, result_len=%ld",
43213 		                     (long) remain, (long) copy_size, (long) input_blen,
43214 		                     (long) result_len));
43215 		if (remain <= copy_size) {
43216 			/* If result_len is zero, this case is taken and does
43217 			 * a zero size copy (with valid pointers).
43218 			 */
43219 			duk_memcpy((void *) p, (const void *) src, remain);
43220 			break;
43221 		} else {
43222 			duk_memcpy((void *) p, (const void *) src, copy_size);
43223 			p += copy_size;
43224 		}
43225 
43226 		src = (const duk_uint8_t *) buf;  /* Use buf as source for larger copies. */
43227 		copy_size = (duk_size_t) (p - buf);
43228 	}
43229 #endif  /* DUK_USE_PREFER_SIZE */
43230 
43231 	/* XXX: It would be useful to be able to create a duk_hstring with
43232 	 * a certain byte size whose data area wasn't initialized and which
43233 	 * wasn't in the string table yet.  This would allow a string to be
43234 	 * constructed directly without a buffer temporary and when it was
43235 	 * finished, it could be injected into the string table.  Currently
43236 	 * this isn't possible because duk_hstrings are only tracked by the
43237 	 * intern table (they are not in heap_allocated).
43238 	 */
43239 
43240 	duk_buffer_to_string(thr, -1);  /* Safe if input is safe. */
43241 	return 1;
43242 
43243  fail_range:
43244 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
43245 }
43246 #endif  /* DUK_USE_ES6 */
43247 
43248 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_locale_compare(duk_hthread *thr) {
43249 	duk_hstring *h1;
43250 	duk_hstring *h2;
43251 	duk_size_t h1_len, h2_len, prefix_len;
43252 	duk_small_int_t ret = 0;
43253 	duk_small_int_t rc;
43254 
43255 	/* The current implementation of localeCompare() is simply a codepoint
43256 	 * by codepoint comparison, implemented with a simple string compare
43257 	 * because UTF-8 should preserve codepoint ordering (assuming valid
43258 	 * shortest UTF-8 encoding).
43259 	 *
43260 	 * The specification requires that the return value must be related
43261 	 * to the sort order: e.g. negative means that 'this' comes before
43262 	 * 'that' in sort order.  We assume an ascending sort order.
43263 	 */
43264 
43265 	/* XXX: could share code with duk_js_ops.c, duk_js_compare_helper */
43266 
43267 	h1 = duk_push_this_coercible_to_string(thr);
43268 	DUK_ASSERT(h1 != NULL);
43269 
43270 	h2 = duk_to_hstring(thr, 0);
43271 	DUK_ASSERT(h2 != NULL);
43272 
43273 	h1_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1);
43274 	h2_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2);
43275 	prefix_len = (h1_len <= h2_len ? h1_len : h2_len);
43276 
43277 	rc = (duk_small_int_t) duk_memcmp((const void *) DUK_HSTRING_GET_DATA(h1),
43278 	                                  (const void *) DUK_HSTRING_GET_DATA(h2),
43279 	                                  (size_t) prefix_len);
43280 
43281 	if (rc < 0) {
43282 		ret = -1;
43283 		goto done;
43284 	} else if (rc > 0) {
43285 		ret = 1;
43286 		goto done;
43287 	}
43288 
43289 	/* prefix matches, lengths matter now */
43290 	if (h1_len > h2_len) {
43291 		ret = 1;
43292 		goto done;
43293 	} else if (h1_len == h2_len) {
43294 		DUK_ASSERT(ret == 0);
43295 		goto done;
43296 	}
43297 	ret = -1;
43298 	goto done;
43299 
43300  done:
43301 	duk_push_int(thr, (duk_int_t) ret);
43302 	return 1;
43303 }
43304 
43305 #if defined(DUK_USE_ES6)
43306 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_startswith_endswith(duk_hthread *thr) {
43307 	duk_int_t magic;
43308 	duk_hstring *h_target;
43309 	duk_size_t blen_target;
43310 	duk_hstring *h_search;
43311 	duk_size_t blen_search;
43312 	duk_int_t off;
43313 	duk_bool_t result = 0;
43314 	duk_size_t blen_left;
43315 
43316 	/* Because string byte lengths are in [0,DUK_INT_MAX] it's safe to
43317 	 * subtract two string lengths without overflow.
43318 	 */
43319 	DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= DUK_INT_MAX);
43320 
43321 	h_target = duk_push_this_coercible_to_string(thr);
43322 	DUK_ASSERT(h_target != NULL);
43323 
43324 	h_search = duk__str_tostring_notregexp(thr, 0);
43325 	DUK_ASSERT(h_search != NULL);
43326 
43327 	magic = duk_get_current_magic(thr);
43328 
43329 	/* Careful to avoid pointer overflows in the matching logic. */
43330 
43331 	blen_target = DUK_HSTRING_GET_BYTELEN(h_target);
43332 	blen_search = DUK_HSTRING_GET_BYTELEN(h_search);
43333 
43334 #if 0
43335 	/* If search string is longer than the target string, we can
43336 	 * never match.  Could check explicitly, but should be handled
43337 	 * correctly below.
43338 	 */
43339 	if (blen_search > blen_target) {
43340 		goto finish;
43341 	}
43342 #endif
43343 
43344 	off = 0;
43345 	if (duk_is_undefined(thr, 1)) {
43346 		if (magic) {
43347 			off = (duk_int_t) blen_target - (duk_int_t) blen_search;
43348 		} else {
43349 			DUK_ASSERT(off == 0);
43350 		}
43351 	} else {
43352 		duk_int_t len;
43353 		duk_int_t pos;
43354 
43355 		DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= DUK_INT_MAX);
43356 		len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h_target);
43357 		pos = duk_to_int_clamped(thr, 1, 0, len);
43358 		DUK_ASSERT(pos >= 0 && pos <= len);
43359 
43360 		off = (duk_int_t) duk_heap_strcache_offset_char2byte(thr, h_target, (duk_uint_fast32_t) pos);
43361 		if (magic) {
43362 			off -= (duk_int_t) blen_search;
43363 		}
43364 	}
43365 	if (off < 0 || off > (duk_int_t) blen_target) {
43366 		goto finish;
43367 	}
43368 
43369 	/* The main comparison can be done using a memcmp() rather than
43370 	 * doing codepoint comparisons: for CESU-8 strings there is a
43371 	 * canonical representation for every codepoint.  But we do need
43372 	 * to deal with the char/byte offset translation to find the
43373 	 * comparison range.
43374 	 */
43375 
43376 	DUK_ASSERT(off >= 0);
43377 	DUK_ASSERT((duk_size_t) off <= blen_target);
43378 	blen_left = blen_target - (duk_size_t) off;
43379 	if (blen_left >= blen_search) {
43380 		const duk_uint8_t *p_cmp_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_target) + off;
43381 		const duk_uint8_t *p_search = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_search);
43382 		if (duk_memcmp_unsafe((const void *) p_cmp_start, (const void *) p_search, (size_t) blen_search) == 0) {
43383 			result = 1;
43384 		}
43385 	}
43386 
43387  finish:
43388 	duk_push_boolean(thr, result);
43389 	return 1;
43390 }
43391 #endif  /* DUK_USE_ES6 */
43392 
43393 #if defined(DUK_USE_ES6)
43394 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_includes(duk_hthread *thr) {
43395 	duk_hstring *h;
43396 	duk_hstring *h_search;
43397 	duk_int_t len;
43398 	duk_int_t pos;
43399 
43400 	h = duk_push_this_coercible_to_string(thr);
43401 	DUK_ASSERT(h != NULL);
43402 
43403 	h_search = duk__str_tostring_notregexp(thr, 0);
43404 	DUK_ASSERT(h_search != NULL);
43405 
43406 	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
43407 	pos = duk_to_int_clamped(thr, 1, 0, len);
43408 	DUK_ASSERT(pos >= 0 && pos <= len);
43409 
43410 	pos = duk__str_search_shared(thr, h, h_search, pos, 0 /*backwards*/);
43411 	duk_push_boolean(thr, pos >= 0);
43412 	return 1;
43413 }
43414 #endif  /* DUK_USE_ES6 */
43415 #endif  /* DUK_USE_STRING_BUILTIN */
43416 /*
43417  *  Symbol built-in
43418  */
43419 
43420 /* #include duk_internal.h -> already included */
43421 
43422 #if defined(DUK_USE_SYMBOL_BUILTIN)
43423 
43424 /*
43425  *  Constructor
43426  */
43427 
43428 DUK_INTERNAL duk_ret_t duk_bi_symbol_constructor_shared(duk_hthread *thr) {
43429 	const duk_uint8_t *desc;
43430 	duk_size_t len;
43431 	duk_uint8_t *buf;
43432 	duk_uint8_t *p;
43433 	duk_int_t magic;
43434 
43435 	magic = duk_get_current_magic(thr);
43436 	if (duk_is_undefined(thr, 0) && (magic == 0)) {
43437 		/* Symbol() accepts undefined and empty string, but they are
43438 		 * treated differently.
43439 		 */
43440 		desc = NULL;
43441 		len = 0;
43442 	} else {
43443 		/* Symbol.for() coerces undefined to 'undefined' */
43444 		desc = (const duk_uint8_t *) duk_to_lstring(thr, 0, &len);
43445 	}
43446 
43447 	/* Maximum symbol data length:
43448 	 *   +1    initial byte (0x80 or 0x81)
43449 	 *   +len  description
43450 	 *   +1    0xff after description, before unique suffix
43451 	 *   +17   autogenerated unique suffix: 'ffffffff-ffffffff' is longest
43452 	 *   +1    0xff after unique suffix for symbols with undefined description
43453 	 */
43454 	buf = (duk_uint8_t *) duk_push_fixed_buffer(thr, 1 + len + 1 + 17 + 1);
43455 	DUK_ASSERT(buf != NULL);
43456 	p = buf + 1;
43457 	DUK_ASSERT(desc != NULL || len == 0);  /* may be NULL if len is 0 */
43458 	duk_memcpy_unsafe((void *) p, (const void *) desc, len);
43459 	p += len;
43460 	if (magic == 0) {
43461 		/* Symbol(): create unique symbol.  Use two 32-bit values
43462 		 * to avoid dependency on 64-bit types and 64-bit integer
43463 		 * formatting (at least for now).
43464 		 */
43465 		if (++thr->heap->sym_counter[0] == 0) {
43466 			thr->heap->sym_counter[1]++;
43467 		}
43468 		p += DUK_SPRINTF((char *) p, "\xFF" "%lx-%lx",
43469 		                 (unsigned long) thr->heap->sym_counter[1],
43470 		                 (unsigned long) thr->heap->sym_counter[0]);
43471 		if (desc == NULL) {
43472 			/* Special case for 'undefined' description, trailing
43473 			 * 0xff distinguishes from empty string description,
43474 			 * but needs minimal special case handling elsewhere.
43475 			 */
43476 			*p++ = 0xff;
43477 		}
43478 		buf[0] = 0x81;
43479 	} else {
43480 		/* Symbol.for(): create a global symbol */
43481 		buf[0] = 0x80;
43482 	}
43483 
43484 	duk_push_lstring(thr, (const char *) buf, (duk_size_t) (p - buf));
43485 	DUK_DDD(DUK_DDDPRINT("created symbol: %!T", duk_get_tval(thr, -1)));
43486 	return 1;
43487 }
43488 
43489 DUK_LOCAL duk_hstring *duk__auto_unbox_symbol(duk_hthread *thr, duk_tval *tv_arg) {
43490 	duk_tval *tv;
43491 	duk_hobject *h_obj;
43492 	duk_hstring *h_str;
43493 
43494 	DUK_ASSERT(tv_arg != NULL);
43495 
43496 	/* XXX: add internal helper: duk_auto_unbox_tval(thr, tv, mask); */
43497 	/* XXX: add internal helper: duk_auto_unbox(thr, tv, idx); */
43498 
43499 	tv = tv_arg;
43500 	if (DUK_TVAL_IS_OBJECT(tv)) {
43501 		h_obj = DUK_TVAL_GET_OBJECT(tv);
43502 		DUK_ASSERT(h_obj != NULL);
43503 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_SYMBOL) {
43504 			tv = duk_hobject_get_internal_value_tval_ptr(thr->heap, h_obj);
43505 			if (tv == NULL) {
43506 				return NULL;
43507 			}
43508 		} else {
43509 			return NULL;
43510 		}
43511 	}
43512 
43513 	if (!DUK_TVAL_IS_STRING(tv)) {
43514 		return NULL;
43515 	}
43516 	h_str = DUK_TVAL_GET_STRING(tv);
43517 	DUK_ASSERT(h_str != NULL);
43518 
43519 	/* Here symbol is more expected than not. */
43520 	if (DUK_UNLIKELY(!DUK_HSTRING_HAS_SYMBOL(h_str))) {
43521 		return NULL;
43522 	}
43523 
43524 	return h_str;
43525 }
43526 
43527 DUK_INTERNAL duk_ret_t duk_bi_symbol_tostring_shared(duk_hthread *thr) {
43528 	duk_hstring *h_str;
43529 
43530 	h_str = duk__auto_unbox_symbol(thr, DUK_HTHREAD_THIS_PTR(thr));
43531 	if (h_str == NULL) {
43532 		return DUK_RET_TYPE_ERROR;
43533 	}
43534 
43535 	if (duk_get_current_magic(thr) == 0) {
43536 		/* .toString() */
43537 		duk_push_symbol_descriptive_string(thr, h_str);
43538 	} else {
43539 		/* .valueOf() */
43540 		duk_push_hstring(thr, h_str);
43541 	}
43542 	return 1;
43543 }
43544 
43545 DUK_INTERNAL duk_ret_t duk_bi_symbol_key_for(duk_hthread *thr) {
43546 	duk_hstring *h;
43547 	const duk_uint8_t *p;
43548 
43549 	/* Argument must be a symbol but not checked here.  The initial byte
43550 	 * check will catch non-symbol strings.
43551 	 */
43552 	h = duk_require_hstring(thr, 0);
43553 	DUK_ASSERT(h != NULL);
43554 
43555 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
43556 	DUK_ASSERT(p != NULL);
43557 
43558 	/* Even for zero length strings there's at least one NUL byte so
43559 	 * we can safely check the initial byte.
43560 	 */
43561 	if (p[0] == 0x80) {
43562 		/* Global symbol, return its key (bytes just after the initial byte). */
43563 		duk_push_lstring(thr, (const char *) (p + 1), (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h) - 1));
43564 		return 1;
43565 	} else if (p[0] == 0x81 || p[0] == 0x82 || p[0] == 0xff) {
43566 		/* Local symbol or hidden symbol, return undefined. */
43567 		return 0;
43568 	}
43569 
43570 	/* Covers normal strings and unknown initial bytes. */
43571 	return DUK_RET_TYPE_ERROR;
43572 }
43573 
43574 DUK_INTERNAL duk_ret_t duk_bi_symbol_toprimitive(duk_hthread *thr) {
43575 	duk_hstring *h_str;
43576 
43577 	h_str = duk__auto_unbox_symbol(thr, DUK_HTHREAD_THIS_PTR(thr));
43578 	if (h_str == NULL) {
43579 		return DUK_RET_TYPE_ERROR;
43580 	}
43581 	duk_push_hstring(thr, h_str);
43582 	return 1;
43583 }
43584 
43585 #endif  /* DUK_USE_SYMBOL_BUILTIN */
43586 /*
43587  *  Thread builtins
43588  */
43589 
43590 /* #include duk_internal.h -> already included */
43591 
43592 /*
43593  *  Constructor
43594  */
43595 
43596 #if defined(DUK_USE_COROUTINE_SUPPORT)
43597 DUK_INTERNAL duk_ret_t duk_bi_thread_constructor(duk_hthread *thr) {
43598 	duk_hthread *new_thr;
43599 	duk_hobject *func;
43600 
43601 	/* Check that the argument is callable; this is not 100% because we
43602 	 * don't allow native functions to be a thread's initial function.
43603 	 * Resume will reject such functions in any case.
43604 	 */
43605 	/* XXX: need a duk_require_func_promote_lfunc() */
43606 	func = duk_require_hobject_promote_lfunc(thr, 0);
43607 	DUK_ASSERT(func != NULL);
43608 	duk_require_callable(thr, 0);
43609 
43610 	duk_push_thread(thr);
43611 	new_thr = (duk_hthread *) duk_known_hobject(thr, -1);
43612 	new_thr->state = DUK_HTHREAD_STATE_INACTIVE;
43613 
43614 	/* push initial function call to new thread stack; this is
43615 	 * picked up by resume().
43616 	 */
43617 	duk_push_hobject(new_thr, func);
43618 
43619 	return 1;  /* return thread */
43620 }
43621 #endif
43622 
43623 /*
43624  *  Resume a thread.
43625  *
43626  *  The thread must be in resumable state, either (a) new thread which hasn't
43627  *  yet started, or (b) a thread which has previously yielded.  This method
43628  *  must be called from an ECMAScript function.
43629  *
43630  *  Args:
43631  *    - thread
43632  *    - value
43633  *    - isError (defaults to false)
43634  *
43635  *  Note: yield and resume handling is currently asymmetric.
43636  */
43637 
43638 #if defined(DUK_USE_COROUTINE_SUPPORT)
43639 DUK_INTERNAL duk_ret_t duk_bi_thread_resume(duk_hthread *ctx) {
43640 	duk_hthread *thr = (duk_hthread *) ctx;
43641 	duk_hthread *thr_resume;
43642 	duk_hobject *caller_func;
43643 	duk_small_uint_t is_error;
43644 
43645 	DUK_DDD(DUK_DDDPRINT("Duktape.Thread.resume(): thread=%!T, value=%!T, is_error=%!T",
43646 	                     (duk_tval *) duk_get_tval(thr, 0),
43647 	                     (duk_tval *) duk_get_tval(thr, 1),
43648 	                     (duk_tval *) duk_get_tval(thr, 2)));
43649 
43650 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
43651 	DUK_ASSERT(thr->heap->curr_thread == thr);
43652 
43653 	thr_resume = duk_require_hthread(thr, 0);
43654 	DUK_ASSERT(duk_get_top(thr) == 3);
43655 	is_error = (duk_small_uint_t) duk_to_boolean_top_pop(thr);
43656 	DUK_ASSERT(duk_get_top(thr) == 2);
43657 
43658 	/* [ thread value ] */
43659 
43660 	/*
43661 	 *  Thread state and calling context checks
43662 	 */
43663 
43664 	if (thr->callstack_top < 2) {
43665 		DUK_DD(DUK_DDPRINT("resume state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.resume)"));
43666 		goto state_error;
43667 	}
43668 	DUK_ASSERT(thr->callstack_curr != NULL);
43669 	DUK_ASSERT(thr->callstack_curr->parent != NULL);
43670 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);  /* us */
43671 	DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
43672 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL);  /* caller */
43673 
43674 	caller_func = DUK_ACT_GET_FUNC(thr->callstack_curr->parent);
43675 	if (!DUK_HOBJECT_IS_COMPFUNC(caller_func)) {
43676 		DUK_DD(DUK_DDPRINT("resume state invalid: caller must be ECMAScript code"));
43677 		goto state_error;
43678 	}
43679 
43680 	/* Note: there is no requirement that: 'thr->callstack_preventcount == 1'
43681 	 * like for yield.
43682 	 */
43683 
43684 	if (thr_resume->state != DUK_HTHREAD_STATE_INACTIVE &&
43685 	    thr_resume->state != DUK_HTHREAD_STATE_YIELDED) {
43686 		DUK_DD(DUK_DDPRINT("resume state invalid: target thread must be INACTIVE or YIELDED"));
43687 		goto state_error;
43688 	}
43689 
43690 	DUK_ASSERT(thr_resume->state == DUK_HTHREAD_STATE_INACTIVE ||
43691 	           thr_resume->state == DUK_HTHREAD_STATE_YIELDED);
43692 
43693 	/* Further state-dependent pre-checks */
43694 
43695 	if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
43696 		/* no pre-checks now, assume a previous yield() has left things in
43697 		 * tip-top shape (longjmp handler will assert for these).
43698 		 */
43699 	} else {
43700 		duk_hobject *h_fun;
43701 
43702 		DUK_ASSERT(thr_resume->state == DUK_HTHREAD_STATE_INACTIVE);
43703 
43704 		/* The initial function must be an ECMAScript function (but
43705 		 * can be bound).  We must make sure of that before we longjmp
43706 		 * because an error in the RESUME handler call processing will
43707 		 * not be handled very cleanly.
43708 		 */
43709 		if ((thr_resume->callstack_top != 0) ||
43710 		    (thr_resume->valstack_top - thr_resume->valstack != 1)) {
43711 			goto state_error;
43712 		}
43713 
43714 		duk_push_tval(thr, DUK_GET_TVAL_NEGIDX(thr_resume, -1));
43715 		duk_resolve_nonbound_function(thr);
43716 		h_fun = duk_require_hobject(thr, -1);  /* reject lightfuncs on purpose */
43717 		if (!DUK_HOBJECT_IS_CALLABLE(h_fun) || !DUK_HOBJECT_IS_COMPFUNC(h_fun)) {
43718 			goto state_error;
43719 		}
43720 		duk_pop(thr);
43721 	}
43722 
43723 #if 0
43724 	/* This check would prevent a heap destruction time finalizer from
43725 	 * launching a coroutine, which would ensure that during finalization
43726 	 * 'thr' would always equal heap_thread.  Normal runtime finalizers
43727 	 * run with ms_running == 0, i.e. outside mark-and-sweep.  See GH-2030.
43728 	 */
43729 	if (thr->heap->ms_running) {
43730 		DUK_D(DUK_DPRINT("refuse Duktape.Thread.resume() when ms_running != 0"));
43731 		goto state_error;
43732 	}
43733 #endif
43734 
43735 	/*
43736 	 *  The error object has been augmented with a traceback and other
43737 	 *  info from its creation point -- usually another thread.  The
43738 	 *  error handler is called here right before throwing, but it also
43739 	 *  runs in the resumer's thread.  It might be nice to get a traceback
43740 	 *  from the resumee but this is not the case now.
43741 	 */
43742 
43743 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
43744 	if (is_error) {
43745 		DUK_ASSERT_TOP(thr, 2);  /* value (error) is at stack top */
43746 		duk_err_augment_error_throw(thr);  /* in resumer's context */
43747 	}
43748 #endif
43749 
43750 #if defined(DUK_USE_DEBUG)
43751 	if (is_error) {
43752 		DUK_DDD(DUK_DDDPRINT("RESUME ERROR: thread=%!T, value=%!T",
43753 		                     (duk_tval *) duk_get_tval(thr, 0),
43754 		                     (duk_tval *) duk_get_tval(thr, 1)));
43755 	} else if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
43756 		DUK_DDD(DUK_DDDPRINT("RESUME NORMAL: thread=%!T, value=%!T",
43757 		                     (duk_tval *) duk_get_tval(thr, 0),
43758 		                     (duk_tval *) duk_get_tval(thr, 1)));
43759 	} else {
43760 		DUK_DDD(DUK_DDDPRINT("RESUME INITIAL: thread=%!T, value=%!T",
43761 		                     (duk_tval *) duk_get_tval(thr, 0),
43762 		                     (duk_tval *) duk_get_tval(thr, 1)));
43763 	}
43764 #endif
43765 
43766 	thr->heap->lj.type = DUK_LJ_TYPE_RESUME;
43767 
43768 	/* lj value2: thread */
43769 	DUK_ASSERT(thr->valstack_bottom < thr->valstack_top);
43770 	DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value2, &thr->valstack_bottom[0]);  /* side effects */
43771 
43772 	/* lj value1: value */
43773 	DUK_ASSERT(thr->valstack_bottom + 1 < thr->valstack_top);
43774 	DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[1]);  /* side effects */
43775 	DUK_TVAL_CHKFAST_INPLACE_SLOW(&thr->heap->lj.value1);
43776 
43777 	thr->heap->lj.iserror = is_error;
43778 
43779 	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* call is from executor, so we know we have a jmpbuf */
43780 	duk_err_longjmp(thr);  /* execution resumes in bytecode executor */
43781 	DUK_UNREACHABLE();
43782 	/* Never here, fall through to error (from compiler point of view). */
43783 
43784  state_error:
43785 	DUK_DCERROR_TYPE_INVALID_STATE(thr);
43786 }
43787 #endif
43788 
43789 /*
43790  *  Yield the current thread.
43791  *
43792  *  The thread must be in yieldable state: it must have a resumer, and there
43793  *  must not be any yield-preventing calls (native calls and constructor calls,
43794  *  currently) in the thread's call stack (otherwise a resume would not be
43795  *  possible later).  This method must be called from an ECMAScript function.
43796  *
43797  *  Args:
43798  *    - value
43799  *    - isError (defaults to false)
43800  *
43801  *  Note: yield and resume handling is currently asymmetric.
43802  */
43803 
43804 #if defined(DUK_USE_COROUTINE_SUPPORT)
43805 DUK_INTERNAL duk_ret_t duk_bi_thread_yield(duk_hthread *thr) {
43806 	duk_hobject *caller_func;
43807 	duk_small_uint_t is_error;
43808 
43809 	DUK_DDD(DUK_DDDPRINT("Duktape.Thread.yield(): value=%!T, is_error=%!T",
43810 	                     (duk_tval *) duk_get_tval(thr, 0),
43811 	                     (duk_tval *) duk_get_tval(thr, 1)));
43812 
43813 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
43814 	DUK_ASSERT(thr->heap->curr_thread == thr);
43815 
43816 	DUK_ASSERT(duk_get_top(thr) == 2);
43817 	is_error = (duk_small_uint_t) duk_to_boolean_top_pop(thr);
43818 	DUK_ASSERT(duk_get_top(thr) == 1);
43819 
43820 	/* [ value ] */
43821 
43822 	/*
43823 	 *  Thread state and calling context checks
43824 	 */
43825 
43826 	if (!thr->resumer) {
43827 		DUK_DD(DUK_DDPRINT("yield state invalid: current thread must have a resumer"));
43828 		goto state_error;
43829 	}
43830 	DUK_ASSERT(thr->resumer->state == DUK_HTHREAD_STATE_RESUMED);
43831 
43832 	if (thr->callstack_top < 2) {
43833 		DUK_DD(DUK_DDPRINT("yield state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.yield)"));
43834 		goto state_error;
43835 	}
43836 	DUK_ASSERT(thr->callstack_curr != NULL);
43837 	DUK_ASSERT(thr->callstack_curr->parent != NULL);
43838 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);  /* us */
43839 	DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
43840 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL);  /* caller */
43841 
43842 	caller_func = DUK_ACT_GET_FUNC(thr->callstack_curr->parent);
43843 	if (!DUK_HOBJECT_IS_COMPFUNC(caller_func)) {
43844 		DUK_DD(DUK_DDPRINT("yield state invalid: caller must be ECMAScript code"));
43845 		goto state_error;
43846 	}
43847 
43848 	DUK_ASSERT(thr->callstack_preventcount >= 1);  /* should never be zero, because we (Duktape.Thread.yield) are on the stack */
43849 	if (thr->callstack_preventcount != 1) {
43850 		/* Note: the only yield-preventing call is Duktape.Thread.yield(), hence check for 1, not 0 */
43851 		DUK_DD(DUK_DDPRINT("yield state invalid: there must be no yield-preventing calls in current thread callstack (preventcount is %ld)",
43852 		                   (long) thr->callstack_preventcount));
43853 		goto state_error;
43854 	}
43855 
43856 	/*
43857 	 *  The error object has been augmented with a traceback and other
43858 	 *  info from its creation point -- usually the current thread.
43859 	 *  The error handler, however, is called right before throwing
43860 	 *  and runs in the yielder's thread.
43861 	 */
43862 
43863 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
43864 	if (is_error) {
43865 		DUK_ASSERT_TOP(thr, 1);  /* value (error) is at stack top */
43866 		duk_err_augment_error_throw(thr);  /* in yielder's context */
43867 	}
43868 #endif
43869 
43870 #if defined(DUK_USE_DEBUG)
43871 	if (is_error) {
43872 		DUK_DDD(DUK_DDDPRINT("YIELD ERROR: value=%!T",
43873 		                     (duk_tval *) duk_get_tval(thr, 0)));
43874 	} else {
43875 		DUK_DDD(DUK_DDDPRINT("YIELD NORMAL: value=%!T",
43876 		                     (duk_tval *) duk_get_tval(thr, 0)));
43877 	}
43878 #endif
43879 
43880 	/*
43881 	 *  Process yield
43882 	 *
43883 	 *  After longjmp(), processing continues in bytecode executor longjmp
43884 	 *  handler, which will e.g. update thr->resumer to NULL.
43885 	 */
43886 
43887 	thr->heap->lj.type = DUK_LJ_TYPE_YIELD;
43888 
43889 	/* lj value1: value */
43890 	DUK_ASSERT(thr->valstack_bottom < thr->valstack_top);
43891 	DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[0]);  /* side effects */
43892 	DUK_TVAL_CHKFAST_INPLACE_SLOW(&thr->heap->lj.value1);
43893 
43894 	thr->heap->lj.iserror = is_error;
43895 
43896 	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* call is from executor, so we know we have a jmpbuf */
43897 	duk_err_longjmp(thr);  /* execution resumes in bytecode executor */
43898 	DUK_UNREACHABLE();
43899 	/* Never here, fall through to error (from compiler point of view). */
43900 
43901  state_error:
43902 	DUK_DCERROR_TYPE_INVALID_STATE(thr);
43903 }
43904 #endif
43905 
43906 #if defined(DUK_USE_COROUTINE_SUPPORT)
43907 DUK_INTERNAL duk_ret_t duk_bi_thread_current(duk_hthread *thr) {
43908 	duk_push_current_thread(thr);
43909 	return 1;
43910 }
43911 #endif
43912 /*
43913  *  Type error thrower, E5 Section 13.2.3.
43914  */
43915 
43916 /* #include duk_internal.h -> already included */
43917 
43918 DUK_INTERNAL duk_ret_t duk_bi_type_error_thrower(duk_hthread *thr) {
43919 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
43920 }
43921 /*
43922  *  Fixed buffer helper useful for debugging, requires no allocation
43923  *  which is critical for debugging.
43924  */
43925 
43926 /* #include duk_internal.h -> already included */
43927 
43928 #if defined(DUK_USE_DEBUG)
43929 
43930 DUK_INTERNAL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length) {
43931 	duk_size_t avail;
43932 	duk_size_t copylen;
43933 
43934 	avail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));
43935 	if (length > avail) {
43936 		copylen = avail;
43937 		fb->truncated = 1;
43938 	} else {
43939 		copylen = length;
43940 	}
43941 	duk_memcpy_unsafe(fb->buffer + fb->offset, buffer, copylen);
43942 	fb->offset += copylen;
43943 }
43944 
43945 DUK_INTERNAL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x) {
43946 	duk_fb_put_bytes(fb, (const duk_uint8_t *) &x, 1);
43947 }
43948 
43949 DUK_INTERNAL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x) {
43950 	duk_fb_put_bytes(fb, (const duk_uint8_t *) x, (duk_size_t) DUK_STRLEN(x));
43951 }
43952 
43953 DUK_INTERNAL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...) {
43954 	duk_size_t avail;
43955 	va_list ap;
43956 
43957 	va_start(ap, fmt);
43958 	avail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));
43959 	if (avail > 0) {
43960 		duk_int_t res = (duk_int_t) DUK_VSNPRINTF((char *) (fb->buffer + fb->offset), avail, fmt, ap);
43961 		if (res < 0) {
43962 			/* error */
43963 		} else if ((duk_size_t) res >= avail) {
43964 			/* (maybe) truncated */
43965 			fb->offset += avail;
43966 			if ((duk_size_t) res > avail) {
43967 				/* actual chars dropped (not just NUL term) */
43968 				fb->truncated = 1;
43969 			}
43970 		} else {
43971 			/* normal */
43972 			fb->offset += (duk_size_t) res;
43973 		}
43974 	}
43975 	va_end(ap);
43976 }
43977 
43978 DUK_INTERNAL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size) {
43979 	char buf[64+1];
43980 	duk_debug_format_funcptr(buf, sizeof(buf), fptr, fptr_size);
43981 	buf[sizeof(buf) - 1] = (char) 0;
43982 	duk_fb_put_cstring(fb, buf);
43983 }
43984 
43985 DUK_INTERNAL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb) {
43986 	return (fb->offset >= fb->length);
43987 }
43988 
43989 #endif  /* DUK_USE_DEBUG */
43990 /*
43991  *  Custom formatter for debug printing, allowing Duktape specific data
43992  *  structures (such as tagged values and heap objects) to be printed with
43993  *  a nice format string.  Because debug printing should not affect execution
43994  *  state, formatting here must be independent of execution (see implications
43995  *  below) and must not allocate memory.
43996  *
43997  *  Custom format tags begin with a '%!' to safely distinguish them from
43998  *  standard format tags.  The following conversions are supported:
43999  *
44000  *     %!T    tagged value (duk_tval *)
44001  *     %!O    heap object (duk_heaphdr *)
44002  *     %!I    decoded bytecode instruction
44003  *     %!X    bytecode instruction opcode name (arg is long)
44004  *     %!C    catcher (duk_catcher *)
44005  *     %!A    activation (duk_activation *)
44006  *
44007  *  Everything is serialized in a JSON-like manner.  The default depth is one
44008  *  level, internal prototype is not followed, and internal properties are not
44009  *  serialized.  The following modifiers change this behavior:
44010  *
44011  *     @      print pointers
44012  *     #      print binary representations (where applicable)
44013  *     d      deep traversal of own properties (not prototype)
44014  *     p      follow prototype chain (useless without 'd')
44015  *     i      include internal properties (other than prototype)
44016  *     x      hexdump buffers
44017  *     h      heavy formatting
44018  *
44019  *  For instance, the following serializes objects recursively, but does not
44020  *  follow the prototype chain nor print internal properties: "%!dO".
44021  *
44022  *  Notes:
44023  *
44024  *    * Standard snprintf return value semantics seem to vary.  This
44025  *      implementation returns the number of bytes it actually wrote
44026  *      (excluding the null terminator).  If retval == buffer size,
44027  *      output was truncated (except for corner cases).
44028  *
44029  *    * Output format is intentionally different from ECMAScript
44030  *      formatting requirements, as formatting here serves debugging
44031  *      of internals.
44032  *
44033  *    * Depth checking (and updating) is done in each type printer
44034  *      separately, to allow them to call each other freely.
44035  *
44036  *    * Some pathological structures might take ages to print (e.g.
44037  *      self recursion with 100 properties pointing to the object
44038  *      itself).  To guard against these, each printer also checks
44039  *      whether the output buffer is full; if so, early exit.
44040  *
44041  *    * Reference loops are detected using a loop stack.
44042  */
44043 
44044 /* #include duk_internal.h -> already included */
44045 
44046 #if defined(DUK_USE_DEBUG)
44047 
44048 /* #include stdio.h -> already included */
44049 /* #include stdarg.h -> already included */
44050 #include <string.h>
44051 
44052 /* list of conversion specifiers that terminate a format tag;
44053  * this is unfortunately guesswork.
44054  */
44055 #define DUK__ALLOWED_STANDARD_SPECIFIERS  "diouxXeEfFgGaAcsCSpnm"
44056 
44057 /* maximum length of standard format tag that we support */
44058 #define DUK__MAX_FORMAT_TAG_LENGTH  32
44059 
44060 /* heapobj recursion depth when deep printing is selected */
44061 #define DUK__DEEP_DEPTH_LIMIT  8
44062 
44063 /* maximum recursion depth for loop detection stacks */
44064 #define DUK__LOOP_STACK_DEPTH  256
44065 
44066 /* must match bytecode defines now; build autogenerate? */
44067 DUK_LOCAL const char * const duk__bc_optab[256] = {
44068 	"LDREG", "STREG", "JUMP", "LDCONST", "LDINT", "LDINTX", "LDTHIS", "LDUNDEF",
44069 	"LDNULL", "LDTRUE", "LDFALSE", "GETVAR", "BNOT", "LNOT", "UNM", "UNP",
44070 	"EQ_RR", "EQ_CR", "EQ_RC", "EQ_CC", "NEQ_RR", "NEQ_CR", "NEQ_RC", "NEQ_CC",
44071 	"SEQ_RR", "SEQ_CR", "SEQ_RC", "SEQ_CC", "SNEQ_RR", "SNEQ_CR", "SNEQ_RC", "SNEQ_CC",
44072 
44073 	"GT_RR", "GT_CR", "GT_RC", "GT_CC", "GE_RR", "GE_CR", "GE_RC", "GE_CC",
44074 	"LT_RR", "LT_CR", "LT_RC", "LT_CC", "LE_RR", "LE_CR", "LE_RC", "LE_CC",
44075 	"IFTRUE_R", "IFTRUE_C", "IFFALSE_R", "IFFALSE_C", "ADD_RR", "ADD_CR", "ADD_RC", "ADD_CC",
44076 	"SUB_RR", "SUB_CR", "SUB_RC", "SUB_CC", "MUL_RR", "MUL_CR", "MUL_RC", "MUL_CC",
44077 
44078 	"DIV_RR", "DIV_CR", "DIV_RC", "DIV_CC", "MOD_RR", "MOD_CR", "MOD_RC", "MOD_CC",
44079 	"EXP_RR", "EXP_CR", "EXP_RC", "EXP_CC", "BAND_RR", "BAND_CR", "BAND_RC", "BAND_CC",
44080 	"BOR_RR", "BOR_CR", "BOR_RC", "BOR_CC", "BXOR_RR", "BXOR_CR", "BXOR_RC", "BXOR_CC",
44081 	"BASL_RR", "BASL_CR", "BASL_RC", "BASL_CC", "BLSR_RR", "BLSR_CR", "BLSR_RC", "BLSR_CC",
44082 
44083 	"BASR_RR", "BASR_CR", "BASR_RC", "BASR_CC", "INSTOF_RR", "INSTOF_CR", "INSTOF_RC", "INSTOF_CC",
44084 	"IN_RR", "IN_CR", "IN_RC", "IN_CC", "GETPROP_RR", "GETPROP_CR", "GETPROP_RC", "GETPROP_CC",
44085 	"PUTPROP_RR", "PUTPROP_CR", "PUTPROP_RC", "PUTPROP_CC", "DELPROP_RR", "DELPROP_CR", "DELPROP_RC", "DELPROP_CC",
44086 	"PREINCR", "PREDECR", "POSTINCR", "POSTDECR", "PREINCV", "PREDECV", "POSTINCV", "POSTDECV",
44087 
44088 	"PREINCP_RR", "PREINCP_CR", "PREINCP_RC", "PREINCP_CC", "PREDECP_RR", "PREDECP_CR", "PREDECP_RC", "PREDECP_CC",
44089 	"POSTINCP_RR", "POSTINCP_CR", "POSTINCP_RC", "POSTINCP_CC", "POSTDECP_RR", "POSTDECP_CR", "POSTDECP_RC", "POSTDECP_CC",
44090 	"DECLVAR_RR", "DECLVAR_CR", "DECLVAR_RC", "DECLVAR_CC", "REGEXP_RR", "REGEXP_RC", "REGEXP_CR", "REGEXP_CC",
44091 	"CLOSURE", "TYPEOF", "TYPEOFID", "PUTVAR", "DELVAR", "RETREG", "RETUNDEF", "RETCONST",
44092 
44093 	"RETCONSTN", "LABEL", "ENDLABEL", "BREAK", "CONTINUE", "TRYCATCH", "ENDTRY", "ENDCATCH",
44094 	"ENDFIN", "THROW", "INVLHS", "CSREG", "CSVAR_RR", "CSVAR_CR", "CSVAR_RC", "CSVAR_CC",
44095 	"CALL0", "CALL1", "CALL2", "CALL3", "CALL4", "CALL5", "CALL6", "CALL7",
44096 	"CALL8", "CALL9", "CALL10", "CALL11", "CALL12", "CALL13", "CALL14", "CALL15",
44097 
44098 	"NEWOBJ", "NEWARR", "MPUTOBJ", "MPUTOBJI", "INITSET", "INITGET", "MPUTARR", "MPUTARRI",
44099 	"SETALEN", "INITENUM", "NEXTENUM", "NEWTARGET", "DEBUGGER", "NOP", "INVALID", "UNUSED207",
44100 	"GETPROPC_RR", "GETPROPC_CR", "GETPROPC_RC", "GETPROPC_CC", "UNUSED212", "UNUSED213", "UNUSED214", "UNUSED215",
44101 	"UNUSED216", "UNUSED217", "UNUSED218", "UNUSED219", "UNUSED220", "UNUSED221", "UNUSED222", "UNUSED223",
44102 
44103 	"UNUSED224", "UNUSED225", "UNUSED226", "UNUSED227", "UNUSED228", "UNUSED229", "UNUSED230", "UNUSED231",
44104 	"UNUSED232", "UNUSED233", "UNUSED234", "UNUSED235", "UNUSED236", "UNUSED237", "UNUSED238", "UNUSED239",
44105 	"UNUSED240", "UNUSED241", "UNUSED242", "UNUSED243", "UNUSED244", "UNUSED245", "UNUSED246", "UNUSED247",
44106 	"UNUSED248", "UNUSED249", "UNUSED250", "UNUSED251", "UNUSED252", "UNUSED253", "UNUSED254", "UNUSED255"
44107 };
44108 
44109 typedef struct duk__dprint_state duk__dprint_state;
44110 struct duk__dprint_state {
44111 	duk_fixedbuffer *fb;
44112 
44113 	/* loop_stack_index could be perhaps be replaced by 'depth', but it's nice
44114 	 * to not couple these two mechanisms unnecessarily.
44115 	 */
44116 	duk_hobject *loop_stack[DUK__LOOP_STACK_DEPTH];
44117 	duk_int_t loop_stack_index;
44118 	duk_int_t loop_stack_limit;
44119 
44120 	duk_int_t depth;
44121 	duk_int_t depth_limit;
44122 
44123 	duk_bool_t pointer;
44124 	duk_bool_t heavy;
44125 	duk_bool_t binary;
44126 	duk_bool_t follow_proto;
44127 	duk_bool_t internal;
44128 	duk_bool_t hexdump;
44129 };
44130 
44131 /* helpers */
44132 DUK_LOCAL_DECL void duk__print_hstring(duk__dprint_state *st, duk_hstring *k, duk_bool_t quotes);
44133 DUK_LOCAL_DECL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h);
44134 DUK_LOCAL_DECL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h);
44135 DUK_LOCAL_DECL void duk__print_tval(duk__dprint_state *st, duk_tval *tv);
44136 DUK_LOCAL_DECL void duk__print_instr(duk__dprint_state *st, duk_instr_t ins);
44137 DUK_LOCAL_DECL void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h);
44138 DUK_LOCAL_DECL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h);
44139 DUK_LOCAL_DECL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h);
44140 
44141 DUK_LOCAL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {
44142 	duk_fixedbuffer *fb = st->fb;
44143 
44144 	if (st->heavy) {
44145 		duk_fb_sprintf(fb, "(%p)", (void *) h);
44146 	}
44147 
44148 	if (!h) {
44149 		return;
44150 	}
44151 
44152 	if (st->binary) {
44153 		duk_size_t i;
44154 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
44155 		for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
44156 			duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)h)[i]);
44157 		}
44158 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
44159 	}
44160 
44161 #if defined(DUK_USE_REFERENCE_COUNTING)  /* currently implicitly also DUK_USE_DOUBLE_LINKED_HEAP */
44162 	if (st->heavy) {
44163 		duk_fb_sprintf(fb, "[h_next=%p,h_prev=%p,h_refcount=%lu,h_flags=%08lx,type=%ld,"
44164 		               "reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
44165 		               (void *) DUK_HEAPHDR_GET_NEXT(NULL, h),
44166 		               (void *) DUK_HEAPHDR_GET_PREV(NULL, h),
44167 		               (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(h),
44168 		               (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),
44169 		               (long) DUK_HEAPHDR_GET_TYPE(h),
44170 		               (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),
44171 		               (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),
44172 		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),
44173 		               (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));
44174 	}
44175 #else
44176 	if (st->heavy) {
44177 		duk_fb_sprintf(fb, "[h_next=%p,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
44178 		               (void *) DUK_HEAPHDR_GET_NEXT(NULL, h),
44179 		               (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),
44180 		               (long) DUK_HEAPHDR_GET_TYPE(h),
44181 		               (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),
44182 		               (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),
44183 		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),
44184 		               (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));
44185 	}
44186 #endif
44187 }
44188 
44189 DUK_LOCAL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h) {
44190 	duk_fixedbuffer *fb = st->fb;
44191 
44192 	if (st->heavy) {
44193 		duk_fb_sprintf(fb, "(%p)", (void *) h);
44194 	}
44195 
44196 	if (!h) {
44197 		return;
44198 	}
44199 
44200 	if (st->binary) {
44201 		duk_size_t i;
44202 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
44203 		for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
44204 			duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)h)[i]);
44205 		}
44206 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
44207 	}
44208 
44209 #if defined(DUK_USE_REFERENCE_COUNTING)
44210 	if (st->heavy) {
44211 		duk_fb_sprintf(fb, "[h_refcount=%lu,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
44212 		               (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h),
44213 		               (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
44214 		               (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
44215 		               (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),
44216 		               (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),
44217 		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),
44218 		               (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));
44219 	}
44220 #else
44221 	if (st->heavy) {
44222 		duk_fb_sprintf(fb, "[h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
44223 		               (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
44224 		               (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
44225 		               (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),
44226 		               (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),
44227 		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),
44228 		               (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));
44229 	}
44230 #endif
44231 }
44232 
44233 DUK_LOCAL void duk__print_hstring(duk__dprint_state *st, duk_hstring *h, duk_bool_t quotes) {
44234 	duk_fixedbuffer *fb = st->fb;
44235 	const duk_uint8_t *p;
44236 	const duk_uint8_t *p_end;
44237 
44238 	/* terminal type: no depth check */
44239 
44240 	if (duk_fb_is_full(fb)) {
44241 		return;
44242 	}
44243 
44244 	duk__print_shared_heaphdr_string(st, &h->hdr);
44245 
44246 	if (!h) {
44247 		duk_fb_put_cstring(fb, "NULL");
44248 		return;
44249 	}
44250 
44251 	p = DUK_HSTRING_GET_DATA(h);
44252 	p_end = p + DUK_HSTRING_GET_BYTELEN(h);
44253 
44254 	if (p_end > p && p[0] == DUK_ASC_UNDERSCORE) {
44255 		/* If property key begins with underscore, encode it with
44256 		 * forced quotes (e.g. "_Foo") to distinguish it from encoded
44257 		 * internal properties (e.g. \x82Bar -> _Bar).
44258 		 */
44259 		quotes = 1;
44260 	}
44261 
44262 	if (quotes) {
44263 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);
44264 	}
44265 	while (p < p_end) {
44266 		duk_uint8_t ch = *p++;
44267 
44268 		/* two special escapes: '\' and '"', other printables as is */
44269 		if (ch == '\\') {
44270 			duk_fb_sprintf(fb, "\\\\");
44271 		} else if (ch == '"') {
44272 			duk_fb_sprintf(fb, "\\\"");
44273 		} else if (ch >= 0x20 && ch <= 0x7e) {
44274 			duk_fb_put_byte(fb, ch);
44275 		} else if (ch == 0x82 && !quotes) {
44276 			/* encode \x82Bar as _Bar if no quotes are
44277 			 * applied, this is for readable internal keys.
44278 			 */
44279 			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_UNDERSCORE);
44280 		} else {
44281 			duk_fb_sprintf(fb, "\\x%02lx", (unsigned long) ch);
44282 		}
44283 	}
44284 	if (quotes) {
44285 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);
44286 	}
44287 #if defined(DUK_USE_REFERENCE_COUNTING)
44288 	/* XXX: limit to quoted strings only, to save keys from being cluttered? */
44289 	duk_fb_sprintf(fb, "/%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));
44290 #endif
44291 }
44292 
44293 #define DUK__COMMA()  do { \
44294 		if (first) { \
44295 			first = 0; \
44296 		} else { \
44297 			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA); \
44298 		} \
44299 	} while (0)
44300 
44301 DUK_LOCAL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h) {
44302 	duk_fixedbuffer *fb = st->fb;
44303 	duk_uint_fast32_t i;
44304 	duk_tval *tv;
44305 	duk_hstring *key;
44306 	duk_bool_t first = 1;
44307 	const char *brace1 = "{";
44308 	const char *brace2 = "}";
44309 	duk_bool_t pushed_loopstack = 0;
44310 
44311 	if (duk_fb_is_full(fb)) {
44312 		return;
44313 	}
44314 
44315 	duk__print_shared_heaphdr(st, &h->hdr);
44316 
44317 	if (h && DUK_HOBJECT_HAS_ARRAY_PART(h)) {
44318 		brace1 = "[";
44319 		brace2 = "]";
44320 	}
44321 
44322 	if (!h) {
44323 		duk_fb_put_cstring(fb, "NULL");
44324 		goto finished;
44325 	}
44326 
44327 	if (st->depth >= st->depth_limit) {
44328 		const char *subtype = "generic";
44329 
44330 		if (DUK_HOBJECT_IS_COMPFUNC(h)) {
44331 			subtype = "compfunc";
44332 		} else if (DUK_HOBJECT_IS_NATFUNC(h)) {
44333 			subtype = "natfunc";
44334 		} else if (DUK_HOBJECT_IS_THREAD(h)) {
44335 			subtype = "thread";
44336 		} else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
44337 			subtype = "bufobj";
44338 		} else if (DUK_HOBJECT_IS_ARRAY(h)) {
44339 			subtype = "array";
44340 		}
44341 		duk_fb_sprintf(fb, "%sobject/%s %p%s", (const char *) brace1, subtype, (void *) h, (const char *) brace2);
44342 		return;
44343 	}
44344 
44345 	for (i = 0; i < (duk_uint_fast32_t) st->loop_stack_index; i++) {
44346 		if (st->loop_stack[i] == h) {
44347 			duk_fb_sprintf(fb, "%sLOOP:%p%s", (const char *) brace1, (void *) h, (const char *) brace2);
44348 			return;
44349 		}
44350 	}
44351 
44352 	/* after this, return paths should 'goto finished' for decrement */
44353 	st->depth++;
44354 
44355 	if (st->loop_stack_index >= st->loop_stack_limit) {
44356 		duk_fb_sprintf(fb, "%sOUT-OF-LOOP-STACK%s", (const char *) brace1, (const char *) brace2);
44357 		goto finished;
44358 	}
44359 	st->loop_stack[st->loop_stack_index++] = h;
44360 	pushed_loopstack = 1;
44361 
44362 	/*
44363 	 *  Notation: double underscore used for internal properties which are not
44364 	 *  stored in the property allocation (e.g. '__valstack').
44365 	 */
44366 
44367 	duk_fb_put_cstring(fb, brace1);
44368 
44369 	if (DUK_HOBJECT_GET_PROPS(NULL, h)) {
44370 		duk_uint32_t a_limit;
44371 
44372 		a_limit = DUK_HOBJECT_GET_ASIZE(h);
44373 		if (st->internal) {
44374 			/* dump all allocated entries, unused entries print as 'unused',
44375 			 * note that these may extend beyond current 'length' and look
44376 			 * a bit funny.
44377 			 */
44378 		} else {
44379 			/* leave out trailing 'unused' elements */
44380 			while (a_limit > 0) {
44381 				tv = DUK_HOBJECT_A_GET_VALUE_PTR(NULL, h, a_limit - 1);
44382 				if (!DUK_TVAL_IS_UNUSED(tv)) {
44383 					break;
44384 				}
44385 				a_limit--;
44386 			}
44387 		}
44388 
44389 		for (i = 0; i < a_limit; i++) {
44390 			tv = DUK_HOBJECT_A_GET_VALUE_PTR(NULL, h, i);
44391 			DUK__COMMA();
44392 			duk__print_tval(st, tv);
44393 		}
44394 		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(h); i++) {
44395 			key = DUK_HOBJECT_E_GET_KEY(NULL, h, i);
44396 			if (!key) {
44397 				continue;
44398 			}
44399 			if (!st->internal && DUK_HSTRING_HAS_HIDDEN(key)) {
44400 				continue;
44401 			}
44402 			DUK__COMMA();
44403 			duk__print_hstring(st, key, 0);
44404 			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COLON);
44405 			if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(NULL, h, i)) {
44406 				duk_fb_sprintf(fb, "[get:%p,set:%p]",
44407 				               (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.get,
44408 				               (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.set);
44409 			} else {
44410 				tv = &DUK_HOBJECT_E_GET_VALUE(NULL, h, i).v;
44411 				duk__print_tval(st, tv);
44412 			}
44413 			if (st->heavy) {
44414 				duk_fb_sprintf(fb, "<%02lx>", (unsigned long) DUK_HOBJECT_E_GET_FLAGS(NULL, h, i));
44415 			}
44416 		}
44417 	}
44418 	if (st->internal) {
44419 		if (DUK_HOBJECT_IS_ARRAY(h)) {
44420 			DUK__COMMA(); duk_fb_sprintf(fb, "__array:true");
44421 		}
44422 		if (DUK_HOBJECT_HAS_EXTENSIBLE(h)) {
44423 			DUK__COMMA(); duk_fb_sprintf(fb, "__extensible:true");
44424 		}
44425 		if (DUK_HOBJECT_HAS_CONSTRUCTABLE(h)) {
44426 			DUK__COMMA(); duk_fb_sprintf(fb, "__constructable:true");
44427 		}
44428 		if (DUK_HOBJECT_HAS_BOUNDFUNC(h)) {
44429 			DUK__COMMA(); duk_fb_sprintf(fb, "__boundfunc:true");
44430 		}
44431 		if (DUK_HOBJECT_HAS_COMPFUNC(h)) {
44432 			DUK__COMMA(); duk_fb_sprintf(fb, "__compfunc:true");
44433 		}
44434 		if (DUK_HOBJECT_HAS_NATFUNC(h)) {
44435 			DUK__COMMA(); duk_fb_sprintf(fb, "__natfunc:true");
44436 		}
44437 		if (DUK_HOBJECT_HAS_BUFOBJ(h)) {
44438 			DUK__COMMA(); duk_fb_sprintf(fb, "__bufobj:true");
44439 		}
44440 		if (DUK_HOBJECT_IS_THREAD(h)) {
44441 			DUK__COMMA(); duk_fb_sprintf(fb, "__thread:true");
44442 		}
44443 		if (DUK_HOBJECT_HAS_ARRAY_PART(h)) {
44444 			DUK__COMMA(); duk_fb_sprintf(fb, "__array_part:true");
44445 		}
44446 		if (DUK_HOBJECT_HAS_STRICT(h)) {
44447 			DUK__COMMA(); duk_fb_sprintf(fb, "__strict:true");
44448 		}
44449 		if (DUK_HOBJECT_HAS_NOTAIL(h)) {
44450 			DUK__COMMA(); duk_fb_sprintf(fb, "__notail:true");
44451 		}
44452 		if (DUK_HOBJECT_HAS_NEWENV(h)) {
44453 			DUK__COMMA(); duk_fb_sprintf(fb, "__newenv:true");
44454 		}
44455 		if (DUK_HOBJECT_HAS_NAMEBINDING(h)) {
44456 			DUK__COMMA(); duk_fb_sprintf(fb, "__namebinding:true");
44457 		}
44458 		if (DUK_HOBJECT_HAS_CREATEARGS(h)) {
44459 			DUK__COMMA(); duk_fb_sprintf(fb, "__createargs:true");
44460 		}
44461 		if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)) {
44462 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_array:true");
44463 		}
44464 		if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h)) {
44465 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_stringobj:true");
44466 		}
44467 		if (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h)) {
44468 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_arguments:true");
44469 		}
44470 		if (DUK_HOBJECT_IS_BUFOBJ(h)) {
44471 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_bufobj:true");
44472 		}
44473 		if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)) {
44474 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_proxyobj:true");
44475 		}
44476 	}
44477 
44478 	if (st->internal && DUK_HOBJECT_IS_ARRAY(h)) {
44479 		duk_harray *a = (duk_harray *) h;
44480 		DUK__COMMA(); duk_fb_sprintf(fb, "__length:%ld", (long) a->length);
44481 		DUK__COMMA(); duk_fb_sprintf(fb, "__length_nonwritable:%ld", (long) a->length_nonwritable);
44482 	} else if (st->internal && DUK_HOBJECT_IS_COMPFUNC(h)) {
44483 		duk_hcompfunc *f = (duk_hcompfunc *) h;
44484 		DUK__COMMA(); duk_fb_put_cstring(fb, "__data:");
44485 		duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(NULL, f));
44486 		DUK__COMMA(); duk_fb_put_cstring(fb, "__lexenv:"); duk__print_hobject(st, DUK_HCOMPFUNC_GET_LEXENV(NULL, f));
44487 		DUK__COMMA(); duk_fb_put_cstring(fb, "__varenv:"); duk__print_hobject(st, DUK_HCOMPFUNC_GET_VARENV(NULL, f));
44488 		DUK__COMMA(); duk_fb_sprintf(fb, "__nregs:%ld", (long) f->nregs);
44489 		DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
44490 #if defined(DUK_USE_DEBUGGER_SUPPORT)
44491 		DUK__COMMA(); duk_fb_sprintf(fb, "__start_line:%ld", (long) f->start_line);
44492 		DUK__COMMA(); duk_fb_sprintf(fb, "__end_line:%ld", (long) f->end_line);
44493 #endif
44494 		DUK__COMMA(); duk_fb_put_cstring(fb, "__data:");
44495 		duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(NULL, f));
44496 	} else if (st->internal && DUK_HOBJECT_IS_NATFUNC(h)) {
44497 		duk_hnatfunc *f = (duk_hnatfunc *) h;
44498 		DUK__COMMA(); duk_fb_sprintf(fb, "__func:");
44499 		duk_fb_put_funcptr(fb, (duk_uint8_t *) &f->func, sizeof(f->func));
44500 		DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
44501 		DUK__COMMA(); duk_fb_sprintf(fb, "__magic:%ld", (long) f->magic);
44502 	} else if (st->internal && DUK_HOBJECT_IS_DECENV(h)) {
44503 		duk_hdecenv *e = (duk_hdecenv *) h;
44504 		DUK__COMMA(); duk_fb_sprintf(fb, "__thread:"); duk__print_hobject(st, (duk_hobject *) e->thread);
44505 		DUK__COMMA(); duk_fb_sprintf(fb, "__varmap:"); duk__print_hobject(st, (duk_hobject *) e->varmap);
44506 		DUK__COMMA(); duk_fb_sprintf(fb, "__regbase_byteoff:%ld", (long) e->regbase_byteoff);
44507 	} else if (st->internal && DUK_HOBJECT_IS_OBJENV(h)) {
44508 		duk_hobjenv *e = (duk_hobjenv *) h;
44509 		DUK__COMMA(); duk_fb_sprintf(fb, "__target:"); duk__print_hobject(st, (duk_hobject *) e->target);
44510 		DUK__COMMA(); duk_fb_sprintf(fb, "__has_this:%ld", (long) e->has_this);
44511 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
44512 	} else if (st->internal && DUK_HOBJECT_IS_BUFOBJ(h)) {
44513 		duk_hbufobj *b = (duk_hbufobj *) h;
44514 		DUK__COMMA(); duk_fb_sprintf(fb, "__buf:");
44515 		duk__print_hbuffer(st, (duk_hbuffer *) b->buf);
44516 		DUK__COMMA(); duk_fb_sprintf(fb, "__buf_prop:");
44517 		duk__print_hobject(st, (duk_hobject *) b->buf_prop);
44518 		DUK__COMMA(); duk_fb_sprintf(fb, "__offset:%ld", (long) b->offset);
44519 		DUK__COMMA(); duk_fb_sprintf(fb, "__length:%ld", (long) b->length);
44520 		DUK__COMMA(); duk_fb_sprintf(fb, "__shift:%ld", (long) b->shift);
44521 		DUK__COMMA(); duk_fb_sprintf(fb, "__elemtype:%ld", (long) b->elem_type);
44522 #endif
44523 	} else if (st->internal && DUK_HOBJECT_IS_PROXY(h)) {
44524 		duk_hproxy *p = (duk_hproxy *) h;
44525 		DUK__COMMA(); duk_fb_sprintf(fb, "__target:");
44526 		duk__print_hobject(st, p->target);
44527 		DUK__COMMA(); duk_fb_sprintf(fb, "__handler:");
44528 		duk__print_hobject(st, p->handler);
44529 	} else if (st->internal && DUK_HOBJECT_IS_THREAD(h)) {
44530 		duk_hthread *t = (duk_hthread *) h;
44531 		DUK__COMMA(); duk_fb_sprintf(fb, "__ptr_curr_pc:%p", (void *) t->ptr_curr_pc);
44532 		DUK__COMMA(); duk_fb_sprintf(fb, "__heap:%p", (void *) t->heap);
44533 		DUK__COMMA(); duk_fb_sprintf(fb, "__strict:%ld", (long) t->strict);
44534 		DUK__COMMA(); duk_fb_sprintf(fb, "__state:%ld", (long) t->state);
44535 		DUK__COMMA(); duk_fb_sprintf(fb, "__unused1:%ld", (long) t->unused1);
44536 		DUK__COMMA(); duk_fb_sprintf(fb, "__unused2:%ld", (long) t->unused2);
44537 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack:%p", (void *) t->valstack);
44538 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_end:%p/%ld", (void *) t->valstack_end, (long) (t->valstack_end - t->valstack));
44539 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_alloc_end:%p/%ld", (void *) t->valstack_alloc_end, (long) (t->valstack_alloc_end - t->valstack));
44540 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_bottom:%p/%ld", (void *) t->valstack_bottom, (long) (t->valstack_bottom - t->valstack));
44541 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_top:%p/%ld", (void *) t->valstack_top, (long) (t->valstack_top - t->valstack));
44542 		DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_curr:%p", (void *) t->callstack_curr);
44543 		DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_top:%ld", (long) t->callstack_top);
44544 		DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_preventcount:%ld", (long) t->callstack_preventcount);
44545 		DUK__COMMA(); duk_fb_sprintf(fb, "__resumer:"); duk__print_hobject(st, (duk_hobject *) t->resumer);
44546 		DUK__COMMA(); duk_fb_sprintf(fb, "__compile_ctx:%p", (void *) t->compile_ctx);
44547 #if defined(DUK_USE_INTERRUPT_COUNTER)
44548 		DUK__COMMA(); duk_fb_sprintf(fb, "__interrupt_counter:%ld", (long) t->interrupt_counter);
44549 		DUK__COMMA(); duk_fb_sprintf(fb, "__interrupt_init:%ld", (long) t->interrupt_init);
44550 #endif
44551 
44552 		/* XXX: print built-ins array? */
44553 
44554 	}
44555 #if defined(DUK_USE_REFERENCE_COUNTING)
44556 	if (st->internal) {
44557 		DUK__COMMA(); duk_fb_sprintf(fb, "__refcount:%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h));
44558 	}
44559 #endif
44560 	if (st->internal) {
44561 		DUK__COMMA(); duk_fb_sprintf(fb, "__class:%ld", (long) DUK_HOBJECT_GET_CLASS_NUMBER(h));
44562 	}
44563 
44564 	DUK__COMMA(); duk_fb_sprintf(fb, "__heapptr:%p", (void *) h);  /* own pointer */
44565 
44566 	/* prototype should be last, for readability */
44567 	if (DUK_HOBJECT_GET_PROTOTYPE(NULL, h)) {
44568 		if (st->follow_proto) {
44569 			DUK__COMMA(); duk_fb_put_cstring(fb, "__prototype:"); duk__print_hobject(st, DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
44570 		} else {
44571 			DUK__COMMA(); duk_fb_sprintf(fb, "__prototype:%p", (void *) DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
44572 		}
44573 	}
44574 
44575 	duk_fb_put_cstring(fb, brace2);
44576 
44577 #if defined(DUK_USE_HOBJECT_HASH_PART)
44578 	if (st->heavy && DUK_HOBJECT_GET_HSIZE(h) > 0) {
44579 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);
44580 		for (i = 0; i < DUK_HOBJECT_GET_HSIZE(h); i++) {
44581 			duk_uint_t h_idx = DUK_HOBJECT_H_GET_INDEX(NULL, h, i);
44582 			if (i > 0) {
44583 				duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA);
44584 			}
44585 			if (h_idx == DUK_HOBJECT_HASHIDX_UNUSED) {
44586 				duk_fb_sprintf(fb, "u");
44587 			} else if (h_idx == DUK_HOBJECT_HASHIDX_DELETED) {
44588 				duk_fb_sprintf(fb, "d");
44589 			} else {
44590 				duk_fb_sprintf(fb, "%ld", (long) h_idx);
44591 			}
44592 		}
44593 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);
44594 	}
44595 #endif
44596 
44597  finished:
44598 	st->depth--;
44599 	if (pushed_loopstack) {
44600 		st->loop_stack_index--;
44601 		st->loop_stack[st->loop_stack_index] = NULL;
44602 	}
44603 }
44604 
44605 DUK_LOCAL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h) {
44606 	duk_fixedbuffer *fb = st->fb;
44607 	duk_size_t i, n;
44608 	duk_uint8_t *p;
44609 
44610 	if (duk_fb_is_full(fb)) {
44611 		return;
44612 	}
44613 
44614 	/* terminal type: no depth check */
44615 
44616 	if (!h) {
44617 		duk_fb_put_cstring(fb, "NULL");
44618 		return;
44619 	}
44620 
44621 	if (DUK_HBUFFER_HAS_DYNAMIC(h)) {
44622 		if (DUK_HBUFFER_HAS_EXTERNAL(h)) {
44623 			duk_hbuffer_external *g = (duk_hbuffer_external *) h;
44624 			duk_fb_sprintf(fb, "buffer:external:%p:%ld",
44625 			               (void *) DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(NULL, g),
44626 			               (long) DUK_HBUFFER_EXTERNAL_GET_SIZE(g));
44627 		} else {
44628 			duk_hbuffer_dynamic *g = (duk_hbuffer_dynamic *) h;
44629 			duk_fb_sprintf(fb, "buffer:dynamic:%p:%ld",
44630 			               (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(NULL, g),
44631 			               (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(g));
44632 		}
44633 	} else {
44634 		duk_fb_sprintf(fb, "buffer:fixed:%ld", (long) DUK_HBUFFER_GET_SIZE(h));
44635 	}
44636 
44637 #if defined(DUK_USE_REFERENCE_COUNTING)
44638 	duk_fb_sprintf(fb, "/%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));
44639 #endif
44640 
44641 	if (st->hexdump) {
44642 		duk_fb_sprintf(fb, "=[");
44643 		n = DUK_HBUFFER_GET_SIZE(h);
44644 		p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(NULL, h);
44645 		for (i = 0; i < n; i++) {
44646 			duk_fb_sprintf(fb, "%02lx", (unsigned long) p[i]);
44647 		}
44648 		duk_fb_sprintf(fb, "]");
44649 	}
44650 }
44651 
44652 DUK_LOCAL void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {
44653 	duk_fixedbuffer *fb = st->fb;
44654 
44655 	if (duk_fb_is_full(fb)) {
44656 		return;
44657 	}
44658 
44659 	if (!h) {
44660 		duk_fb_put_cstring(fb, "NULL");
44661 		return;
44662 	}
44663 
44664 	switch (DUK_HEAPHDR_GET_TYPE(h)) {
44665 	case DUK_HTYPE_STRING:
44666 		duk__print_hstring(st, (duk_hstring *) h, 1);
44667 		break;
44668 	case DUK_HTYPE_OBJECT:
44669 		duk__print_hobject(st, (duk_hobject *) h);
44670 		break;
44671 	case DUK_HTYPE_BUFFER:
44672 		duk__print_hbuffer(st, (duk_hbuffer *) h);
44673 		break;
44674 	default:
44675 		duk_fb_sprintf(fb, "[unknown htype %ld]", (long) DUK_HEAPHDR_GET_TYPE(h));
44676 		break;
44677 	}
44678 }
44679 
44680 DUK_LOCAL void duk__print_tval(duk__dprint_state *st, duk_tval *tv) {
44681 	duk_fixedbuffer *fb = st->fb;
44682 
44683 	if (duk_fb_is_full(fb)) {
44684 		return;
44685 	}
44686 
44687 	/* depth check is done when printing an actual type */
44688 
44689 	if (st->heavy) {
44690 		duk_fb_sprintf(fb, "(%p)", (void *) tv);
44691 	}
44692 
44693 	if (!tv) {
44694 		duk_fb_put_cstring(fb, "NULL");
44695 		return;
44696 	}
44697 
44698 	if (st->binary) {
44699 		duk_size_t i;
44700 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
44701 		for (i = 0; i < (duk_size_t) sizeof(*tv); i++) {
44702 			duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)tv)[i]);
44703 		}
44704 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
44705 	}
44706 
44707 	if (st->heavy) {
44708 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);
44709 	}
44710 	switch (DUK_TVAL_GET_TAG(tv)) {
44711 	case DUK_TAG_UNDEFINED: {
44712 		duk_fb_put_cstring(fb, "undefined");
44713 		break;
44714 	}
44715 	case DUK_TAG_UNUSED: {
44716 		duk_fb_put_cstring(fb, "unused");
44717 		break;
44718 	}
44719 	case DUK_TAG_NULL: {
44720 		duk_fb_put_cstring(fb, "null");
44721 		break;
44722 	}
44723 	case DUK_TAG_BOOLEAN: {
44724 		duk_fb_put_cstring(fb, DUK_TVAL_GET_BOOLEAN(tv) ? "true" : "false");
44725 		break;
44726 	}
44727 	case DUK_TAG_STRING: {
44728 		/* Note: string is a terminal heap object, so no depth check here */
44729 		duk__print_hstring(st, DUK_TVAL_GET_STRING(tv), 1);
44730 		break;
44731 	}
44732 	case DUK_TAG_OBJECT: {
44733 		duk__print_hobject(st, DUK_TVAL_GET_OBJECT(tv));
44734 		break;
44735 	}
44736 	case DUK_TAG_BUFFER: {
44737 		duk__print_hbuffer(st, DUK_TVAL_GET_BUFFER(tv));
44738 		break;
44739 	}
44740 	case DUK_TAG_POINTER: {
44741 		duk_fb_sprintf(fb, "pointer:%p", (void *) DUK_TVAL_GET_POINTER(tv));
44742 		break;
44743 	}
44744 	case DUK_TAG_LIGHTFUNC: {
44745 		duk_c_function func;
44746 		duk_small_uint_t lf_flags;
44747 
44748 		DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
44749 		duk_fb_sprintf(fb, "lightfunc:");
44750 		duk_fb_put_funcptr(fb, (duk_uint8_t *) &func, sizeof(func));
44751 		duk_fb_sprintf(fb, ":%04lx", (long) lf_flags);
44752 		break;
44753 	}
44754 #if defined(DUK_USE_FASTINT)
44755 	case DUK_TAG_FASTINT:
44756 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
44757 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
44758 		duk_fb_sprintf(fb, "%.18g_F", (double) DUK_TVAL_GET_NUMBER(tv));
44759 		break;
44760 #endif
44761 	default: {
44762 		/* IEEE double is approximately 16 decimal digits; print a couple extra */
44763 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
44764 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
44765 		duk_fb_sprintf(fb, "%.18g", (double) DUK_TVAL_GET_NUMBER(tv));
44766 		break;
44767 	}
44768 	}
44769 	if (st->heavy) {
44770 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);
44771 	}
44772 }
44773 
44774 DUK_LOCAL void duk__print_instr(duk__dprint_state *st, duk_instr_t ins) {
44775 	duk_fixedbuffer *fb = st->fb;
44776 	duk_small_int_t op;
44777 	const char *op_name;
44778 
44779 	op = (duk_small_int_t) DUK_DEC_OP(ins);
44780 	op_name = duk__bc_optab[op];
44781 
44782 	/* XXX: option to fix opcode length so it lines up nicely */
44783 
44784 	if (op == DUK_OP_JUMP) {
44785 		duk_int_t diff1 = (duk_int_t) (DUK_DEC_ABC(ins) - DUK_BC_JUMP_BIAS);  /* from next pc */
44786 		duk_int_t diff2 = diff1 + 1;                                          /* from curr pc */
44787 
44788 		duk_fb_sprintf(fb, "%s %ld (to pc%c%ld)",
44789 		               (const char *) op_name, (long) diff1,
44790 		               (int) (diff2 >= 0 ? '+' : '-'),  /* char format: use int */
44791 		               (long) (diff2 >= 0 ? diff2 : -diff2));
44792 	} else {
44793 		duk_fb_sprintf(fb, "%s %ld, %ld, %ld",
44794 		               (const char *) op_name, (long) DUK_DEC_A(ins),
44795 		               (long) DUK_DEC_B(ins), (long) DUK_DEC_C(ins));
44796 	}
44797 }
44798 
44799 DUK_LOCAL void duk__print_opcode(duk__dprint_state *st, duk_small_int_t opcode) {
44800 	duk_fixedbuffer *fb = st->fb;
44801 
44802 	if (opcode < DUK_BC_OP_MIN || opcode > DUK_BC_OP_MAX) {
44803 		duk_fb_sprintf(fb, "?(%ld)", (long) opcode);
44804 	} else {
44805 		duk_fb_sprintf(fb, "%s", (const char *) duk__bc_optab[opcode]);
44806 	}
44807 }
44808 
44809 DUK_LOCAL void duk__print_catcher(duk__dprint_state *st, duk_catcher *cat) {
44810 	duk_fixedbuffer *fb = st->fb;
44811 
44812 	if (duk_fb_is_full(fb)) {
44813 		return;
44814 	}
44815 
44816 	if (!cat) {
44817 		duk_fb_put_cstring(fb, "NULL");
44818 		return;
44819 	}
44820 
44821 	duk_fb_sprintf(fb, "[catcher ptr=%p parent=%p varname=%p pc_base=%p, idx_base=%ld, flags=0x%08lx]",
44822 	               (void *) cat,
44823 	               (void *) cat->parent, (void *) cat->h_varname, (void *) cat->pc_base,
44824 		       (long) cat->idx_base, (unsigned long) cat->flags);
44825 }
44826 
44827 
44828 DUK_LOCAL void duk__print_activation(duk__dprint_state *st, duk_activation *act) {
44829 	duk_fixedbuffer *fb = st->fb;
44830 
44831 	if (duk_fb_is_full(fb)) {
44832 		return;
44833 	}
44834 
44835 	if (!act) {
44836 		duk_fb_put_cstring(fb, "NULL");
44837 		return;
44838 	}
44839 
44840 	/* prev_caller: conditional, omitted on purpose, it's rarely used. */
44841 	/* prev_line: conditional, omitted on purpose (but would be nice). */
44842 	duk_fb_sprintf(fb, "[activation ptr=%p tv_func=<omit> func=%p parent=%p var_env=%p lex_env=%p cat=%p curr_pc=%p bottom_byteoff=%ld retval_byteoff=%ld reserve_byteoff=%ld flags=%ld]",
44843 	               (void *) act,
44844 	               (void *) act->func, (void *) act->parent, (void *) act->var_env,
44845 		       (void *) act->lex_env, (void *) act->cat, (void *) act->curr_pc,
44846 		       (long) act->bottom_byteoff, (long) act->retval_byteoff, (long) act->reserve_byteoff,
44847 		       (long) act->flags);
44848 }
44849 
44850 DUK_INTERNAL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap) {
44851 	duk_fixedbuffer fb;
44852 	const char *p = format;
44853 	const char *p_end = p + DUK_STRLEN(format);
44854 	duk_int_t retval;
44855 
44856 	duk_memzero(&fb, sizeof(fb));
44857 	fb.buffer = (duk_uint8_t *) str;
44858 	fb.length = size;
44859 	fb.offset = 0;
44860 	fb.truncated = 0;
44861 
44862 	while (p < p_end) {
44863 		char ch = *p++;
44864 		const char *p_begfmt = NULL;
44865 		duk_bool_t got_exclamation = 0;
44866 		duk_bool_t got_long = 0;  /* %lf, %ld etc */
44867 		duk__dprint_state st;
44868 
44869 		if (ch != DUK_ASC_PERCENT) {
44870 			duk_fb_put_byte(&fb, (duk_uint8_t) ch);
44871 			continue;
44872 		}
44873 
44874 		/*
44875 		 *  Format tag parsing.  Since we don't understand all the
44876 		 *  possible format tags allowed, we just scan for a terminating
44877 		 *  specifier and keep track of relevant modifiers that we do
44878 		 *  understand.  See man 3 printf.
44879 		 */
44880 
44881 		duk_memzero(&st, sizeof(st));
44882 		st.fb = &fb;
44883 		st.depth = 0;
44884 		st.depth_limit = 1;
44885 		st.loop_stack_index = 0;
44886 		st.loop_stack_limit = DUK__LOOP_STACK_DEPTH;
44887 
44888 		p_begfmt = p - 1;
44889 		while (p < p_end) {
44890 			ch = *p++;
44891 
44892 			if (ch == DUK_ASC_STAR) {
44893 				/* unsupported: would consume multiple args */
44894 				goto format_error;
44895 			} else if (ch == DUK_ASC_PERCENT) {
44896 				duk_fb_put_byte(&fb, (duk_uint8_t) DUK_ASC_PERCENT);
44897 				break;
44898 			} else if (ch == DUK_ASC_EXCLAMATION) {
44899 				got_exclamation = 1;
44900 			} else if (!got_exclamation && ch == DUK_ASC_LC_L) {
44901 				got_long = 1;
44902 			} else if (got_exclamation && ch == DUK_ASC_LC_D) {
44903 				st.depth_limit = DUK__DEEP_DEPTH_LIMIT;
44904 			} else if (got_exclamation && ch == DUK_ASC_LC_P) {
44905 				st.follow_proto = 1;
44906 			} else if (got_exclamation && ch == DUK_ASC_LC_I) {
44907 				st.internal = 1;
44908 			} else if (got_exclamation && ch == DUK_ASC_LC_X) {
44909 				st.hexdump = 1;
44910 			} else if (got_exclamation && ch == DUK_ASC_LC_H) {
44911 				st.heavy = 1;
44912 			} else if (got_exclamation && ch == DUK_ASC_ATSIGN) {
44913 				st.pointer = 1;
44914 			} else if (got_exclamation && ch == DUK_ASC_HASH) {
44915 				st.binary = 1;
44916 			} else if (got_exclamation && ch == DUK_ASC_UC_T) {
44917 				duk_tval *t = va_arg(ap, duk_tval *);
44918 				if (st.pointer && !st.heavy) {
44919 					duk_fb_sprintf(&fb, "(%p)", (void *) t);
44920 				}
44921 				duk__print_tval(&st, t);
44922 				break;
44923 			} else if (got_exclamation && ch == DUK_ASC_UC_O) {
44924 				duk_heaphdr *t = va_arg(ap, duk_heaphdr *);
44925 				if (st.pointer && !st.heavy) {
44926 					duk_fb_sprintf(&fb, "(%p)", (void *) t);
44927 				}
44928 				duk__print_heaphdr(&st, t);
44929 				break;
44930 			} else if (got_exclamation && ch == DUK_ASC_UC_I) {
44931 				duk_instr_t t = va_arg(ap, duk_instr_t);
44932 				duk__print_instr(&st, t);
44933 				break;
44934 			} else if (got_exclamation && ch == DUK_ASC_UC_X) {
44935 				long t = va_arg(ap, long);
44936 				duk__print_opcode(&st, (duk_small_int_t) t);
44937 				break;
44938 			} else if (got_exclamation && ch == DUK_ASC_UC_C) {
44939 				duk_catcher *t = va_arg(ap, duk_catcher *);
44940 				duk__print_catcher(&st, t);
44941 				break;
44942 			} else if (got_exclamation && ch == DUK_ASC_UC_A) {
44943 				duk_activation *t = va_arg(ap, duk_activation *);
44944 				duk__print_activation(&st, t);
44945 				break;
44946 			} else if (!got_exclamation && strchr(DUK__ALLOWED_STANDARD_SPECIFIERS, (int) ch)) {
44947 				char fmtbuf[DUK__MAX_FORMAT_TAG_LENGTH];
44948 				duk_size_t fmtlen;
44949 
44950 				DUK_ASSERT(p >= p_begfmt);
44951 				fmtlen = (duk_size_t) (p - p_begfmt);
44952 				if (fmtlen >= sizeof(fmtbuf)) {
44953 					/* format is too large, abort */
44954 					goto format_error;
44955 				}
44956 				duk_memzero(fmtbuf, sizeof(fmtbuf));
44957 				duk_memcpy(fmtbuf, p_begfmt, fmtlen);
44958 
44959 				/* assume exactly 1 arg, which is why '*' is forbidden; arg size still
44960 				 * depends on type though.
44961 				 */
44962 
44963 				if (ch == DUK_ASC_LC_F || ch == DUK_ASC_LC_G || ch == DUK_ASC_LC_E) {
44964 					/* %f and %lf both consume a 'long' */
44965 					double arg = va_arg(ap, double);
44966 					duk_fb_sprintf(&fb, fmtbuf, arg);
44967 				} else if (ch == DUK_ASC_LC_D && got_long) {
44968 					/* %ld */
44969 					long arg = va_arg(ap, long);
44970 					duk_fb_sprintf(&fb, fmtbuf, arg);
44971 				} else if (ch == DUK_ASC_LC_D) {
44972 					/* %d; only 16 bits are guaranteed */
44973 					int arg = va_arg(ap, int);
44974 					duk_fb_sprintf(&fb, fmtbuf, arg);
44975 				} else if (ch == DUK_ASC_LC_U && got_long) {
44976 					/* %lu */
44977 					unsigned long arg = va_arg(ap, unsigned long);
44978 					duk_fb_sprintf(&fb, fmtbuf, arg);
44979 				} else if (ch == DUK_ASC_LC_U) {
44980 					/* %u; only 16 bits are guaranteed */
44981 					unsigned int arg = va_arg(ap, unsigned int);
44982 					duk_fb_sprintf(&fb, fmtbuf, arg);
44983 				} else if (ch == DUK_ASC_LC_X && got_long) {
44984 					/* %lx */
44985 					unsigned long arg = va_arg(ap, unsigned long);
44986 					duk_fb_sprintf(&fb, fmtbuf, arg);
44987 				} else if (ch == DUK_ASC_LC_X) {
44988 					/* %x; only 16 bits are guaranteed */
44989 					unsigned int arg = va_arg(ap, unsigned int);
44990 					duk_fb_sprintf(&fb, fmtbuf, arg);
44991 				} else if (ch == DUK_ASC_LC_S) {
44992 					/* %s */
44993 					const char *arg = va_arg(ap, const char *);
44994 					if (arg == NULL) {
44995 						/* '%s' and NULL is not portable, so special case
44996 						 * it for debug printing.
44997 						 */
44998 						duk_fb_sprintf(&fb, "NULL");
44999 					} else {
45000 						duk_fb_sprintf(&fb, fmtbuf, arg);
45001 					}
45002 				} else if (ch == DUK_ASC_LC_P) {
45003 					/* %p */
45004 					void *arg = va_arg(ap, void *);
45005 					if (arg == NULL) {
45006 						/* '%p' and NULL is portable, but special case it
45007 						 * anyway to get a standard NULL marker in logs.
45008 						 */
45009 						duk_fb_sprintf(&fb, "NULL");
45010 					} else {
45011 						duk_fb_sprintf(&fb, fmtbuf, arg);
45012 					}
45013 				} else if (ch == DUK_ASC_LC_C) {
45014 					/* '%c', passed concretely as int */
45015 					int arg = va_arg(ap, int);
45016 					duk_fb_sprintf(&fb, fmtbuf, arg);
45017 				} else {
45018 					/* Should not happen. */
45019 					duk_fb_sprintf(&fb, "INVALID-FORMAT(%s)", (const char *) fmtbuf);
45020 				}
45021 				break;
45022 			} else {
45023 				/* ignore */
45024 			}
45025 		}
45026 	}
45027 	goto done;
45028 
45029  format_error:
45030 	duk_fb_put_cstring(&fb, "FMTERR");
45031 	/* fall through */
45032 
45033  done:
45034 	retval = (duk_int_t) fb.offset;
45035 	duk_fb_put_byte(&fb, (duk_uint8_t) 0);
45036 
45037 	/* return total chars written excluding terminator */
45038 	return retval;
45039 }
45040 
45041 #if 0  /*unused*/
45042 DUK_INTERNAL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...) {
45043 	duk_int_t retval;
45044 	va_list ap;
45045 	va_start(ap, format);
45046 	retval = duk_debug_vsnprintf(str, size, format, ap);
45047 	va_end(ap);
45048 	return retval;
45049 }
45050 #endif
45051 
45052 /* Formatting function pointers is tricky: there is no standard pointer for
45053  * function pointers and the size of a function pointer may depend on the
45054  * specific pointer type.  This helper formats a function pointer based on
45055  * its memory layout to get something useful on most platforms.
45056  */
45057 DUK_INTERNAL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size) {
45058 	duk_size_t i;
45059 	duk_uint8_t *p = (duk_uint8_t *) buf;
45060 	duk_uint8_t *p_end = (duk_uint8_t *) (buf + buf_size - 1);
45061 
45062 	DUK_ASSERT(buf != NULL);
45063 	duk_memzero(buf, buf_size);
45064 
45065 	for (i = 0; i < fptr_size; i++) {
45066 		duk_int_t left = (duk_int_t) (p_end - p);
45067 		duk_uint8_t ch;
45068 		if (left <= 0) {
45069 			break;
45070 		}
45071 
45072 		/* Quite approximate but should be useful for little and big endian. */
45073 #if defined(DUK_USE_INTEGER_BE)
45074 		ch = fptr[i];
45075 #else
45076 		ch = fptr[fptr_size - 1 - i];
45077 #endif
45078 		p += DUK_SNPRINTF((char *) p, (duk_size_t) left, "%02lx", (unsigned long) ch);
45079 	}
45080 }
45081 
45082 #endif  /* DUK_USE_DEBUG */
45083 
45084 /* automatic undefs */
45085 #undef DUK__ALLOWED_STANDARD_SPECIFIERS
45086 #undef DUK__COMMA
45087 #undef DUK__DEEP_DEPTH_LIMIT
45088 #undef DUK__LOOP_STACK_DEPTH
45089 #undef DUK__MAX_FORMAT_TAG_LENGTH
45090 /*
45091  *  Duktape debugger
45092  */
45093 
45094 /* #include duk_internal.h -> already included */
45095 
45096 #if defined(DUK_USE_DEBUGGER_SUPPORT)
45097 
45098 /*
45099  *  Assert helpers
45100  */
45101 
45102 #if defined(DUK_USE_ASSERTIONS)
45103 #define DUK__DBG_TPORT_ENTER() do { \
45104 		DUK_ASSERT(heap->dbg_calling_transport == 0); \
45105 		heap->dbg_calling_transport = 1; \
45106 	} while (0)
45107 #define DUK__DBG_TPORT_EXIT() do { \
45108 		DUK_ASSERT(heap->dbg_calling_transport == 1); \
45109 		heap->dbg_calling_transport = 0; \
45110 	} while (0)
45111 #else
45112 #define DUK__DBG_TPORT_ENTER() do {} while (0)
45113 #define DUK__DBG_TPORT_EXIT() do {} while (0)
45114 #endif
45115 
45116 /*
45117  *  Helper structs
45118  */
45119 
45120 typedef union {
45121 	void *p;
45122 	duk_uint_t b[1];
45123 	/* Use b[] to access the size of the union, which is strictly not
45124 	 * correct.  Can't use fixed size unless there's feature detection
45125 	 * for pointer byte size.
45126 	 */
45127 } duk__ptr_union;
45128 
45129 /*
45130  *  Detach handling
45131  */
45132 
45133 #define DUK__SET_CONN_BROKEN(thr,reason) do { \
45134 		/* For now shared handler is fine. */ \
45135 		duk__debug_do_detach1((thr)->heap, (reason)); \
45136 	} while (0)
45137 
45138 DUK_LOCAL void duk__debug_do_detach1(duk_heap *heap, duk_int_t reason) {
45139 	/* Can be called multiple times with no harm.  Mark the transport
45140 	 * bad (dbg_read_cb == NULL) and clear state except for the detached
45141 	 * callback and the udata field.  The detached callback is delayed
45142 	 * to the message loop so that it can be called between messages;
45143 	 * this avoids corner cases related to immediate debugger reattach
45144 	 * inside the detached callback.
45145 	 */
45146 
45147 	if (heap->dbg_detaching) {
45148 		DUK_D(DUK_DPRINT("debugger already detaching, ignore detach1"));
45149 		return;
45150 	}
45151 
45152 	DUK_D(DUK_DPRINT("debugger transport detaching, marking transport broken"));
45153 
45154 	heap->dbg_detaching = 1;  /* prevent multiple in-progress detaches */
45155 
45156 	if (heap->dbg_write_cb != NULL) {
45157 		duk_hthread *thr;
45158 
45159 		thr = heap->heap_thread;
45160 		DUK_ASSERT(thr != NULL);
45161 
45162 		duk_debug_write_notify(thr, DUK_DBG_CMD_DETACHING);
45163 		duk_debug_write_int(thr, reason);
45164 		duk_debug_write_eom(thr);
45165 	}
45166 
45167 	heap->dbg_read_cb = NULL;
45168 	heap->dbg_write_cb = NULL;
45169 	heap->dbg_peek_cb = NULL;
45170 	heap->dbg_read_flush_cb = NULL;
45171 	heap->dbg_write_flush_cb = NULL;
45172 	heap->dbg_request_cb = NULL;
45173 	/* heap->dbg_detached_cb: keep */
45174 	/* heap->dbg_udata: keep */
45175 	/* heap->dbg_processing: keep on purpose to avoid debugger re-entry in detaching state */
45176 	heap->dbg_state_dirty = 0;
45177 	heap->dbg_force_restart = 0;
45178 	heap->dbg_pause_flags = 0;
45179 	heap->dbg_pause_act = NULL;
45180 	heap->dbg_pause_startline = 0;
45181 	heap->dbg_have_next_byte = 0;
45182 	duk_debug_clear_paused(heap);  /* XXX: some overlap with field inits above */
45183 	heap->dbg_state_dirty = 0;     /* XXX: clear_paused sets dirty; rework? */
45184 
45185 	/* Ensure there are no stale active breakpoint pointers.
45186 	 * Breakpoint list is currently kept - we could empty it
45187 	 * here but we'd need to handle refcounts correctly, and
45188 	 * we'd need a 'thr' reference for that.
45189 	 *
45190 	 * XXX: clear breakpoint on either attach or detach?
45191 	 */
45192 	heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
45193 }
45194 
45195 DUK_LOCAL void duk__debug_do_detach2(duk_heap *heap) {
45196 	duk_debug_detached_function detached_cb;
45197 	void *detached_udata;
45198 	duk_hthread *thr;
45199 
45200 	thr = heap->heap_thread;
45201 	if (thr == NULL) {
45202 		DUK_ASSERT(heap->dbg_detached_cb == NULL);
45203 		return;
45204 	}
45205 
45206 	/* Safe to call multiple times. */
45207 
45208 	detached_cb = heap->dbg_detached_cb;
45209 	detached_udata = heap->dbg_udata;
45210 	heap->dbg_detached_cb = NULL;
45211 	heap->dbg_udata = NULL;
45212 
45213 	if (detached_cb) {
45214 		/* Careful here: state must be wiped before the call
45215 		 * so that we can cleanly handle a re-attach from
45216 		 * inside the callback.
45217 		 */
45218 		DUK_D(DUK_DPRINT("detached during message loop, delayed call to detached_cb"));
45219 		detached_cb(thr, detached_udata);
45220 	}
45221 
45222 	heap->dbg_detaching = 0;
45223 }
45224 
45225 DUK_INTERNAL void duk_debug_do_detach(duk_heap *heap) {
45226 	duk__debug_do_detach1(heap, 0);
45227 	duk__debug_do_detach2(heap);
45228 }
45229 
45230 /* Called on a read/write error: NULL all callbacks except the detached
45231  * callback so that we never accidentally call them after a read/write
45232  * error has been indicated.  This is especially important for the transport
45233  * I/O callbacks to fulfill guaranteed callback semantics.
45234  */
45235 DUK_LOCAL void duk__debug_null_most_callbacks(duk_hthread *thr) {
45236 	duk_heap *heap;
45237 
45238 	DUK_ASSERT(thr != NULL);
45239 
45240 	heap = thr->heap;
45241 	DUK_D(DUK_DPRINT("transport read/write error, NULL all callbacks expected detached"));
45242 	heap->dbg_read_cb = NULL;
45243 	heap->dbg_write_cb = NULL;  /* this is especially critical to avoid another write call in detach1() */
45244 	heap->dbg_peek_cb = NULL;
45245 	heap->dbg_read_flush_cb = NULL;
45246 	heap->dbg_write_flush_cb = NULL;
45247 	heap->dbg_request_cb = NULL;
45248 	/* keep heap->dbg_detached_cb */
45249 }
45250 
45251 /*
45252  *  Pause handling
45253  */
45254 
45255 DUK_LOCAL void duk__debug_set_pause_state(duk_hthread *thr, duk_heap *heap, duk_small_uint_t pause_flags) {
45256 	duk_uint_fast32_t line;
45257 
45258 	line = duk_debug_curr_line(thr);
45259 	if (line == 0) {
45260 		/* No line info for current function. */
45261 		duk_small_uint_t updated_flags;
45262 
45263 		updated_flags = pause_flags & ~(DUK_PAUSE_FLAG_LINE_CHANGE);
45264 		DUK_D(DUK_DPRINT("no line info for current activation, disable line-based pause flags: 0x%08lx -> 0x%08lx",
45265 		                 (long) pause_flags, (long) updated_flags));
45266 		pause_flags = updated_flags;
45267 	}
45268 
45269 	heap->dbg_pause_flags = pause_flags;
45270 	heap->dbg_pause_act = thr->callstack_curr;
45271 	heap->dbg_pause_startline = (duk_uint32_t) line;
45272 	heap->dbg_state_dirty = 1;
45273 
45274 	DUK_D(DUK_DPRINT("set state for automatic pause triggers, flags=0x%08lx, act=%p, startline=%ld",
45275 	                 (long) heap->dbg_pause_flags, (void *) heap->dbg_pause_act,
45276 	                 (long) heap->dbg_pause_startline));
45277 }
45278 
45279 /*
45280  *  Debug connection peek and flush primitives
45281  */
45282 
45283 DUK_INTERNAL duk_bool_t duk_debug_read_peek(duk_hthread *thr) {
45284 	duk_heap *heap;
45285 	duk_bool_t ret;
45286 
45287 	DUK_ASSERT(thr != NULL);
45288 	heap = thr->heap;
45289 	DUK_ASSERT(heap != NULL);
45290 
45291 	if (heap->dbg_read_cb == NULL) {
45292 		DUK_D(DUK_DPRINT("attempt to peek in detached state, return zero (= no data)"));
45293 		return 0;
45294 	}
45295 	if (heap->dbg_peek_cb == NULL) {
45296 		DUK_DD(DUK_DDPRINT("no peek callback, return zero (= no data)"));
45297 		return 0;
45298 	}
45299 
45300 	DUK__DBG_TPORT_ENTER();
45301 	ret = (duk_bool_t) (heap->dbg_peek_cb(heap->dbg_udata) > 0);
45302 	DUK__DBG_TPORT_EXIT();
45303 	return ret;
45304 }
45305 
45306 DUK_INTERNAL void duk_debug_read_flush(duk_hthread *thr) {
45307 	duk_heap *heap;
45308 
45309 	DUK_ASSERT(thr != NULL);
45310 	heap = thr->heap;
45311 	DUK_ASSERT(heap != NULL);
45312 
45313 	if (heap->dbg_read_cb == NULL) {
45314 		DUK_D(DUK_DPRINT("attempt to read flush in detached state, ignore"));
45315 		return;
45316 	}
45317 	if (heap->dbg_read_flush_cb == NULL) {
45318 		DUK_DD(DUK_DDPRINT("no read flush callback, ignore"));
45319 		return;
45320 	}
45321 
45322 	DUK__DBG_TPORT_ENTER();
45323 	heap->dbg_read_flush_cb(heap->dbg_udata);
45324 	DUK__DBG_TPORT_EXIT();
45325 }
45326 
45327 DUK_INTERNAL void duk_debug_write_flush(duk_hthread *thr) {
45328 	duk_heap *heap;
45329 
45330 	DUK_ASSERT(thr != NULL);
45331 	heap = thr->heap;
45332 	DUK_ASSERT(heap != NULL);
45333 
45334 	if (heap->dbg_read_cb == NULL) {
45335 		DUK_D(DUK_DPRINT("attempt to write flush in detached state, ignore"));
45336 		return;
45337 	}
45338 	if (heap->dbg_write_flush_cb == NULL) {
45339 		DUK_DD(DUK_DDPRINT("no write flush callback, ignore"));
45340 		return;
45341 	}
45342 
45343 	DUK__DBG_TPORT_ENTER();
45344 	heap->dbg_write_flush_cb(heap->dbg_udata);
45345 	DUK__DBG_TPORT_EXIT();
45346 }
45347 
45348 /*
45349  *  Debug connection skip primitives
45350  */
45351 
45352 /* Skip fully. */
45353 DUK_INTERNAL void duk_debug_skip_bytes(duk_hthread *thr, duk_size_t length) {
45354 	duk_uint8_t dummy[64];
45355 	duk_size_t now;
45356 
45357 	DUK_ASSERT(thr != NULL);
45358 
45359 	while (length > 0) {
45360 		now = (length > sizeof(dummy) ? sizeof(dummy) : length);
45361 		duk_debug_read_bytes(thr, dummy, now);
45362 		length -= now;
45363 	}
45364 }
45365 
45366 DUK_INTERNAL void duk_debug_skip_byte(duk_hthread *thr) {
45367 	DUK_ASSERT(thr != NULL);
45368 
45369 	(void) duk_debug_read_byte(thr);
45370 }
45371 
45372 /*
45373  *  Debug connection read primitives
45374  */
45375 
45376 /* Peek ahead in the stream one byte. */
45377 DUK_INTERNAL uint8_t duk_debug_peek_byte(duk_hthread *thr) {
45378 	/* It is important not to call this if the last byte read was an EOM.
45379 	 * Reading ahead in this scenario would cause unnecessary blocking if
45380 	 * another message is not available.
45381 	 */
45382 
45383 	duk_uint8_t x;
45384 
45385 	x = duk_debug_read_byte(thr);
45386 	thr->heap->dbg_have_next_byte = 1;
45387 	thr->heap->dbg_next_byte = x;
45388 	return x;
45389 }
45390 
45391 /* Read fully. */
45392 DUK_INTERNAL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_size_t length) {
45393 	duk_heap *heap;
45394 	duk_uint8_t *p;
45395 	duk_size_t left;
45396 	duk_size_t got;
45397 
45398 	DUK_ASSERT(thr != NULL);
45399 	heap = thr->heap;
45400 	DUK_ASSERT(heap != NULL);
45401 	DUK_ASSERT(data != NULL);
45402 
45403 	if (heap->dbg_read_cb == NULL) {
45404 		DUK_D(DUK_DPRINT("attempt to read %ld bytes in detached state, return zero data", (long) length));
45405 		goto fail;
45406 	}
45407 
45408 	/* NOTE: length may be zero */
45409 	p = data;
45410 	if (length >= 1 && heap->dbg_have_next_byte) {
45411 		heap->dbg_have_next_byte = 0;
45412 		*p++ = heap->dbg_next_byte;
45413 	}
45414 	for (;;) {
45415 		left = (duk_size_t) ((data + length) - p);
45416 		if (left == 0) {
45417 			break;
45418 		}
45419 		DUK_ASSERT(heap->dbg_read_cb != NULL);
45420 		DUK_ASSERT(left >= 1);
45421 #if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)
45422 		left = 1;
45423 #endif
45424 		DUK__DBG_TPORT_ENTER();
45425 		got = heap->dbg_read_cb(heap->dbg_udata, (char *) p, left);
45426 		DUK__DBG_TPORT_EXIT();
45427 
45428 		if (got == 0 || got > left) {
45429 			DUK_D(DUK_DPRINT("connection error during read, return zero data"));
45430 			duk__debug_null_most_callbacks(thr);  /* avoid calling write callback in detach1() */
45431 			DUK__SET_CONN_BROKEN(thr, 1);
45432 			goto fail;
45433 		}
45434 		p += got;
45435 	}
45436 	return;
45437 
45438  fail:
45439 	duk_memzero((void *) data, (size_t) length);
45440 }
45441 
45442 DUK_INTERNAL duk_uint8_t duk_debug_read_byte(duk_hthread *thr) {
45443 	duk_uint8_t x;
45444 
45445 	x = 0;  /* just in case callback is broken and won't write 'x' */
45446 	duk_debug_read_bytes(thr, &x, 1);
45447 	return x;
45448 }
45449 
45450 DUK_LOCAL duk_uint32_t duk__debug_read_uint32_raw(duk_hthread *thr) {
45451 	duk_uint8_t buf[4];
45452 
45453 	DUK_ASSERT(thr != NULL);
45454 
45455 	duk_debug_read_bytes(thr, buf, 4);
45456 	return ((duk_uint32_t) buf[0] << 24) |
45457 	       ((duk_uint32_t) buf[1] << 16) |
45458 	       ((duk_uint32_t) buf[2] << 8) |
45459 	       (duk_uint32_t) buf[3];
45460 }
45461 
45462 DUK_LOCAL duk_int32_t duk__debug_read_int32_raw(duk_hthread *thr) {
45463 	return (duk_int32_t) duk__debug_read_uint32_raw(thr);
45464 }
45465 
45466 DUK_LOCAL duk_uint16_t duk__debug_read_uint16_raw(duk_hthread *thr) {
45467 	duk_uint8_t buf[2];
45468 
45469 	DUK_ASSERT(thr != NULL);
45470 
45471 	duk_debug_read_bytes(thr, buf, 2);
45472 	return ((duk_uint16_t) buf[0] << 8) |
45473 	       (duk_uint16_t) buf[1];
45474 }
45475 
45476 DUK_INTERNAL duk_int32_t duk_debug_read_int(duk_hthread *thr) {
45477 	duk_small_uint_t x;
45478 	duk_small_uint_t t;
45479 
45480 	DUK_ASSERT(thr != NULL);
45481 
45482 	x = duk_debug_read_byte(thr);
45483 	if (x >= 0xc0) {
45484 		t = duk_debug_read_byte(thr);
45485 		return (duk_int32_t) (((x - 0xc0) << 8) + t);
45486 	} else if (x >= 0x80) {
45487 		return (duk_int32_t) (x - 0x80);
45488 	} else if (x == DUK_DBG_IB_INT4) {
45489 		return (duk_int32_t) duk__debug_read_uint32_raw(thr);
45490 	}
45491 
45492 	DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
45493 	DUK__SET_CONN_BROKEN(thr, 1);
45494 	return 0;
45495 }
45496 
45497 DUK_LOCAL duk_hstring *duk__debug_read_hstring_raw(duk_hthread *thr, duk_uint32_t len) {
45498 	duk_uint8_t buf[31];
45499 	duk_uint8_t *p;
45500 
45501 	if (len <= sizeof(buf)) {
45502 		duk_debug_read_bytes(thr, buf, (duk_size_t) len);
45503 		duk_push_lstring(thr, (const char *) buf, (duk_size_t) len);
45504 	} else {
45505 		p = (duk_uint8_t *) duk_push_fixed_buffer(thr, (duk_size_t) len);  /* zero for paranoia */
45506 		DUK_ASSERT(p != NULL);
45507 		duk_debug_read_bytes(thr, p, (duk_size_t) len);
45508 		(void) duk_buffer_to_string(thr, -1);  /* Safety relies on debug client, which is OK. */
45509 	}
45510 
45511 	return duk_require_hstring(thr, -1);
45512 }
45513 
45514 DUK_INTERNAL duk_hstring *duk_debug_read_hstring(duk_hthread *thr) {
45515 	duk_small_uint_t x;
45516 	duk_uint32_t len;
45517 
45518 	DUK_ASSERT(thr != NULL);
45519 
45520 	x = duk_debug_read_byte(thr);
45521 	if (x >= 0x60 && x <= 0x7f) {
45522 		/* For short strings, use a fixed temp buffer. */
45523 		len = (duk_uint32_t) (x - 0x60);
45524 	} else if (x == DUK_DBG_IB_STR2) {
45525 		len = (duk_uint32_t) duk__debug_read_uint16_raw(thr);
45526 	} else if (x == DUK_DBG_IB_STR4) {
45527 		len = (duk_uint32_t) duk__debug_read_uint32_raw(thr);
45528 	} else {
45529 		goto fail;
45530 	}
45531 
45532 	return duk__debug_read_hstring_raw(thr, len);
45533 
45534  fail:
45535 	DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
45536 	DUK__SET_CONN_BROKEN(thr, 1);
45537 	duk_push_hstring_empty(thr);  /* always push some string */
45538 	return duk_require_hstring(thr, -1);
45539 }
45540 
45541 DUK_LOCAL duk_hbuffer *duk__debug_read_hbuffer_raw(duk_hthread *thr, duk_uint32_t len) {
45542 	duk_uint8_t *p;
45543 
45544 	p = (duk_uint8_t *) duk_push_fixed_buffer(thr, (duk_size_t) len);  /* zero for paranoia */
45545 	DUK_ASSERT(p != NULL);
45546 	duk_debug_read_bytes(thr, p, (duk_size_t) len);
45547 
45548 	return duk_require_hbuffer(thr, -1);
45549 }
45550 
45551 DUK_LOCAL void *duk__debug_read_pointer_raw(duk_hthread *thr) {
45552 	duk_small_uint_t x;
45553 	duk__ptr_union pu;
45554 
45555 	DUK_ASSERT(thr != NULL);
45556 
45557 	x = duk_debug_read_byte(thr);
45558 	if (x != sizeof(pu)) {
45559 		goto fail;
45560 	}
45561 	duk_debug_read_bytes(thr, (duk_uint8_t *) &pu.p, sizeof(pu));
45562 #if defined(DUK_USE_INTEGER_LE)
45563 	duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
45564 #endif
45565 	return (void *) pu.p;
45566 
45567  fail:
45568 	DUK_D(DUK_DPRINT("debug connection error: failed to decode pointer"));
45569 	DUK__SET_CONN_BROKEN(thr, 1);
45570 	return (void *) NULL;
45571 }
45572 
45573 DUK_LOCAL duk_double_t duk__debug_read_double_raw(duk_hthread *thr) {
45574 	duk_double_union du;
45575 
45576 	DUK_ASSERT(sizeof(du.uc) == 8);
45577 	duk_debug_read_bytes(thr, (duk_uint8_t *) du.uc, sizeof(du.uc));
45578 	DUK_DBLUNION_DOUBLE_NTOH(&du);
45579 	return du.d;
45580 }
45581 
45582 #if 0
45583 DUK_INTERNAL duk_heaphdr *duk_debug_read_heapptr(duk_hthread *thr) {
45584 	duk_small_uint_t x;
45585 
45586 	DUK_ASSERT(thr != NULL);
45587 
45588 	x = duk_debug_read_byte(thr);
45589 	if (x != DUK_DBG_IB_HEAPPTR) {
45590 		goto fail;
45591 	}
45592 
45593 	return (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
45594 
45595  fail:
45596 	DUK_D(DUK_DPRINT("debug connection error: failed to decode heapptr"));
45597 	DUK__SET_CONN_BROKEN(thr, 1);
45598 	return NULL;
45599 }
45600 #endif
45601 
45602 DUK_INTERNAL duk_heaphdr *duk_debug_read_any_ptr(duk_hthread *thr) {
45603 	duk_small_uint_t x;
45604 
45605 	DUK_ASSERT(thr != NULL);
45606 
45607 	x = duk_debug_read_byte(thr);
45608 	switch (x) {
45609 	case DUK_DBG_IB_OBJECT:
45610 	case DUK_DBG_IB_POINTER:
45611 	case DUK_DBG_IB_HEAPPTR:
45612 		/* Accept any pointer-like value; for 'object' dvalue, read
45613 		 * and ignore the class number.
45614 		 */
45615 		if (x == DUK_DBG_IB_OBJECT) {
45616 			duk_debug_skip_byte(thr);
45617 		}
45618 		break;
45619 	default:
45620 		goto fail;
45621 	}
45622 
45623 	return (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
45624 
45625  fail:
45626 	DUK_D(DUK_DPRINT("debug connection error: failed to decode any pointer (object, pointer, heapptr)"));
45627 	DUK__SET_CONN_BROKEN(thr, 1);
45628 	return NULL;
45629 }
45630 
45631 DUK_INTERNAL duk_tval *duk_debug_read_tval(duk_hthread *thr) {
45632 	duk_uint8_t x;
45633 	duk_uint_t t;
45634 	duk_uint32_t len;
45635 
45636 	DUK_ASSERT(thr != NULL);
45637 
45638 	x = duk_debug_read_byte(thr);
45639 
45640 	if (x >= 0xc0) {
45641 		t = (duk_uint_t) (x - 0xc0);
45642 		t = (t << 8) + duk_debug_read_byte(thr);
45643 		duk_push_uint(thr, (duk_uint_t) t);
45644 		goto return_ptr;
45645 	}
45646 	if (x >= 0x80) {
45647 		duk_push_uint(thr, (duk_uint_t) (x - 0x80));
45648 		goto return_ptr;
45649 	}
45650 	if (x >= 0x60) {
45651 		len = (duk_uint32_t) (x - 0x60);
45652 		duk__debug_read_hstring_raw(thr, len);
45653 		goto return_ptr;
45654 	}
45655 
45656 	switch (x) {
45657 	case DUK_DBG_IB_INT4: {
45658 		duk_int32_t i = duk__debug_read_int32_raw(thr);
45659 		duk_push_i32(thr, i);
45660 		break;
45661 	}
45662 	case DUK_DBG_IB_STR4: {
45663 		len = duk__debug_read_uint32_raw(thr);
45664 		duk__debug_read_hstring_raw(thr, len);
45665 		break;
45666 	}
45667 	case DUK_DBG_IB_STR2: {
45668 		len = duk__debug_read_uint16_raw(thr);
45669 		duk__debug_read_hstring_raw(thr, len);
45670 		break;
45671 	}
45672 	case DUK_DBG_IB_BUF4: {
45673 		len = duk__debug_read_uint32_raw(thr);
45674 		duk__debug_read_hbuffer_raw(thr, len);
45675 		break;
45676 	}
45677 	case DUK_DBG_IB_BUF2: {
45678 		len = duk__debug_read_uint16_raw(thr);
45679 		duk__debug_read_hbuffer_raw(thr, len);
45680 		break;
45681 	}
45682 	case DUK_DBG_IB_UNDEFINED: {
45683 		duk_push_undefined(thr);
45684 		break;
45685 	}
45686 	case DUK_DBG_IB_NULL: {
45687 		duk_push_null(thr);
45688 		break;
45689 	}
45690 	case DUK_DBG_IB_TRUE: {
45691 		duk_push_true(thr);
45692 		break;
45693 	}
45694 	case DUK_DBG_IB_FALSE: {
45695 		duk_push_false(thr);
45696 		break;
45697 	}
45698 	case DUK_DBG_IB_NUMBER: {
45699 		duk_double_t d;
45700 		d = duk__debug_read_double_raw(thr);
45701 		duk_push_number(thr, d);
45702 		break;
45703 	}
45704 	case DUK_DBG_IB_OBJECT: {
45705 		duk_heaphdr *h;
45706 		duk_debug_skip_byte(thr);
45707 		h = (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
45708 		duk_push_heapptr(thr, (void *) h);
45709 		break;
45710 	}
45711 	case DUK_DBG_IB_POINTER: {
45712 		void *ptr;
45713 		ptr = duk__debug_read_pointer_raw(thr);
45714 		duk_push_pointer(thr, ptr);
45715 		break;
45716 	}
45717 	case DUK_DBG_IB_LIGHTFUNC: {
45718 		/* XXX: Not needed for now, so not implemented.  Note that
45719 		 * function pointers may have different size/layout than
45720 		 * a void pointer.
45721 		 */
45722 		DUK_D(DUK_DPRINT("reading lightfunc values unimplemented"));
45723 		goto fail;
45724 	}
45725 	case DUK_DBG_IB_HEAPPTR: {
45726 		duk_heaphdr *h;
45727 		h = (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
45728 		duk_push_heapptr(thr, (void *) h);
45729 		break;
45730 	}
45731 	case DUK_DBG_IB_UNUSED:  /* unused: not accepted in inbound messages */
45732 	default:
45733 		goto fail;
45734 	}
45735 
45736  return_ptr:
45737 	return DUK_GET_TVAL_NEGIDX(thr, -1);
45738 
45739  fail:
45740 	DUK_D(DUK_DPRINT("debug connection error: failed to decode tval"));
45741 	DUK__SET_CONN_BROKEN(thr, 1);
45742 	return NULL;
45743 }
45744 
45745 /*
45746  *  Debug connection write primitives
45747  */
45748 
45749 /* Write fully. */
45750 DUK_INTERNAL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *data, duk_size_t length) {
45751 	duk_heap *heap;
45752 	const duk_uint8_t *p;
45753 	duk_size_t left;
45754 	duk_size_t got;
45755 
45756 	DUK_ASSERT(thr != NULL);
45757 	DUK_ASSERT(length == 0 || data != NULL);
45758 	heap = thr->heap;
45759 	DUK_ASSERT(heap != NULL);
45760 
45761 	if (heap->dbg_write_cb == NULL) {
45762 		DUK_D(DUK_DPRINT("attempt to write %ld bytes in detached state, ignore", (long) length));
45763 		return;
45764 	}
45765 	if (length == 0) {
45766 		/* Avoid doing an actual write callback with length == 0,
45767 		 * because that's reserved for a write flush.
45768 		 */
45769 		return;
45770 	}
45771 	DUK_ASSERT(data != NULL);
45772 
45773 	p = data;
45774 	for (;;) {
45775 		left = (duk_size_t) ((data + length) - p);
45776 		if (left == 0) {
45777 			break;
45778 		}
45779 		DUK_ASSERT(heap->dbg_write_cb != NULL);
45780 		DUK_ASSERT(left >= 1);
45781 #if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)
45782 		left = 1;
45783 #endif
45784 		DUK__DBG_TPORT_ENTER();
45785 		got = heap->dbg_write_cb(heap->dbg_udata, (const char *) p, left);
45786 		DUK__DBG_TPORT_EXIT();
45787 
45788 		if (got == 0 || got > left) {
45789 			duk__debug_null_most_callbacks(thr);  /* avoid calling write callback in detach1() */
45790 			DUK_D(DUK_DPRINT("connection error during write"));
45791 			DUK__SET_CONN_BROKEN(thr, 1);
45792 			return;
45793 		}
45794 		p += got;
45795 	}
45796 }
45797 
45798 DUK_INTERNAL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x) {
45799 	duk_debug_write_bytes(thr, (const duk_uint8_t *) &x, 1);
45800 }
45801 
45802 DUK_INTERNAL void duk_debug_write_unused(duk_hthread *thr) {
45803 	duk_debug_write_byte(thr, DUK_DBG_IB_UNUSED);
45804 }
45805 
45806 DUK_INTERNAL void duk_debug_write_undefined(duk_hthread *thr) {
45807 	duk_debug_write_byte(thr, DUK_DBG_IB_UNDEFINED);
45808 }
45809 
45810 #if defined(DUK_USE_DEBUGGER_INSPECT)
45811 DUK_INTERNAL void duk_debug_write_null(duk_hthread *thr) {
45812 	duk_debug_write_byte(thr, DUK_DBG_IB_NULL);
45813 }
45814 #endif
45815 
45816 DUK_INTERNAL void duk_debug_write_boolean(duk_hthread *thr, duk_uint_t val) {
45817 	duk_debug_write_byte(thr, val ? DUK_DBG_IB_TRUE : DUK_DBG_IB_FALSE);
45818 }
45819 
45820 /* Write signed 32-bit integer. */
45821 DUK_INTERNAL void duk_debug_write_int(duk_hthread *thr, duk_int32_t x) {
45822 	duk_uint8_t buf[5];
45823 	duk_size_t len;
45824 
45825 	DUK_ASSERT(thr != NULL);
45826 
45827 	if (x >= 0 && x <= 0x3fL) {
45828 		buf[0] = (duk_uint8_t) (0x80 + x);
45829 		len = 1;
45830 	} else if (x >= 0 && x <= 0x3fffL) {
45831 		buf[0] = (duk_uint8_t) (0xc0 + (x >> 8));
45832 		buf[1] = (duk_uint8_t) (x & 0xff);
45833 		len = 2;
45834 	} else {
45835 		/* Signed integers always map to 4 bytes now. */
45836 		buf[0] = (duk_uint8_t) DUK_DBG_IB_INT4;
45837 		buf[1] = (duk_uint8_t) ((x >> 24) & 0xff);
45838 		buf[2] = (duk_uint8_t) ((x >> 16) & 0xff);
45839 		buf[3] = (duk_uint8_t) ((x >> 8) & 0xff);
45840 		buf[4] = (duk_uint8_t) (x & 0xff);
45841 		len = 5;
45842 	}
45843 	duk_debug_write_bytes(thr, buf, len);
45844 }
45845 
45846 /* Write unsigned 32-bit integer. */
45847 DUK_INTERNAL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x) {
45848 	/* The debugger protocol doesn't support a plain integer encoding for
45849 	 * the full 32-bit unsigned range (only 32-bit signed).  For now,
45850 	 * unsigned 32-bit values simply written as signed ones.  This is not
45851 	 * a concrete issue except for 32-bit heaphdr fields.  Proper solutions
45852 	 * would be to (a) write such integers as IEEE doubles or (b) add an
45853 	 * unsigned 32-bit dvalue.
45854 	 */
45855 	if (x >= 0x80000000UL) {
45856 		DUK_D(DUK_DPRINT("writing unsigned integer 0x%08lx as signed integer",
45857 		                 (long) x));
45858 	}
45859 	duk_debug_write_int(thr, (duk_int32_t) x);
45860 }
45861 
45862 DUK_INTERNAL void duk_debug_write_strbuf(duk_hthread *thr, const char *data, duk_size_t length, duk_uint8_t marker_base) {
45863 	duk_uint8_t buf[5];
45864 	duk_size_t buflen;
45865 
45866 	DUK_ASSERT(thr != NULL);
45867 	DUK_ASSERT(length == 0 || data != NULL);
45868 
45869 	if (length <= 0x1fUL && marker_base == DUK_DBG_IB_STR4) {
45870 		/* For strings, special form for short lengths. */
45871 		buf[0] = (duk_uint8_t) (0x60 + length);
45872 		buflen = 1;
45873 	} else if (length <= 0xffffUL) {
45874 		buf[0] = (duk_uint8_t) (marker_base + 1);
45875 		buf[1] = (duk_uint8_t) (length >> 8);
45876 		buf[2] = (duk_uint8_t) (length & 0xff);
45877 		buflen = 3;
45878 	} else {
45879 		buf[0] = (duk_uint8_t) marker_base;
45880 		buf[1] = (duk_uint8_t) (length >> 24);
45881 		buf[2] = (duk_uint8_t) ((length >> 16) & 0xff);
45882 		buf[3] = (duk_uint8_t) ((length >> 8) & 0xff);
45883 		buf[4] = (duk_uint8_t) (length & 0xff);
45884 		buflen = 5;
45885 	}
45886 
45887 	duk_debug_write_bytes(thr, (const duk_uint8_t *) buf, buflen);
45888 	duk_debug_write_bytes(thr, (const duk_uint8_t *) data, length);
45889 }
45890 
45891 DUK_INTERNAL void duk_debug_write_string(duk_hthread *thr, const char *data, duk_size_t length) {
45892 	duk_debug_write_strbuf(thr, data, length, DUK_DBG_IB_STR4);
45893 }
45894 
45895 DUK_INTERNAL void duk_debug_write_cstring(duk_hthread *thr, const char *data) {
45896 	DUK_ASSERT(thr != NULL);
45897 
45898 	duk_debug_write_string(thr,
45899 	                       data,
45900 	                       data ? DUK_STRLEN(data) : 0);
45901 }
45902 
45903 DUK_INTERNAL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h) {
45904 	DUK_ASSERT(thr != NULL);
45905 
45906 	/* XXX: differentiate null pointer from empty string? */
45907 	duk_debug_write_string(thr,
45908 	                       (h != NULL ? (const char *) DUK_HSTRING_GET_DATA(h) : NULL),
45909 	                       (h != NULL ? (duk_size_t) DUK_HSTRING_GET_BYTELEN(h) : 0));
45910 }
45911 
45912 DUK_LOCAL void duk__debug_write_hstring_safe_top(duk_hthread *thr) {
45913 	duk_debug_write_hstring(thr, duk_safe_to_hstring(thr, -1));
45914 }
45915 
45916 DUK_INTERNAL void duk_debug_write_buffer(duk_hthread *thr, const char *data, duk_size_t length) {
45917 	duk_debug_write_strbuf(thr, data, length, DUK_DBG_IB_BUF4);
45918 }
45919 
45920 DUK_INTERNAL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h) {
45921 	DUK_ASSERT(thr != NULL);
45922 
45923 	duk_debug_write_buffer(thr,
45924 	                       (h != NULL ? (const char *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h) : NULL),
45925 	                       (h != NULL ? (duk_size_t) DUK_HBUFFER_GET_SIZE(h) : 0));
45926 }
45927 
45928 DUK_LOCAL void duk__debug_write_pointer_raw(duk_hthread *thr, void *ptr, duk_uint8_t ibyte) {
45929 	duk_uint8_t buf[2];
45930 	duk__ptr_union pu;
45931 
45932 	DUK_ASSERT(thr != NULL);
45933 	DUK_ASSERT(sizeof(ptr) >= 1 && sizeof(ptr) <= 16);
45934 	/* ptr may be NULL */
45935 
45936 	buf[0] = ibyte;
45937 	buf[1] = sizeof(pu);
45938 	duk_debug_write_bytes(thr, buf, 2);
45939 	pu.p = (void *) ptr;
45940 #if defined(DUK_USE_INTEGER_LE)
45941 	duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
45942 #endif
45943 	duk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) sizeof(pu));
45944 }
45945 
45946 DUK_INTERNAL void duk_debug_write_pointer(duk_hthread *thr, void *ptr) {
45947 	duk__debug_write_pointer_raw(thr, ptr, DUK_DBG_IB_POINTER);
45948 }
45949 
45950 #if defined(DUK_USE_DEBUGGER_DUMPHEAP) || defined(DUK_USE_DEBUGGER_INSPECT)
45951 DUK_INTERNAL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h) {
45952 	duk__debug_write_pointer_raw(thr, (void *) h, DUK_DBG_IB_HEAPPTR);
45953 }
45954 #endif  /* DUK_USE_DEBUGGER_DUMPHEAP || DUK_USE_DEBUGGER_INSPECT */
45955 
45956 DUK_INTERNAL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj) {
45957 	duk_uint8_t buf[3];
45958 	duk__ptr_union pu;
45959 
45960 	DUK_ASSERT(thr != NULL);
45961 	DUK_ASSERT(sizeof(obj) >= 1 && sizeof(obj) <= 16);
45962 	DUK_ASSERT(obj != NULL);
45963 
45964 	buf[0] = DUK_DBG_IB_OBJECT;
45965 	buf[1] = (duk_uint8_t) DUK_HOBJECT_GET_CLASS_NUMBER(obj);
45966 	buf[2] = sizeof(pu);
45967 	duk_debug_write_bytes(thr, buf, 3);
45968 	pu.p = (void *) obj;
45969 #if defined(DUK_USE_INTEGER_LE)
45970 	duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
45971 #endif
45972 	duk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) sizeof(pu));
45973 }
45974 
45975 DUK_INTERNAL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv) {
45976 	duk_c_function lf_func;
45977 	duk_small_uint_t lf_flags;
45978 	duk_uint8_t buf[4];
45979 	duk_double_union du1;
45980 	duk_double_union du2;
45981 	duk_int32_t i32;
45982 
45983 	DUK_ASSERT(thr != NULL);
45984 	DUK_ASSERT(tv != NULL);
45985 
45986 	switch (DUK_TVAL_GET_TAG(tv)) {
45987 	case DUK_TAG_UNDEFINED:
45988 		duk_debug_write_byte(thr, DUK_DBG_IB_UNDEFINED);
45989 		break;
45990 	case DUK_TAG_UNUSED:
45991 		duk_debug_write_byte(thr, DUK_DBG_IB_UNUSED);
45992 		break;
45993 	case DUK_TAG_NULL:
45994 		duk_debug_write_byte(thr, DUK_DBG_IB_NULL);
45995 		break;
45996 	case DUK_TAG_BOOLEAN:
45997 		DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv) == 0 ||
45998 		           DUK_TVAL_GET_BOOLEAN(tv) == 1);
45999 		duk_debug_write_boolean(thr, DUK_TVAL_GET_BOOLEAN(tv));
46000 		break;
46001 	case DUK_TAG_POINTER:
46002 		duk_debug_write_pointer(thr, (void *) DUK_TVAL_GET_POINTER(tv));
46003 		break;
46004 	case DUK_TAG_LIGHTFUNC:
46005 		DUK_TVAL_GET_LIGHTFUNC(tv, lf_func, lf_flags);
46006 		buf[0] = DUK_DBG_IB_LIGHTFUNC;
46007 		buf[1] = (duk_uint8_t) (lf_flags >> 8);
46008 		buf[2] = (duk_uint8_t) (lf_flags & 0xff);
46009 		buf[3] = sizeof(lf_func);
46010 		duk_debug_write_bytes(thr, buf, 4);
46011 		duk_debug_write_bytes(thr, (const duk_uint8_t *) &lf_func, sizeof(lf_func));
46012 		break;
46013 	case DUK_TAG_STRING:
46014 		duk_debug_write_hstring(thr, DUK_TVAL_GET_STRING(tv));
46015 		break;
46016 	case DUK_TAG_OBJECT:
46017 		duk_debug_write_hobject(thr, DUK_TVAL_GET_OBJECT(tv));
46018 		break;
46019 	case DUK_TAG_BUFFER:
46020 		duk_debug_write_hbuffer(thr, DUK_TVAL_GET_BUFFER(tv));
46021 		break;
46022 #if defined(DUK_USE_FASTINT)
46023 	case DUK_TAG_FASTINT:
46024 #endif
46025 	default:
46026 		/* Numbers are normalized to big (network) endian.  We can
46027 		 * (but are not required) to use integer dvalues when there's
46028 		 * no loss of precision.
46029 		 *
46030 		 * XXX: share check with other code; this check is slow but
46031 		 * reliable and doesn't require careful exponent/mantissa
46032 		 * mask tricks as in the fastint downgrade code.
46033 		 */
46034 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
46035 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
46036 		du1.d = DUK_TVAL_GET_NUMBER(tv);
46037 		i32 = (duk_int32_t) du1.d;
46038 		du2.d = (duk_double_t) i32;
46039 
46040 		DUK_DD(DUK_DDPRINT("i32=%ld du1=%02x%02x%02x%02x%02x%02x%02x%02x "
46041 		                   "du2=%02x%02x%02x%02x%02x%02x%02x%02x",
46042 		                   (long) i32,
46043 		                   (unsigned int) du1.uc[0], (unsigned int) du1.uc[1],
46044 		                   (unsigned int) du1.uc[2], (unsigned int) du1.uc[3],
46045 		                   (unsigned int) du1.uc[4], (unsigned int) du1.uc[5],
46046 		                   (unsigned int) du1.uc[6], (unsigned int) du1.uc[7],
46047 		                   (unsigned int) du2.uc[0], (unsigned int) du2.uc[1],
46048 		                   (unsigned int) du2.uc[2], (unsigned int) du2.uc[3],
46049 		                   (unsigned int) du2.uc[4], (unsigned int) du2.uc[5],
46050 		                   (unsigned int) du2.uc[6], (unsigned int) du2.uc[7]));
46051 
46052 		if (duk_memcmp((const void *) du1.uc, (const void *) du2.uc, sizeof(du1.uc)) == 0) {
46053 			duk_debug_write_int(thr, i32);
46054 		} else {
46055 			DUK_DBLUNION_DOUBLE_HTON(&du1);
46056 			duk_debug_write_byte(thr, DUK_DBG_IB_NUMBER);
46057 			duk_debug_write_bytes(thr, (const duk_uint8_t *) du1.uc, sizeof(du1.uc));
46058 		}
46059 	}
46060 }
46061 
46062 #if defined(DUK_USE_DEBUGGER_DUMPHEAP)
46063 /* Variant for writing duk_tvals so that any heap allocated values are
46064  * written out as tagged heap pointers.
46065  */
46066 DUK_LOCAL void duk__debug_write_tval_heapptr(duk_hthread *thr, duk_tval *tv) {
46067 	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
46068 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
46069 		duk_debug_write_heapptr(thr, h);
46070 	} else {
46071 		duk_debug_write_tval(thr, tv);
46072 	}
46073 }
46074 #endif  /* DUK_USE_DEBUGGER_DUMPHEAP */
46075 
46076 /*
46077  *  Debug connection message write helpers
46078  */
46079 
46080 #if 0  /* unused */
46081 DUK_INTERNAL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command) {
46082 	duk_debug_write_byte(thr, DUK_DBG_IB_REQUEST);
46083 	duk_debug_write_int(thr, command);
46084 }
46085 #endif
46086 
46087 DUK_INTERNAL void duk_debug_write_reply(duk_hthread *thr) {
46088 	duk_debug_write_byte(thr, DUK_DBG_IB_REPLY);
46089 }
46090 
46091 DUK_INTERNAL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uint_t err_code, const char *msg) {
46092 	/* Allow NULL 'msg' */
46093 	duk_debug_write_byte(thr, DUK_DBG_IB_ERROR);
46094 	duk_debug_write_int(thr, (duk_int32_t) err_code);
46095 	duk_debug_write_cstring(thr, msg);
46096 	duk_debug_write_eom(thr);
46097 }
46098 
46099 DUK_INTERNAL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t command) {
46100 	duk_debug_write_byte(thr, DUK_DBG_IB_NOTIFY);
46101 	duk_debug_write_int(thr, (duk_int32_t) command);
46102 }
46103 
46104 DUK_INTERNAL void duk_debug_write_eom(duk_hthread *thr) {
46105 	duk_debug_write_byte(thr, DUK_DBG_IB_EOM);
46106 
46107 	/* As an initial implementation, write flush after every EOM (and the
46108 	 * version identifier).  A better implementation would flush only when
46109 	 * Duktape is finished processing messages so that a flush only happens
46110 	 * after all outbound messages are finished on that occasion.
46111 	 */
46112 	duk_debug_write_flush(thr);
46113 }
46114 
46115 /*
46116  *  Status message and helpers
46117  */
46118 
46119 DUK_INTERNAL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr) {
46120 	duk_activation *act;
46121 	duk_uint_fast32_t line;
46122 	duk_uint_fast32_t pc;
46123 
46124 	act = thr->callstack_curr;
46125 	if (act == NULL) {
46126 		return 0;
46127 	}
46128 
46129 	/* We're conceptually between two opcodes; act->pc indicates the next
46130 	 * instruction to be executed.  This is usually the correct pc/line to
46131 	 * indicate in Status.  (For the 'debugger' statement this now reports
46132 	 * the pc/line after the debugger statement because the debugger opcode
46133 	 * has already been executed.)
46134 	 */
46135 
46136 	pc = duk_hthread_get_act_curr_pc(thr, act);
46137 
46138 	/* XXX: this should be optimized to be a raw query and avoid valstack
46139 	 * operations if possible.
46140 	 */
46141 	duk_push_tval(thr, &act->tv_func);
46142 	line = duk_hobject_pc2line_query(thr, -1, pc);
46143 	duk_pop(thr);
46144 	return line;
46145 }
46146 
46147 DUK_INTERNAL void duk_debug_send_status(duk_hthread *thr) {
46148 	duk_activation *act;
46149 
46150 	duk_debug_write_notify(thr, DUK_DBG_CMD_STATUS);
46151 	duk_debug_write_int(thr, (DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) ? 1 : 0));
46152 
46153 	act = thr->callstack_curr;
46154 	if (act == NULL) {
46155 		duk_debug_write_undefined(thr);
46156 		duk_debug_write_undefined(thr);
46157 		duk_debug_write_int(thr, 0);
46158 		duk_debug_write_int(thr, 0);
46159 	} else {
46160 		duk_push_tval(thr, &act->tv_func);
46161 		duk_get_prop_literal(thr, -1, "fileName");
46162 		duk__debug_write_hstring_safe_top(thr);
46163 		duk_get_prop_literal(thr, -2, "name");
46164 		duk__debug_write_hstring_safe_top(thr);
46165 		duk_pop_3(thr);
46166 		/* Report next pc/line to be executed. */
46167 		duk_debug_write_uint(thr, (duk_uint32_t) duk_debug_curr_line(thr));
46168 		duk_debug_write_uint(thr, (duk_uint32_t) duk_hthread_get_act_curr_pc(thr, act));
46169 	}
46170 
46171 	duk_debug_write_eom(thr);
46172 }
46173 
46174 #if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
46175 DUK_INTERNAL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal) {
46176 	/*
46177 	 *  NFY <int: 5> <int: fatal> <str: msg> <str: filename> <int: linenumber> EOM
46178 	 */
46179 
46180 	duk_activation *act;
46181 	duk_uint32_t pc;
46182 
46183 	DUK_ASSERT(thr->valstack_top > thr->valstack);  /* At least: ... [err] */
46184 
46185 	duk_debug_write_notify(thr, DUK_DBG_CMD_THROW);
46186 	duk_debug_write_int(thr, (duk_int32_t) fatal);
46187 
46188 	/* Report thrown value to client coerced to string */
46189 	duk_dup_top(thr);
46190 	duk__debug_write_hstring_safe_top(thr);
46191 	duk_pop(thr);
46192 
46193 	if (duk_is_error(thr, -1)) {
46194 		/* Error instance, use augmented error data directly */
46195 		duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_FILE_NAME);
46196 		duk__debug_write_hstring_safe_top(thr);
46197 		duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_LINE_NUMBER);
46198 		duk_debug_write_uint(thr, duk_get_uint(thr, -1));
46199 		duk_pop_2(thr);
46200 	} else {
46201 		/* For anything other than an Error instance, we calculate the
46202 		 * error location directly from the current activation if one
46203 		 * exists.
46204 		 */
46205 		act = thr->callstack_curr;
46206 		if (act != NULL) {
46207 			duk_push_tval(thr, &act->tv_func);
46208 			duk_get_prop_literal(thr, -1, "fileName");
46209 			duk__debug_write_hstring_safe_top(thr);
46210 			pc = (duk_uint32_t) duk_hthread_get_act_prev_pc(thr, act);
46211 			duk_debug_write_uint(thr, (duk_uint32_t) duk_hobject_pc2line_query(thr, -2, pc));
46212 			duk_pop_2(thr);
46213 		} else {
46214 			/* Can happen if duk_throw() is called on an empty
46215 			 * callstack.
46216 			 */
46217 			duk_debug_write_cstring(thr, "");
46218 			duk_debug_write_uint(thr, 0);
46219 		}
46220 	}
46221 
46222 	duk_debug_write_eom(thr);
46223 }
46224 #endif  /* DUK_USE_DEBUGGER_THROW_NOTIFY */
46225 
46226 /*
46227  *  Debug message processing
46228  */
46229 
46230 /* Skip dvalue. */
46231 DUK_LOCAL duk_bool_t duk__debug_skip_dvalue(duk_hthread *thr) {
46232 	duk_uint8_t x;
46233 	duk_uint32_t len;
46234 
46235 	x = duk_debug_read_byte(thr);
46236 
46237 	if (x >= 0xc0) {
46238 		duk_debug_skip_byte(thr);
46239 		return 0;
46240 	}
46241 	if (x >= 0x80) {
46242 		return 0;
46243 	}
46244 	if (x >= 0x60) {
46245 		duk_debug_skip_bytes(thr, (duk_size_t) (x - 0x60));
46246 		return 0;
46247 	}
46248 	switch(x) {
46249 	case DUK_DBG_IB_EOM:
46250 		return 1;  /* Return 1: got EOM */
46251 	case DUK_DBG_IB_REQUEST:
46252 	case DUK_DBG_IB_REPLY:
46253 	case DUK_DBG_IB_ERROR:
46254 	case DUK_DBG_IB_NOTIFY:
46255 		break;
46256 	case DUK_DBG_IB_INT4:
46257 		(void) duk__debug_read_uint32_raw(thr);
46258 		break;
46259 	case DUK_DBG_IB_STR4:
46260 	case DUK_DBG_IB_BUF4:
46261 		len = duk__debug_read_uint32_raw(thr);
46262 		duk_debug_skip_bytes(thr, len);
46263 		break;
46264 	case DUK_DBG_IB_STR2:
46265 	case DUK_DBG_IB_BUF2:
46266 		len = duk__debug_read_uint16_raw(thr);
46267 		duk_debug_skip_bytes(thr, len);
46268 		break;
46269 	case DUK_DBG_IB_UNUSED:
46270 	case DUK_DBG_IB_UNDEFINED:
46271 	case DUK_DBG_IB_NULL:
46272 	case DUK_DBG_IB_TRUE:
46273 	case DUK_DBG_IB_FALSE:
46274 		break;
46275 	case DUK_DBG_IB_NUMBER:
46276 		duk_debug_skip_bytes(thr, 8);
46277 		break;
46278 	case DUK_DBG_IB_OBJECT:
46279 		duk_debug_skip_byte(thr);
46280 		len = duk_debug_read_byte(thr);
46281 		duk_debug_skip_bytes(thr, len);
46282 		break;
46283 	case DUK_DBG_IB_POINTER:
46284 	case DUK_DBG_IB_HEAPPTR:
46285 		len = duk_debug_read_byte(thr);
46286 		duk_debug_skip_bytes(thr, len);
46287 		break;
46288 	case DUK_DBG_IB_LIGHTFUNC:
46289 		duk_debug_skip_bytes(thr, 2);
46290 		len = duk_debug_read_byte(thr);
46291 		duk_debug_skip_bytes(thr, len);
46292 		break;
46293 	default:
46294 		goto fail;
46295 	}
46296 
46297 	return 0;
46298 
46299  fail:
46300 	DUK__SET_CONN_BROKEN(thr, 1);
46301 	return 1;  /* Pretend like we got EOM */
46302 }
46303 
46304 /* Skip dvalues to EOM. */
46305 DUK_LOCAL void duk__debug_skip_to_eom(duk_hthread *thr) {
46306 	for (;;) {
46307 		if (duk__debug_skip_dvalue(thr)) {
46308 			break;
46309 		}
46310 	}
46311 }
46312 
46313 /* Read and validate a call stack index.  If index is invalid, write out an
46314  * error message and return zero.
46315  */
46316 DUK_LOCAL duk_int32_t duk__debug_read_validate_csindex(duk_hthread *thr) {
46317 	duk_int32_t level;
46318 	level = duk_debug_read_int(thr);
46319 	if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
46320 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack index");
46321 		return 0;  /* zero indicates failure */
46322 	}
46323 	return level;
46324 }
46325 
46326 /* Read a call stack index and lookup the corresponding duk_activation.
46327  * If index is invalid, write out an error message and return NULL.
46328  */
46329 DUK_LOCAL duk_activation *duk__debug_read_level_get_activation(duk_hthread *thr) {
46330 	duk_activation *act;
46331 	duk_int32_t level;
46332 
46333 	level = duk_debug_read_int(thr);
46334 	act = duk_hthread_get_activation_for_level(thr, level);
46335 	if (act == NULL) {
46336 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack index");
46337 	}
46338 	return act;
46339 }
46340 
46341 /*
46342  *  Simple commands
46343  */
46344 
46345 DUK_LOCAL void duk__debug_handle_basic_info(duk_hthread *thr, duk_heap *heap) {
46346 	DUK_UNREF(heap);
46347 	DUK_D(DUK_DPRINT("debug command Version"));
46348 
46349 	duk_debug_write_reply(thr);
46350 	duk_debug_write_int(thr, DUK_VERSION);
46351 	duk_debug_write_cstring(thr, DUK_GIT_DESCRIBE);
46352 	duk_debug_write_cstring(thr, DUK_USE_TARGET_INFO);
46353 #if defined(DUK_USE_DOUBLE_LE)
46354 	duk_debug_write_int(thr, 1);
46355 #elif defined(DUK_USE_DOUBLE_ME)
46356 	duk_debug_write_int(thr, 2);
46357 #elif defined(DUK_USE_DOUBLE_BE)
46358 	duk_debug_write_int(thr, 3);
46359 #else
46360 	duk_debug_write_int(thr, 0);
46361 #endif
46362 	duk_debug_write_int(thr, (duk_int_t) sizeof(void *));
46363 	duk_debug_write_eom(thr);
46364 }
46365 
46366 DUK_LOCAL void duk__debug_handle_trigger_status(duk_hthread *thr, duk_heap *heap) {
46367 	DUK_UNREF(heap);
46368 	DUK_D(DUK_DPRINT("debug command TriggerStatus"));
46369 
46370 	duk_debug_write_reply(thr);
46371 	duk_debug_write_eom(thr);
46372 	heap->dbg_state_dirty = 1;
46373 }
46374 
46375 DUK_LOCAL void duk__debug_handle_pause(duk_hthread *thr, duk_heap *heap) {
46376 	DUK_D(DUK_DPRINT("debug command Pause"));
46377 	duk_debug_set_paused(heap);
46378 	duk_debug_write_reply(thr);
46379 	duk_debug_write_eom(thr);
46380 }
46381 
46382 DUK_LOCAL void duk__debug_handle_resume(duk_hthread *thr, duk_heap *heap) {
46383 	duk_small_uint_t pause_flags;
46384 
46385 	DUK_D(DUK_DPRINT("debug command Resume"));
46386 
46387 	duk_debug_clear_paused(heap);
46388 
46389 	pause_flags = 0;
46390 #if 0  /* manual testing */
46391 	pause_flags |= DUK_PAUSE_FLAG_ONE_OPCODE;
46392 	pause_flags |= DUK_PAUSE_FLAG_CAUGHT_ERROR;
46393 	pause_flags |= DUK_PAUSE_FLAG_UNCAUGHT_ERROR;
46394 #endif
46395 #if defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT)
46396 	pause_flags |= DUK_PAUSE_FLAG_UNCAUGHT_ERROR;
46397 #endif
46398 
46399 	duk__debug_set_pause_state(thr, heap, pause_flags);
46400 
46401 	duk_debug_write_reply(thr);
46402 	duk_debug_write_eom(thr);
46403 }
46404 
46405 DUK_LOCAL void duk__debug_handle_step(duk_hthread *thr, duk_heap *heap, duk_int32_t cmd) {
46406 	duk_small_uint_t pause_flags;
46407 
46408 	DUK_D(DUK_DPRINT("debug command StepInto/StepOver/StepOut: %d", (int) cmd));
46409 
46410 	if (cmd == DUK_DBG_CMD_STEPINTO) {
46411 		pause_flags = DUK_PAUSE_FLAG_LINE_CHANGE |
46412 		              DUK_PAUSE_FLAG_FUNC_ENTRY |
46413 		              DUK_PAUSE_FLAG_FUNC_EXIT;
46414 	} else if (cmd == DUK_DBG_CMD_STEPOVER) {
46415 		pause_flags = DUK_PAUSE_FLAG_LINE_CHANGE |
46416 		              DUK_PAUSE_FLAG_FUNC_EXIT;
46417 	} else {
46418 		DUK_ASSERT(cmd == DUK_DBG_CMD_STEPOUT);
46419 		pause_flags = DUK_PAUSE_FLAG_FUNC_EXIT;
46420 	}
46421 #if defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT)
46422 	pause_flags |= DUK_PAUSE_FLAG_UNCAUGHT_ERROR;
46423 #endif
46424 
46425 	/* If current activation doesn't have line information, line-based
46426 	 * pause flags are automatically disabled.  As a result, e.g.
46427 	 * StepInto will then pause on (native) function entry or exit.
46428 	 */
46429 	duk_debug_clear_paused(heap);
46430 	duk__debug_set_pause_state(thr, heap, pause_flags);
46431 
46432 	duk_debug_write_reply(thr);
46433 	duk_debug_write_eom(thr);
46434 }
46435 
46436 DUK_LOCAL void duk__debug_handle_list_break(duk_hthread *thr, duk_heap *heap) {
46437 	duk_small_int_t i;
46438 
46439 	DUK_D(DUK_DPRINT("debug command ListBreak"));
46440 	duk_debug_write_reply(thr);
46441 	for (i = 0; i < (duk_small_int_t) heap->dbg_breakpoint_count; i++) {
46442 		duk_debug_write_hstring(thr, heap->dbg_breakpoints[i].filename);
46443 		duk_debug_write_uint(thr, (duk_uint32_t) heap->dbg_breakpoints[i].line);
46444 	}
46445 	duk_debug_write_eom(thr);
46446 }
46447 
46448 DUK_LOCAL void duk__debug_handle_add_break(duk_hthread *thr, duk_heap *heap) {
46449 	duk_hstring *filename;
46450 	duk_uint32_t linenumber;
46451 	duk_small_int_t idx;
46452 
46453 	DUK_UNREF(heap);
46454 
46455 	filename = duk_debug_read_hstring(thr);
46456 	linenumber = (duk_uint32_t) duk_debug_read_int(thr);
46457 	DUK_D(DUK_DPRINT("debug command AddBreak: %!O:%ld", (duk_hobject *) filename, (long) linenumber));
46458 	idx = duk_debug_add_breakpoint(thr, filename, linenumber);
46459 	if (idx >= 0) {
46460 		duk_debug_write_reply(thr);
46461 		duk_debug_write_int(thr, (duk_int32_t) idx);
46462 		duk_debug_write_eom(thr);
46463 	} else {
46464 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_TOOMANY, "no space for breakpoint");
46465 	}
46466 }
46467 
46468 DUK_LOCAL void duk__debug_handle_del_break(duk_hthread *thr, duk_heap *heap) {
46469 	duk_small_uint_t idx;
46470 
46471 	DUK_UNREF(heap);
46472 
46473 	DUK_D(DUK_DPRINT("debug command DelBreak"));
46474 	idx = (duk_small_uint_t) duk_debug_read_int(thr);
46475 	if (duk_debug_remove_breakpoint(thr, idx)) {
46476 		duk_debug_write_reply(thr);
46477 		duk_debug_write_eom(thr);
46478 	} else {
46479 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid breakpoint index");
46480 	}
46481 }
46482 
46483 DUK_LOCAL void duk__debug_handle_get_var(duk_hthread *thr, duk_heap *heap) {
46484 	duk_activation *act;
46485 	duk_hstring *str;
46486 	duk_bool_t rc;
46487 
46488 	DUK_UNREF(heap);
46489 	DUK_D(DUK_DPRINT("debug command GetVar"));
46490 
46491 	act = duk__debug_read_level_get_activation(thr);
46492 	if (act == NULL) {
46493 		return;
46494 	}
46495 	str = duk_debug_read_hstring(thr);  /* push to stack */
46496 	DUK_ASSERT(str != NULL);
46497 
46498 	rc = duk_js_getvar_activation(thr, act, str, 0);
46499 
46500 	duk_debug_write_reply(thr);
46501 	if (rc) {
46502 		duk_debug_write_int(thr, 1);
46503 		DUK_ASSERT(duk_get_tval(thr, -2) != NULL);
46504 		duk_debug_write_tval(thr, duk_get_tval(thr, -2));
46505 	} else {
46506 		duk_debug_write_int(thr, 0);
46507 		duk_debug_write_unused(thr);
46508 	}
46509 	duk_debug_write_eom(thr);
46510 }
46511 
46512 DUK_LOCAL void duk__debug_handle_put_var(duk_hthread *thr, duk_heap *heap) {
46513 	duk_activation *act;
46514 	duk_hstring *str;
46515 	duk_tval *tv;
46516 
46517 	DUK_UNREF(heap);
46518 	DUK_D(DUK_DPRINT("debug command PutVar"));
46519 
46520 	act = duk__debug_read_level_get_activation(thr);
46521 	if (act == NULL) {
46522 		return;
46523 	}
46524 	str = duk_debug_read_hstring(thr);  /* push to stack */
46525 	DUK_ASSERT(str != NULL);
46526 	tv = duk_debug_read_tval(thr);
46527 	if (tv == NULL) {
46528 		/* detached */
46529 		return;
46530 	}
46531 
46532 	duk_js_putvar_activation(thr, act, str, tv, 0);
46533 
46534 	/* XXX: Current putvar implementation doesn't have a success flag,
46535 	 * add one and send to debug client?
46536 	 */
46537 	duk_debug_write_reply(thr);
46538 	duk_debug_write_eom(thr);
46539 }
46540 
46541 DUK_LOCAL void duk__debug_handle_get_call_stack(duk_hthread *thr, duk_heap *heap) {
46542 	duk_hthread *curr_thr = thr;
46543 	duk_activation *curr_act;
46544 	duk_uint_fast32_t pc;
46545 	duk_uint_fast32_t line;
46546 
46547 	DUK_ASSERT(thr != NULL);
46548 	DUK_UNREF(heap);
46549 
46550 	duk_debug_write_reply(thr);
46551 	while (curr_thr != NULL) {
46552 		for (curr_act = curr_thr->callstack_curr; curr_act != NULL; curr_act = curr_act->parent) {
46553 			/* PC/line semantics here are:
46554 			 *   - For callstack top we're conceptually between two
46555 			 *     opcodes and current PC indicates next line to
46556 			 *     execute, so report that (matches Status).
46557 			 *   - For other activations we're conceptually still
46558 			 *     executing the instruction at PC-1, so report that
46559 			 *     (matches error stacktrace behavior).
46560 			 *   - See: https://github.com/svaarala/duktape/issues/281
46561 			 */
46562 
46563 			/* XXX: optimize to use direct reads, i.e. avoid
46564 			 * value stack operations.
46565 			 */
46566 			duk_push_tval(thr, &curr_act->tv_func);
46567 			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_FILE_NAME);
46568 			duk__debug_write_hstring_safe_top(thr);
46569 			duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_NAME);
46570 			duk__debug_write_hstring_safe_top(thr);
46571 			pc = duk_hthread_get_act_curr_pc(thr, curr_act);
46572 			if (curr_act != curr_thr->callstack_curr && pc > 0) {
46573 				pc--;
46574 			}
46575 			line = duk_hobject_pc2line_query(thr, -3, pc);
46576 			duk_debug_write_uint(thr, (duk_uint32_t) line);
46577 			duk_debug_write_uint(thr, (duk_uint32_t) pc);
46578 			duk_pop_3(thr);
46579 		}
46580 		curr_thr = curr_thr->resumer;
46581 	}
46582 	/* SCANBUILD: warning about 'thr' potentially being NULL here,
46583 	 * warning is incorrect because thr != NULL always here.
46584 	 */
46585 	duk_debug_write_eom(thr);
46586 }
46587 
46588 DUK_LOCAL void duk__debug_handle_get_locals(duk_hthread *thr, duk_heap *heap) {
46589 	duk_activation *act;
46590 	duk_hstring *varname;
46591 
46592 	DUK_UNREF(heap);
46593 
46594 	act = duk__debug_read_level_get_activation(thr);
46595 	if (act == NULL) {
46596 		return;
46597 	}
46598 
46599 	duk_debug_write_reply(thr);
46600 
46601 	/* XXX: several nice-to-have improvements here:
46602 	 *   - Use direct reads avoiding value stack operations
46603 	 *   - Avoid triggering getters, indicate getter values to debug client
46604 	 *   - If side effects are possible, add error catching
46605 	 */
46606 
46607 	if (DUK_TVAL_IS_OBJECT(&act->tv_func)) {
46608 		duk_hobject *h_func = DUK_TVAL_GET_OBJECT(&act->tv_func);
46609 		duk_hobject *h_varmap;
46610 
46611 		h_varmap = duk_hobject_get_varmap(thr, h_func);
46612 		if (h_varmap != NULL) {
46613 			duk_push_hobject(thr, h_varmap);
46614 			duk_enum(thr, -1, 0 /*enum_flags*/);
46615 			while (duk_next(thr, -1 /*enum_index*/, 0 /*get_value*/)) {
46616 				varname = duk_known_hstring(thr, -1);
46617 
46618 				duk_js_getvar_activation(thr, act, varname, 0 /*throw_flag*/);
46619 				/* [ ... func varmap enum key value this ] */
46620 				duk_debug_write_hstring(thr, duk_get_hstring(thr, -3));
46621 				duk_debug_write_tval(thr, duk_get_tval(thr, -2));
46622 				duk_pop_3(thr);  /* -> [ ... func varmap enum ] */
46623 			}
46624 		} else {
46625 			DUK_D(DUK_DPRINT("varmap missing in GetLocals, ignore"));
46626 		}
46627 	} else {
46628 		DUK_D(DUK_DPRINT("varmap is not an object in GetLocals, ignore"));
46629 	}
46630 
46631 	duk_debug_write_eom(thr);
46632 }
46633 
46634 DUK_LOCAL void duk__debug_handle_eval(duk_hthread *thr, duk_heap *heap) {
46635 	duk_small_uint_t call_flags;
46636 	duk_int_t call_ret;
46637 	duk_small_int_t eval_err;
46638 	duk_bool_t direct_eval;
46639 	duk_int32_t level;
46640 	duk_idx_t idx_func;
46641 
46642 	DUK_UNREF(heap);
46643 
46644 	DUK_D(DUK_DPRINT("debug command Eval"));
46645 
46646 	/* The eval code is executed within the lexical environment of a specified
46647 	 * activation.  For now, use global object eval() function, with the eval
46648 	 * considered a 'direct call to eval'.
46649 	 *
46650 	 * Callstack index for debug commands only affects scope -- the callstack
46651 	 * as seen by, e.g. Duktape.act() will be the same regardless.
46652 	 */
46653 
46654 	/* nargs == 2 so we can pass a callstack index to eval(). */
46655 	idx_func = duk_get_top(thr);
46656 	duk_push_c_function(thr, duk_bi_global_object_eval, 2 /*nargs*/);
46657 	duk_push_undefined(thr);  /* 'this' binding shouldn't matter here */
46658 
46659 	/* Read callstack index, if non-null. */
46660 	if (duk_debug_peek_byte(thr) == DUK_DBG_IB_NULL) {
46661 		direct_eval = 0;
46662 		level = -1;  /* Not needed, but silences warning. */
46663 		(void) duk_debug_read_byte(thr);
46664 	} else {
46665 		direct_eval = 1;
46666 		level = duk__debug_read_validate_csindex(thr);
46667 		if (level == 0) {
46668 			return;
46669 		}
46670 	}
46671 
46672 	DUK_ASSERT(!direct_eval ||
46673 	           (level < 0 && -level <= (duk_int32_t) thr->callstack_top));
46674 
46675 	(void) duk_debug_read_hstring(thr);
46676 	if (direct_eval) {
46677 		duk_push_int(thr, level - 1);  /* compensate for eval() call */
46678 	}
46679 
46680 	/* [ ... eval "eval" eval_input level? ] */
46681 
46682 	call_flags = 0;
46683 	if (direct_eval) {
46684 		duk_activation *act;
46685 		duk_hobject *fun;
46686 
46687 		act = duk_hthread_get_activation_for_level(thr, level);
46688 		if (act != NULL) {
46689 			fun = DUK_ACT_GET_FUNC(act);
46690 			if (fun != NULL && DUK_HOBJECT_IS_COMPFUNC(fun)) {
46691 				/* Direct eval requires that there's a current
46692 				 * activation and it is an ECMAScript function.
46693 				 * When Eval is executed from e.g. cooperate API
46694 				 * call we'll need to do an indirect eval instead.
46695 				 */
46696 				call_flags |= DUK_CALL_FLAG_DIRECT_EVAL;
46697 			}
46698 		}
46699 	}
46700 
46701 	call_ret = duk_pcall_method_flags(thr, duk_get_top(thr) - (idx_func + 2), call_flags);
46702 
46703 	if (call_ret == DUK_EXEC_SUCCESS) {
46704 		eval_err = 0;
46705 		/* Use result value as is. */
46706 	} else {
46707 		/* For errors a string coerced result is most informative
46708 		 * right now, as the debug client doesn't have the capability
46709 		 * to traverse the error object.
46710 		 */
46711 		eval_err = 1;
46712 		duk_safe_to_string(thr, -1);
46713 	}
46714 
46715 	/* [ ... result ] */
46716 
46717 	duk_debug_write_reply(thr);
46718 	duk_debug_write_int(thr, (duk_int32_t) eval_err);
46719 	DUK_ASSERT(duk_get_tval(thr, -1) != NULL);
46720 	duk_debug_write_tval(thr, duk_get_tval(thr, -1));
46721 	duk_debug_write_eom(thr);
46722 }
46723 
46724 DUK_LOCAL void duk__debug_handle_detach(duk_hthread *thr, duk_heap *heap) {
46725 	DUK_UNREF(heap);
46726 	DUK_D(DUK_DPRINT("debug command Detach"));
46727 
46728 	duk_debug_write_reply(thr);
46729 	duk_debug_write_eom(thr);
46730 
46731 	DUK_D(DUK_DPRINT("debug connection detached, mark broken"));
46732 	DUK__SET_CONN_BROKEN(thr, 0);  /* not an error */
46733 }
46734 
46735 DUK_LOCAL void duk__debug_handle_apprequest(duk_hthread *thr, duk_heap *heap) {
46736 	duk_idx_t old_top;
46737 
46738 	DUK_D(DUK_DPRINT("debug command AppRequest"));
46739 
46740 	old_top = duk_get_top(thr);  /* save stack top */
46741 
46742 	if (heap->dbg_request_cb != NULL) {
46743 		duk_idx_t nrets;
46744 		duk_idx_t nvalues = 0;
46745 		duk_idx_t top, idx;
46746 
46747 		/* Read tvals from the message and push them onto the valstack,
46748 		 * then call the request callback to process the request.
46749 		 */
46750 		while (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
46751 			duk_tval *tv;
46752 			if (!duk_check_stack(thr, 1)) {
46753 				DUK_D(DUK_DPRINT("failed to allocate space for request dvalue(s)"));
46754 				goto fail;
46755 			}
46756 			tv = duk_debug_read_tval(thr);  /* push to stack */
46757 			if (tv == NULL) {
46758 				/* detached */
46759 				return;
46760 			}
46761 			nvalues++;
46762 		}
46763 		DUK_ASSERT(duk_get_top(thr) == old_top + nvalues);
46764 
46765 		/* Request callback should push values for reply to client onto valstack */
46766 		DUK_D(DUK_DPRINT("calling into AppRequest request_cb with nvalues=%ld, old_top=%ld, top=%ld",
46767 		                 (long) nvalues, (long) old_top, (long) duk_get_top(thr)));
46768 		nrets = heap->dbg_request_cb(thr, heap->dbg_udata, nvalues);
46769 		DUK_D(DUK_DPRINT("returned from AppRequest request_cb; nvalues=%ld -> nrets=%ld, old_top=%ld, top=%ld",
46770 		                 (long) nvalues, (long) nrets, (long) old_top, (long) duk_get_top(thr)));
46771 		if (nrets >= 0) {
46772 			DUK_ASSERT(duk_get_top(thr) >= old_top + nrets);
46773 			if (duk_get_top(thr) < old_top + nrets) {
46774 				DUK_D(DUK_DPRINT("AppRequest callback doesn't match value stack configuration, "
46775 				                 "top=%ld < old_top=%ld + nrets=%ld; "
46776 				                 "this might mean it's unsafe to continue!",
46777 				                 (long) duk_get_top(thr), (long) old_top, (long) nrets));
46778 				goto fail;
46779 			}
46780 
46781 			/* Reply with tvals pushed by request callback */
46782 			duk_debug_write_byte(thr, DUK_DBG_IB_REPLY);
46783 			top = duk_get_top(thr);
46784 			for (idx = top - nrets; idx < top; idx++) {
46785 				duk_debug_write_tval(thr, DUK_GET_TVAL_POSIDX(thr, idx));
46786 			}
46787 			duk_debug_write_eom(thr);
46788 		} else {
46789 			DUK_ASSERT(duk_get_top(thr) >= old_top + 1);
46790 			if (duk_get_top(thr) < old_top + 1) {
46791 				DUK_D(DUK_DPRINT("request callback return value doesn't match value stack configuration"));
46792 				goto fail;
46793 			}
46794 			duk_debug_write_error_eom(thr, DUK_DBG_ERR_APPLICATION, duk_get_string(thr, -1));
46795 		}
46796 
46797 		duk_set_top(thr, old_top);  /* restore stack top */
46798 	} else {
46799 		DUK_D(DUK_DPRINT("no request callback, treat AppRequest as unsupported"));
46800 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, "AppRequest unsupported by target");
46801 	}
46802 
46803 	return;
46804 
46805  fail:
46806 	duk_set_top(thr, old_top);  /* restore stack top */
46807 	DUK__SET_CONN_BROKEN(thr, 1);
46808 }
46809 
46810 /*
46811  *  DumpHeap command
46812  */
46813 
46814 #if defined(DUK_USE_DEBUGGER_DUMPHEAP)
46815 /* XXX: this has some overlap with object inspection; remove this and make
46816  * DumpHeap return lists of heapptrs instead?
46817  */
46818 DUK_LOCAL void duk__debug_dump_heaphdr(duk_hthread *thr, duk_heap *heap, duk_heaphdr *hdr) {
46819 	DUK_UNREF(heap);
46820 
46821 	duk_debug_write_heapptr(thr, hdr);
46822 	duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_TYPE(hdr));
46823 	duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_FLAGS_RAW(hdr));
46824 #if defined(DUK_USE_REFERENCE_COUNTING)
46825 	duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_REFCOUNT(hdr));
46826 #else
46827 	duk_debug_write_int(thr, (duk_int32_t) -1);
46828 #endif
46829 
46830 	switch (DUK_HEAPHDR_GET_TYPE(hdr)) {
46831 	case DUK_HTYPE_STRING: {
46832 		duk_hstring *h = (duk_hstring *) hdr;
46833 
46834 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HSTRING_GET_BYTELEN(h));
46835 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HSTRING_GET_CHARLEN(h));
46836 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HSTRING_GET_HASH(h));
46837 		duk_debug_write_hstring(thr, h);
46838 		break;
46839 	}
46840 	case DUK_HTYPE_OBJECT: {
46841 		duk_hobject *h = (duk_hobject *) hdr;
46842 		duk_hstring *k;
46843 		duk_uint_fast32_t i;
46844 
46845 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_CLASS_NUMBER(h));
46846 		duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(heap, h));
46847 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ESIZE(h));
46848 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ENEXT(h));
46849 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ASIZE(h));
46850 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_HSIZE(h));
46851 
46852 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
46853 			duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_E_GET_FLAGS(heap, h, i));
46854 			k = DUK_HOBJECT_E_GET_KEY(heap, h, i);
46855 			duk_debug_write_heapptr(thr, (duk_heaphdr *) k);
46856 			if (k == NULL) {
46857 				duk_debug_write_int(thr, 0);  /* isAccessor */
46858 				duk_debug_write_unused(thr);
46859 				continue;
46860 			}
46861 			if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {
46862 				duk_debug_write_int(thr, 1);  /* isAccessor */
46863 				duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);
46864 				duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);
46865 			} else {
46866 				duk_debug_write_int(thr, 0);  /* isAccessor */
46867 
46868 				duk__debug_write_tval_heapptr(thr, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);
46869 			}
46870 		}
46871 
46872 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
46873 			/* Note: array dump will include elements beyond
46874 			 * 'length'.
46875 			 */
46876 			duk__debug_write_tval_heapptr(thr, DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i));
46877 		}
46878 		break;
46879 	}
46880 	case DUK_HTYPE_BUFFER: {
46881 		duk_hbuffer *h = (duk_hbuffer *) hdr;
46882 
46883 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HBUFFER_GET_SIZE(h));
46884 		duk_debug_write_buffer(thr, (const char *) DUK_HBUFFER_GET_DATA_PTR(heap, h), (duk_size_t) DUK_HBUFFER_GET_SIZE(h));
46885 		break;
46886 	}
46887 	default: {
46888 		DUK_D(DUK_DPRINT("invalid htype: %d", (int) DUK_HEAPHDR_GET_TYPE(hdr)));
46889 	}
46890 	}
46891 }
46892 
46893 DUK_LOCAL void duk__debug_dump_heap_allocated(duk_hthread *thr, duk_heap *heap) {
46894 	duk_heaphdr *hdr;
46895 
46896 	hdr = heap->heap_allocated;
46897 	while (hdr != NULL) {
46898 		duk__debug_dump_heaphdr(thr, heap, hdr);
46899 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
46900 	}
46901 }
46902 
46903 DUK_LOCAL void duk__debug_dump_strtab(duk_hthread *thr, duk_heap *heap) {
46904 	duk_uint32_t i;
46905 	duk_hstring *h;
46906 
46907 	for (i = 0; i < heap->st_size; i++) {
46908 #if defined(DUK_USE_STRTAB_PTRCOMP)
46909 		h = DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, heap->strtable16[i]);
46910 #else
46911 		h = heap->strtable[i];
46912 #endif
46913 		while (h != NULL) {
46914 			duk__debug_dump_heaphdr(thr, heap, (duk_heaphdr *) h);
46915 			h = h->hdr.h_next;
46916 		}
46917 	}
46918 }
46919 
46920 DUK_LOCAL void duk__debug_handle_dump_heap(duk_hthread *thr, duk_heap *heap) {
46921 	DUK_D(DUK_DPRINT("debug command DumpHeap"));
46922 
46923 	duk_debug_write_reply(thr);
46924 	duk__debug_dump_heap_allocated(thr, heap);
46925 	duk__debug_dump_strtab(thr, heap);
46926 	duk_debug_write_eom(thr);
46927 }
46928 #endif  /* DUK_USE_DEBUGGER_DUMPHEAP */
46929 
46930 DUK_LOCAL void duk__debug_handle_get_bytecode(duk_hthread *thr, duk_heap *heap) {
46931 	duk_activation *act;
46932 	duk_hcompfunc *fun = NULL;
46933 	duk_size_t i, n;
46934 	duk_tval *tv;
46935 	duk_hobject **fn;
46936 	duk_int32_t level = -1;
46937 	duk_uint8_t ibyte;
46938 
46939 	DUK_UNREF(heap);
46940 
46941 	DUK_D(DUK_DPRINT("debug command GetBytecode"));
46942 
46943 	ibyte = duk_debug_peek_byte(thr);
46944 	if (ibyte != DUK_DBG_IB_EOM) {
46945 		tv = duk_debug_read_tval(thr);
46946 		if (tv == NULL) {
46947 			/* detached */
46948 			return;
46949 		}
46950 		if (DUK_TVAL_IS_OBJECT(tv)) {
46951 			/* tentative, checked later */
46952 			fun = (duk_hcompfunc *) DUK_TVAL_GET_OBJECT(tv);
46953 			DUK_ASSERT(fun != NULL);
46954 		} else if (DUK_TVAL_IS_NUMBER(tv)) {
46955 			level = (duk_int32_t) DUK_TVAL_GET_NUMBER(tv);
46956 		} else {
46957 			DUK_D(DUK_DPRINT("invalid argument to GetBytecode: %!T", tv));
46958 			goto fail_args;
46959 		}
46960 	}
46961 
46962 	if (fun == NULL) {
46963 		act = duk_hthread_get_activation_for_level(thr, level);
46964 		if (act == NULL) {
46965 			goto fail_index;
46966 		}
46967 		fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
46968 	}
46969 
46970 	if (fun == NULL || !DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun)) {
46971 		DUK_D(DUK_DPRINT("invalid argument to GetBytecode: %!O", fun));
46972 		goto fail_args;
46973 	}
46974 	DUK_ASSERT(fun != NULL && DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun));
46975 
46976 	duk_debug_write_reply(thr);
46977 	n = DUK_HCOMPFUNC_GET_CONSTS_COUNT(heap, fun);
46978 	duk_debug_write_int(thr, (duk_int32_t) n);
46979 	tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, fun);
46980 	for (i = 0; i < n; i++) {
46981 		duk_debug_write_tval(thr, tv);
46982 		tv++;
46983 	}
46984 	n = DUK_HCOMPFUNC_GET_FUNCS_COUNT(heap, fun);
46985 	duk_debug_write_int(thr, (duk_int32_t) n);
46986 	fn = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, fun);
46987 	for (i = 0; i < n; i++) {
46988 		duk_debug_write_hobject(thr, *fn);
46989 		fn++;
46990 	}
46991 	duk_debug_write_string(thr,
46992 	                       (const char *) DUK_HCOMPFUNC_GET_CODE_BASE(heap, fun),
46993 	                       (duk_size_t) DUK_HCOMPFUNC_GET_CODE_SIZE(heap, fun));
46994 	duk_debug_write_eom(thr);
46995 	return;
46996 
46997  fail_args:
46998 	duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid argument");
46999 	return;
47000 
47001  fail_index:
47002 	duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack index");
47003 	return;
47004 }
47005 
47006 /*
47007  *  Object inspection commands: GetHeapObjInfo, GetObjPropDesc,
47008  *  GetObjPropDescRange
47009  */
47010 
47011 #if defined(DUK_USE_DEBUGGER_INSPECT)
47012 
47013 #if 0 /* pruned */
47014 DUK_LOCAL const char * const duk__debug_getinfo_heaphdr_keys[] = {
47015 	"reachable",
47016 	"temproot",
47017 	"finalizable",
47018 	"finalized",
47019 	"readonly"
47020 	/* NULL not needed here */
47021 };
47022 DUK_LOCAL duk_uint_t duk__debug_getinfo_heaphdr_masks[] = {
47023 	DUK_HEAPHDR_FLAG_REACHABLE,
47024 	DUK_HEAPHDR_FLAG_TEMPROOT,
47025 	DUK_HEAPHDR_FLAG_FINALIZABLE,
47026 	DUK_HEAPHDR_FLAG_FINALIZED,
47027 	DUK_HEAPHDR_FLAG_READONLY,
47028 	0  /* terminator */
47029 };
47030 #endif
47031 DUK_LOCAL const char * const duk__debug_getinfo_hstring_keys[] = {
47032 #if 0
47033 	"arridx",
47034 	"symbol",
47035 	"hidden",
47036 	"reserved_word",
47037 	"strict_reserved_word",
47038 	"eval_or_arguments",
47039 #endif
47040 	"extdata"
47041 	/* NULL not needed here */
47042 };
47043 DUK_LOCAL duk_uint_t duk__debug_getinfo_hstring_masks[] = {
47044 #if 0
47045 	DUK_HSTRING_FLAG_ARRIDX,
47046 	DUK_HSTRING_FLAG_SYMBOL,
47047 	DUK_HSTRING_FLAG_HIDDEN,
47048 	DUK_HSTRING_FLAG_RESERVED_WORD,
47049 	DUK_HSTRING_FLAG_STRICT_RESERVED_WORD,
47050 	DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS,
47051 #endif
47052 	DUK_HSTRING_FLAG_EXTDATA,
47053 	0  /* terminator */
47054 };
47055 DUK_LOCAL const char * const duk__debug_getinfo_hobject_keys[] = {
47056 	"extensible",
47057 	"constructable",
47058 	"callable",
47059 	"boundfunc",
47060 	"compfunc",
47061 	"natfunc",
47062 	"bufobj",
47063 	"fastrefs",
47064 	"array_part",
47065 	"strict",
47066 	"notail",
47067 	"newenv",
47068 	"namebinding",
47069 	"createargs",
47070 	"have_finalizer",
47071 	"exotic_array",
47072 	"exotic_stringobj",
47073 	"exotic_arguments",
47074 	"exotic_proxyobj",
47075 	"special_call"
47076 	/* NULL not needed here */
47077 };
47078 DUK_LOCAL duk_uint_t duk__debug_getinfo_hobject_masks[] = {
47079 	DUK_HOBJECT_FLAG_EXTENSIBLE,
47080 	DUK_HOBJECT_FLAG_CONSTRUCTABLE,
47081 	DUK_HOBJECT_FLAG_CALLABLE,
47082 	DUK_HOBJECT_FLAG_BOUNDFUNC,
47083 	DUK_HOBJECT_FLAG_COMPFUNC,
47084 	DUK_HOBJECT_FLAG_NATFUNC,
47085 	DUK_HOBJECT_FLAG_BUFOBJ,
47086 	DUK_HOBJECT_FLAG_FASTREFS,
47087 	DUK_HOBJECT_FLAG_ARRAY_PART,
47088 	DUK_HOBJECT_FLAG_STRICT,
47089 	DUK_HOBJECT_FLAG_NOTAIL,
47090 	DUK_HOBJECT_FLAG_NEWENV,
47091 	DUK_HOBJECT_FLAG_NAMEBINDING,
47092 	DUK_HOBJECT_FLAG_CREATEARGS,
47093 	DUK_HOBJECT_FLAG_HAVE_FINALIZER,
47094 	DUK_HOBJECT_FLAG_EXOTIC_ARRAY,
47095 	DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ,
47096 	DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS,
47097 	DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ,
47098 	DUK_HOBJECT_FLAG_SPECIAL_CALL,
47099 	0  /* terminator */
47100 };
47101 DUK_LOCAL const char * const duk__debug_getinfo_hbuffer_keys[] = {
47102 	"dynamic",
47103 	"external"
47104 	/* NULL not needed here */
47105 };
47106 DUK_LOCAL duk_uint_t duk__debug_getinfo_hbuffer_masks[] = {
47107 	DUK_HBUFFER_FLAG_DYNAMIC,
47108 	DUK_HBUFFER_FLAG_EXTERNAL,
47109 	0  /* terminator */
47110 };
47111 
47112 DUK_LOCAL void duk__debug_getinfo_flags_key(duk_hthread *thr, const char *key) {
47113 	duk_debug_write_uint(thr, 0);
47114 	duk_debug_write_cstring(thr, key);
47115 }
47116 
47117 DUK_LOCAL void duk__debug_getinfo_prop_uint(duk_hthread *thr, const char *key, duk_uint_t val) {
47118 	duk_debug_write_uint(thr, 0);
47119 	duk_debug_write_cstring(thr, key);
47120 	duk_debug_write_uint(thr, val);
47121 }
47122 
47123 DUK_LOCAL void duk__debug_getinfo_prop_int(duk_hthread *thr, const char *key, duk_int_t val) {
47124 	duk_debug_write_uint(thr, 0);
47125 	duk_debug_write_cstring(thr, key);
47126 	duk_debug_write_int(thr, val);
47127 }
47128 
47129 DUK_LOCAL void duk__debug_getinfo_prop_bool(duk_hthread *thr, const char *key, duk_bool_t val) {
47130 	duk_debug_write_uint(thr, 0);
47131 	duk_debug_write_cstring(thr, key);
47132 	duk_debug_write_boolean(thr, val);
47133 }
47134 
47135 DUK_LOCAL void duk__debug_getinfo_bitmask(duk_hthread *thr, const char * const * keys, duk_uint_t *masks, duk_uint_t flags) {
47136 	const char *key;
47137 	duk_uint_t mask;
47138 
47139 	for (;;) {
47140 		mask = *masks++;
47141 		if (mask == 0) {
47142 			break;
47143 		}
47144 		key = *keys++;
47145 		DUK_ASSERT(key != NULL);
47146 
47147 		DUK_DD(DUK_DDPRINT("inspect bitmask: key=%s, mask=0x%08lx, flags=0x%08lx", key, (unsigned long) mask, (unsigned long) flags));
47148 		duk__debug_getinfo_prop_bool(thr, key, flags & mask);
47149 	}
47150 }
47151 
47152 /* Inspect a property using a virtual index into a conceptual property list
47153  * consisting of (1) all array part items from [0,a_size[ (even when above
47154  * .length) and (2) all entry part items from [0,e_next[.  Unused slots are
47155  * indicated using dvalue 'unused'.
47156  */
47157 DUK_LOCAL duk_bool_t duk__debug_getprop_index(duk_hthread *thr, duk_heap *heap, duk_hobject *h_obj, duk_uint_t idx) {
47158 	duk_uint_t a_size;
47159 	duk_tval *tv;
47160 	duk_hstring *h_key;
47161 	duk_hobject *h_getset;
47162 	duk_uint_t flags;
47163 
47164 	DUK_UNREF(heap);
47165 
47166 	a_size = DUK_HOBJECT_GET_ASIZE(h_obj);
47167 	if (idx < a_size) {
47168 		duk_debug_write_uint(thr, DUK_PROPDESC_FLAGS_WEC);
47169 		duk_debug_write_uint(thr, idx);
47170 		tv = DUK_HOBJECT_A_GET_VALUE_PTR(heap, h_obj, idx);
47171 		duk_debug_write_tval(thr, tv);
47172 		return 1;
47173 	}
47174 
47175 	idx -= a_size;
47176 	if (idx >= DUK_HOBJECT_GET_ENEXT(h_obj)) {
47177 		return 0;
47178 	}
47179 
47180 	h_key = DUK_HOBJECT_E_GET_KEY(heap, h_obj, idx);
47181 	if (h_key == NULL) {
47182 		duk_debug_write_uint(thr, 0);
47183 		duk_debug_write_null(thr);
47184 		duk_debug_write_unused(thr);
47185 		return 1;
47186 	}
47187 
47188 	flags = DUK_HOBJECT_E_GET_FLAGS(heap, h_obj, idx);
47189 	if (DUK_HSTRING_HAS_SYMBOL(h_key)) {
47190 		flags |= DUK_DBG_PROPFLAG_SYMBOL;
47191 	}
47192 	if (DUK_HSTRING_HAS_HIDDEN(h_key)) {
47193 		flags |= DUK_DBG_PROPFLAG_HIDDEN;
47194 	}
47195 	duk_debug_write_uint(thr, flags);
47196 	duk_debug_write_hstring(thr, h_key);
47197 	if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
47198 		h_getset = DUK_HOBJECT_E_GET_VALUE_GETTER(heap, h_obj, idx);
47199 		if (h_getset) {
47200 			duk_debug_write_hobject(thr, h_getset);
47201 		} else {
47202 			duk_debug_write_null(thr);
47203 		}
47204 		h_getset = DUK_HOBJECT_E_GET_VALUE_SETTER(heap, h_obj, idx);
47205 		if (h_getset) {
47206 			duk_debug_write_hobject(thr, h_getset);
47207 		} else {
47208 			duk_debug_write_null(thr);
47209 		}
47210 	} else {
47211 		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, h_obj, idx);
47212 		duk_debug_write_tval(thr, tv);
47213 	}
47214 	return 1;
47215 }
47216 
47217 DUK_LOCAL void duk__debug_handle_get_heap_obj_info(duk_hthread *thr, duk_heap *heap) {
47218 	duk_heaphdr *h;
47219 
47220 	DUK_D(DUK_DPRINT("debug command GetHeapObjInfo"));
47221 	DUK_UNREF(heap);
47222 
47223 	DUK_ASSERT(sizeof(duk__debug_getinfo_hstring_keys) / sizeof(const char *) == sizeof(duk__debug_getinfo_hstring_masks) / sizeof(duk_uint_t) - 1);
47224 	DUK_ASSERT(sizeof(duk__debug_getinfo_hobject_keys) / sizeof(const char *) == sizeof(duk__debug_getinfo_hobject_masks) / sizeof(duk_uint_t) - 1);
47225 	DUK_ASSERT(sizeof(duk__debug_getinfo_hbuffer_keys) / sizeof(const char *) == sizeof(duk__debug_getinfo_hbuffer_masks) / sizeof(duk_uint_t) - 1);
47226 
47227 	h = duk_debug_read_any_ptr(thr);
47228 	if (!h) {
47229 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid target");
47230 		return;
47231 	}
47232 
47233 	duk_debug_write_reply(thr);
47234 
47235 	/* As with all inspection code, we rely on the debug client providing
47236 	 * a valid, non-stale pointer: there's no portable way to safely
47237 	 * validate the pointer here.
47238 	 */
47239 
47240 	duk__debug_getinfo_flags_key(thr, "heapptr");
47241 	duk_debug_write_heapptr(thr, h);
47242 
47243 	/* XXX: comes out as signed now */
47244 	duk__debug_getinfo_prop_uint(thr, "heaphdr_flags", (duk_uint_t) DUK_HEAPHDR_GET_FLAGS(h));
47245 	duk__debug_getinfo_prop_uint(thr, "heaphdr_type", (duk_uint_t) DUK_HEAPHDR_GET_TYPE(h));
47246 #if defined(DUK_USE_REFERENCE_COUNTING)
47247 	duk__debug_getinfo_prop_uint(thr, "refcount", (duk_uint_t) DUK_HEAPHDR_GET_REFCOUNT(h));
47248 #endif
47249 #if 0 /* pruned */
47250 	duk__debug_getinfo_bitmask(thr,
47251 	                           duk__debug_getinfo_heaphdr_keys,
47252 	                           duk__debug_getinfo_heaphdr_masks,
47253 	                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
47254 #endif
47255 
47256 	switch (DUK_HEAPHDR_GET_TYPE(h)) {
47257 	case DUK_HTYPE_STRING: {
47258 		duk_hstring *h_str;
47259 
47260 		h_str = (duk_hstring *) h;
47261 		duk__debug_getinfo_bitmask(thr,
47262 		                           duk__debug_getinfo_hstring_keys,
47263 		                           duk__debug_getinfo_hstring_masks,
47264 		                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
47265 		duk__debug_getinfo_prop_uint(thr, "bytelen", (duk_uint_t) DUK_HSTRING_GET_BYTELEN(h_str));
47266 		duk__debug_getinfo_prop_uint(thr, "charlen", (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h_str));
47267 		duk__debug_getinfo_prop_uint(thr, "hash", (duk_uint_t) DUK_HSTRING_GET_HASH(h_str));
47268 		duk__debug_getinfo_flags_key(thr, "data");
47269 		duk_debug_write_hstring(thr, h_str);
47270 		break;
47271 	}
47272 	case DUK_HTYPE_OBJECT: {
47273 		duk_hobject *h_obj;
47274 		duk_hobject *h_proto;
47275 
47276 		h_obj = (duk_hobject *) h;
47277 		h_proto = DUK_HOBJECT_GET_PROTOTYPE(heap, h_obj);
47278 
47279 		/* duk_hobject specific fields. */
47280 		duk__debug_getinfo_bitmask(thr,
47281 		                           duk__debug_getinfo_hobject_keys,
47282 		                           duk__debug_getinfo_hobject_masks,
47283 		                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
47284 		duk__debug_getinfo_prop_uint(thr, "class_number", DUK_HOBJECT_GET_CLASS_NUMBER(h_obj));
47285 		duk__debug_getinfo_flags_key(thr, "class_name");
47286 		duk_debug_write_hstring(thr, DUK_HOBJECT_GET_CLASS_STRING(heap, h_obj));
47287 		duk__debug_getinfo_flags_key(thr, "prototype");
47288 		if (h_proto != NULL) {
47289 			duk_debug_write_hobject(thr, h_proto);
47290 		} else {
47291 			duk_debug_write_null(thr);
47292 		}
47293 		duk__debug_getinfo_flags_key(thr, "props");
47294 		duk_debug_write_pointer(thr, (void *) DUK_HOBJECT_GET_PROPS(heap, h_obj));
47295 		duk__debug_getinfo_prop_uint(thr, "e_size", (duk_uint_t) DUK_HOBJECT_GET_ESIZE(h_obj));
47296 		duk__debug_getinfo_prop_uint(thr, "e_next", (duk_uint_t) DUK_HOBJECT_GET_ENEXT(h_obj));
47297 		duk__debug_getinfo_prop_uint(thr, "a_size", (duk_uint_t) DUK_HOBJECT_GET_ASIZE(h_obj));
47298 		duk__debug_getinfo_prop_uint(thr, "h_size", (duk_uint_t) DUK_HOBJECT_GET_HSIZE(h_obj));
47299 
47300 		if (DUK_HOBJECT_IS_ARRAY(h_obj)) {
47301 			duk_harray *h_arr;
47302 			h_arr = (duk_harray *) h_obj;
47303 
47304 			duk__debug_getinfo_prop_uint(thr, "length", (duk_uint_t) h_arr->length);
47305 			duk__debug_getinfo_prop_bool(thr, "length_nonwritable", h_arr->length_nonwritable);
47306 		}
47307 
47308 		if (DUK_HOBJECT_IS_NATFUNC(h_obj)) {
47309 			duk_hnatfunc *h_fun;
47310 			h_fun = (duk_hnatfunc *) h_obj;
47311 
47312 			duk__debug_getinfo_prop_int(thr, "nargs", h_fun->nargs);
47313 			duk__debug_getinfo_prop_int(thr, "magic", h_fun->magic);
47314 			duk__debug_getinfo_prop_bool(thr, "varargs", h_fun->magic == DUK_HNATFUNC_NARGS_VARARGS);
47315 			/* Native function pointer may be different from a void pointer,
47316 			 * and we serialize it from memory directly now (no byte swapping etc).
47317 			 */
47318 			duk__debug_getinfo_flags_key(thr, "funcptr");
47319 			duk_debug_write_buffer(thr, (const char *) &h_fun->func, sizeof(h_fun->func));
47320 		}
47321 
47322 		if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
47323 			duk_hcompfunc *h_fun;
47324 			duk_hbuffer *h_buf;
47325 			duk_hobject *h_lexenv;
47326 			duk_hobject *h_varenv;
47327 			h_fun = (duk_hcompfunc *) h_obj;
47328 
47329 			duk__debug_getinfo_prop_int(thr, "nregs", h_fun->nregs);
47330 			duk__debug_getinfo_prop_int(thr, "nargs", h_fun->nargs);
47331 
47332 			duk__debug_getinfo_flags_key(thr, "lex_env");
47333 			h_lexenv = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, h_fun);
47334 			if (h_lexenv != NULL) {
47335 				duk_debug_write_hobject(thr, h_lexenv);
47336 			} else {
47337 				duk_debug_write_null(thr);
47338 			}
47339 			duk__debug_getinfo_flags_key(thr, "var_env");
47340 			h_varenv = DUK_HCOMPFUNC_GET_VARENV(thr->heap, h_fun);
47341 			if (h_varenv != NULL) {
47342 				duk_debug_write_hobject(thr, h_varenv);
47343 			} else {
47344 				duk_debug_write_null(thr);
47345 			}
47346 
47347 			duk__debug_getinfo_prop_uint(thr, "start_line", h_fun->start_line);
47348 			duk__debug_getinfo_prop_uint(thr, "end_line", h_fun->end_line);
47349 			h_buf = (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(thr->heap, h_fun);
47350 			if (h_buf != NULL) {
47351 				duk__debug_getinfo_flags_key(thr, "data");
47352 				duk_debug_write_heapptr(thr, (duk_heaphdr *) h_buf);
47353 			}
47354 		}
47355 
47356 		if (DUK_HOBJECT_IS_BOUNDFUNC(h_obj)) {
47357 			duk_hboundfunc *h_bfun;
47358 			h_bfun = (duk_hboundfunc *) (void *) h_obj;
47359 
47360 			duk__debug_getinfo_flags_key(thr, "target");
47361 			duk_debug_write_tval(thr, &h_bfun->target);
47362 			duk__debug_getinfo_flags_key(thr, "this_binding");
47363 			duk_debug_write_tval(thr, &h_bfun->this_binding);
47364 			duk__debug_getinfo_flags_key(thr, "nargs");
47365 			duk_debug_write_int(thr, h_bfun->nargs);
47366 			/* h_bfun->args not exposed now */
47367 		}
47368 
47369 		if (DUK_HOBJECT_IS_THREAD(h_obj)) {
47370 			/* XXX: Currently no inspection of threads, e.g. value stack, call
47371 			 * stack, catch stack, etc.
47372 			 */
47373 			duk_hthread *h_thr;
47374 			h_thr = (duk_hthread *) h_obj;
47375 			DUK_UNREF(h_thr);
47376 		}
47377 
47378 		if (DUK_HOBJECT_IS_DECENV(h_obj)) {
47379 			duk_hdecenv *h_env;
47380 			h_env = (duk_hdecenv *) h_obj;
47381 
47382 			duk__debug_getinfo_flags_key(thr, "thread");
47383 			duk_debug_write_heapptr(thr, (duk_heaphdr *) (h_env->thread));
47384 			duk__debug_getinfo_flags_key(thr, "varmap");
47385 			duk_debug_write_heapptr(thr, (duk_heaphdr *) (h_env->varmap));
47386 			duk__debug_getinfo_prop_uint(thr, "regbase", (duk_uint_t) h_env->regbase_byteoff);
47387 		}
47388 
47389 		if (DUK_HOBJECT_IS_OBJENV(h_obj)) {
47390 			duk_hobjenv *h_env;
47391 			h_env = (duk_hobjenv *) h_obj;
47392 
47393 			duk__debug_getinfo_flags_key(thr, "target");
47394 			duk_debug_write_heapptr(thr, (duk_heaphdr *) (h_env->target));
47395 			duk__debug_getinfo_prop_bool(thr, "has_this", h_env->has_this);
47396 		}
47397 
47398 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
47399 		if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
47400 			duk_hbufobj *h_bufobj;
47401 			h_bufobj = (duk_hbufobj *) h_obj;
47402 
47403 			duk__debug_getinfo_prop_uint(thr, "slice_offset", h_bufobj->offset);
47404 			duk__debug_getinfo_prop_uint(thr, "slice_length", h_bufobj->length);
47405 			duk__debug_getinfo_prop_uint(thr, "elem_shift", (duk_uint_t) h_bufobj->shift);
47406 			duk__debug_getinfo_prop_uint(thr, "elem_type", (duk_uint_t) h_bufobj->elem_type);
47407 			duk__debug_getinfo_prop_bool(thr, "is_typedarray", (duk_uint_t) h_bufobj->is_typedarray);
47408 			if (h_bufobj->buf != NULL) {
47409 				duk__debug_getinfo_flags_key(thr, "buffer");
47410 				duk_debug_write_heapptr(thr, (duk_heaphdr *) h_bufobj->buf);
47411 			}
47412 		}
47413 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
47414 		break;
47415 	}
47416 	case DUK_HTYPE_BUFFER: {
47417 		duk_hbuffer *h_buf;
47418 
47419 		h_buf = (duk_hbuffer *) h;
47420 		duk__debug_getinfo_bitmask(thr,
47421 		                           duk__debug_getinfo_hbuffer_keys,
47422 		                           duk__debug_getinfo_hbuffer_masks,
47423 		                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
47424 		duk__debug_getinfo_prop_uint(thr, "size", (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_buf));
47425 		duk__debug_getinfo_flags_key(thr, "dataptr");
47426 		duk_debug_write_pointer(thr, (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf));
47427 		duk__debug_getinfo_flags_key(thr, "data");
47428 		duk_debug_write_hbuffer(thr, h_buf);  /* tolerates NULL h_buf */
47429 		break;
47430 	}
47431 	default: {
47432 		/* Since we already started writing the reply, just emit nothing. */
47433 		DUK_D(DUK_DPRINT("inspect target pointer has invalid heaphdr type"));
47434 	}
47435 	}
47436 
47437 	duk_debug_write_eom(thr);
47438 }
47439 
47440 DUK_LOCAL void duk__debug_handle_get_obj_prop_desc(duk_hthread *thr, duk_heap *heap) {
47441 	duk_heaphdr *h;
47442 	duk_hobject *h_obj;
47443 	duk_hstring *h_key;
47444 	duk_propdesc desc;
47445 
47446 	DUK_D(DUK_DPRINT("debug command GetObjPropDesc"));
47447 	DUK_UNREF(heap);
47448 
47449 	h = duk_debug_read_any_ptr(thr);
47450 	if (!h) {
47451 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid target");
47452 		return;
47453 	}
47454 	h_key = duk_debug_read_hstring(thr);
47455 	if (h == NULL || DUK_HEAPHDR_GET_TYPE(h) != DUK_HTYPE_OBJECT || h_key == NULL) {
47456 		goto fail_args;
47457 	}
47458 	h_obj = (duk_hobject *) h;
47459 
47460 	if (duk_hobject_get_own_propdesc(thr, h_obj, h_key, &desc, 0 /*flags*/)) {
47461 		duk_int_t virtual_idx;
47462 		duk_bool_t rc;
47463 
47464 		/* To use the shared helper need the virtual index. */
47465 		DUK_ASSERT(desc.e_idx >= 0 || desc.a_idx >= 0);
47466 		virtual_idx = (desc.a_idx >= 0 ? desc.a_idx :
47467 		               (duk_int_t) DUK_HOBJECT_GET_ASIZE(h_obj) + desc.e_idx);
47468 
47469 		duk_debug_write_reply(thr);
47470 		rc = duk__debug_getprop_index(thr, heap, h_obj, (duk_uint_t) virtual_idx);
47471 		DUK_ASSERT(rc == 1);
47472 		DUK_UNREF(rc);
47473 		duk_debug_write_eom(thr);
47474 	} else {
47475 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "not found");
47476 	}
47477 	return;
47478 
47479  fail_args:
47480 	duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid args");
47481 }
47482 
47483 DUK_LOCAL void duk__debug_handle_get_obj_prop_desc_range(duk_hthread *thr, duk_heap *heap) {
47484 	duk_heaphdr *h;
47485 	duk_hobject *h_obj;
47486 	duk_uint_t idx, idx_start, idx_end;
47487 
47488 	DUK_D(DUK_DPRINT("debug command GetObjPropDescRange"));
47489 	DUK_UNREF(heap);
47490 
47491 	h = duk_debug_read_any_ptr(thr);
47492 	idx_start = (duk_uint_t) duk_debug_read_int(thr);
47493 	idx_end = (duk_uint_t) duk_debug_read_int(thr);
47494 	if (h == NULL || DUK_HEAPHDR_GET_TYPE(h) != DUK_HTYPE_OBJECT) {
47495 		goto fail_args;
47496 	}
47497 	h_obj = (duk_hobject *) h;
47498 
47499 	/* The index range space is conceptually the array part followed by the
47500 	 * entry part.  Unlike normal enumeration all slots are exposed here as
47501 	 * is and return 'unused' if the slots are not in active use.  In particular
47502 	 * the array part is included for the full a_size regardless of what the
47503 	 * array .length is.
47504 	 */
47505 
47506 	duk_debug_write_reply(thr);
47507 	for (idx = idx_start; idx < idx_end; idx++) {
47508 		if (!duk__debug_getprop_index(thr, heap, h_obj, idx)) {
47509 			break;
47510 		}
47511 	}
47512 	duk_debug_write_eom(thr);
47513 	return;
47514 
47515  fail_args:
47516 	duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid args");
47517 }
47518 
47519 #endif  /* DUK_USE_DEBUGGER_INSPECT */
47520 
47521 /*
47522  *  Process incoming debug requests
47523  *
47524  *  Individual request handlers can push temporaries on the value stack and
47525  *  rely on duk__debug_process_message() to restore the value stack top
47526  *  automatically.
47527  */
47528 
47529 /* Process one debug message.  Automatically restore value stack top to its
47530  * entry value, so that individual message handlers don't need exact value
47531  * stack handling which is convenient.
47532  */
47533 DUK_LOCAL void duk__debug_process_message(duk_hthread *thr) {
47534 	duk_heap *heap;
47535 	duk_uint8_t x;
47536 	duk_int32_t cmd;
47537 	duk_idx_t entry_top;
47538 
47539 	DUK_ASSERT(thr != NULL);
47540 	heap = thr->heap;
47541 	DUK_ASSERT(heap != NULL);
47542 
47543 	entry_top = duk_get_top(thr);
47544 
47545 	x = duk_debug_read_byte(thr);
47546 	switch (x) {
47547 	case DUK_DBG_IB_REQUEST: {
47548 		cmd = duk_debug_read_int(thr);
47549 		switch (cmd) {
47550 		case DUK_DBG_CMD_BASICINFO: {
47551 			duk__debug_handle_basic_info(thr, heap);
47552 			break;
47553 		}
47554 		case DUK_DBG_CMD_TRIGGERSTATUS: {
47555 			duk__debug_handle_trigger_status(thr, heap);
47556 			break;
47557 		}
47558 		case DUK_DBG_CMD_PAUSE: {
47559 			duk__debug_handle_pause(thr, heap);
47560 			break;
47561 		}
47562 		case DUK_DBG_CMD_RESUME: {
47563 			duk__debug_handle_resume(thr, heap);
47564 			break;
47565 		}
47566 		case DUK_DBG_CMD_STEPINTO:
47567 		case DUK_DBG_CMD_STEPOVER:
47568 		case DUK_DBG_CMD_STEPOUT: {
47569 			duk__debug_handle_step(thr, heap, cmd);
47570 			break;
47571 		}
47572 		case DUK_DBG_CMD_LISTBREAK: {
47573 			duk__debug_handle_list_break(thr, heap);
47574 			break;
47575 		}
47576 		case DUK_DBG_CMD_ADDBREAK: {
47577 			duk__debug_handle_add_break(thr, heap);
47578 			break;
47579 		}
47580 		case DUK_DBG_CMD_DELBREAK: {
47581 			duk__debug_handle_del_break(thr, heap);
47582 			break;
47583 		}
47584 		case DUK_DBG_CMD_GETVAR: {
47585 			duk__debug_handle_get_var(thr, heap);
47586 			break;
47587 		}
47588 		case DUK_DBG_CMD_PUTVAR: {
47589 			duk__debug_handle_put_var(thr, heap);
47590 			break;
47591 		}
47592 		case DUK_DBG_CMD_GETCALLSTACK: {
47593 			duk__debug_handle_get_call_stack(thr, heap);
47594 			break;
47595 		}
47596 		case DUK_DBG_CMD_GETLOCALS: {
47597 			duk__debug_handle_get_locals(thr, heap);
47598 			break;
47599 		}
47600 		case DUK_DBG_CMD_EVAL: {
47601 			duk__debug_handle_eval(thr, heap);
47602 			break;
47603 		}
47604 		case DUK_DBG_CMD_DETACH: {
47605 			/* The actual detached_cb call is postponed to message loop so
47606 			 * we don't need any special precautions here (just skip to EOM
47607 			 * on the already closed connection).
47608 			 */
47609 			duk__debug_handle_detach(thr, heap);
47610 			break;
47611 		}
47612 #if defined(DUK_USE_DEBUGGER_DUMPHEAP)
47613 		case DUK_DBG_CMD_DUMPHEAP: {
47614 			duk__debug_handle_dump_heap(thr, heap);
47615 			break;
47616 		}
47617 #endif  /* DUK_USE_DEBUGGER_DUMPHEAP */
47618 		case DUK_DBG_CMD_GETBYTECODE: {
47619 			duk__debug_handle_get_bytecode(thr, heap);
47620 			break;
47621 		}
47622 		case DUK_DBG_CMD_APPREQUEST: {
47623 			duk__debug_handle_apprequest(thr, heap);
47624 			break;
47625 		}
47626 #if defined(DUK_USE_DEBUGGER_INSPECT)
47627 		case DUK_DBG_CMD_GETHEAPOBJINFO: {
47628 			duk__debug_handle_get_heap_obj_info(thr, heap);
47629 			break;
47630 		}
47631 		case DUK_DBG_CMD_GETOBJPROPDESC: {
47632 			duk__debug_handle_get_obj_prop_desc(thr, heap);
47633 			break;
47634 		}
47635 		case DUK_DBG_CMD_GETOBJPROPDESCRANGE: {
47636 			duk__debug_handle_get_obj_prop_desc_range(thr, heap);
47637 			break;
47638 		}
47639 #endif  /* DUK_USE_DEBUGGER_INSPECT */
47640 		default: {
47641 			DUK_D(DUK_DPRINT("debug command unsupported: %d", (int) cmd));
47642 			duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, "unsupported command");
47643 		}
47644 		}  /* switch cmd */
47645 		break;
47646 	}
47647 	case DUK_DBG_IB_REPLY: {
47648 		DUK_D(DUK_DPRINT("debug reply, skipping"));
47649 		break;
47650 	}
47651 	case DUK_DBG_IB_ERROR: {
47652 		DUK_D(DUK_DPRINT("debug error, skipping"));
47653 		break;
47654 	}
47655 	case DUK_DBG_IB_NOTIFY: {
47656 		DUK_D(DUK_DPRINT("debug notify, skipping"));
47657 		break;
47658 	}
47659 	default: {
47660 		DUK_D(DUK_DPRINT("invalid initial byte, drop connection: %d", (int) x));
47661 		goto fail;
47662 	}
47663 	}  /* switch initial byte */
47664 
47665 	DUK_ASSERT(duk_get_top(thr) >= entry_top);
47666 	duk_set_top(thr, entry_top);
47667 	duk__debug_skip_to_eom(thr);
47668 	return;
47669 
47670  fail:
47671 	DUK_ASSERT(duk_get_top(thr) >= entry_top);
47672 	duk_set_top(thr, entry_top);
47673 	DUK__SET_CONN_BROKEN(thr, 1);
47674 	return;
47675 }
47676 
47677 DUK_LOCAL void duk__check_resend_status(duk_hthread *thr) {
47678 	if (thr->heap->dbg_read_cb != NULL && thr->heap->dbg_state_dirty) {
47679 		duk_debug_send_status(thr);
47680 		thr->heap->dbg_state_dirty = 0;
47681 	}
47682 }
47683 
47684 DUK_INTERNAL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t no_block) {
47685 #if defined(DUK_USE_ASSERTIONS)
47686 	duk_idx_t entry_top;
47687 #endif
47688 	duk_bool_t retval = 0;
47689 
47690 	DUK_ASSERT(thr != NULL);
47691 	DUK_ASSERT(thr->heap != NULL);
47692 #if defined(DUK_USE_ASSERTIONS)
47693 	entry_top = duk_get_top(thr);
47694 #endif
47695 
47696 	DUK_D(DUK_DPRINT("process debug messages: read_cb=%s, no_block=%ld, detaching=%ld, processing=%ld",
47697 	                 thr->heap->dbg_read_cb ? "not NULL" : "NULL", (long) no_block,
47698 	                 (long) thr->heap->dbg_detaching, (long) thr->heap->dbg_processing));
47699 	DUK_DD(DUK_DDPRINT("top at entry: %ld", (long) duk_get_top(thr)));
47700 
47701 	/* thr->heap->dbg_detaching may be != 0 if a debugger write outside
47702 	 * the message loop caused a transport error and detach1() to run.
47703 	 */
47704 	DUK_ASSERT(thr->heap->dbg_detaching == 0 || thr->heap->dbg_detaching == 1);
47705 	DUK_ASSERT(thr->heap->dbg_processing == 0);
47706 	thr->heap->dbg_processing = 1;
47707 
47708 	/* Ensure dirty state causes a Status even if never process any
47709 	 * messages.  This is expected by the bytecode executor when in
47710 	 * the running state.
47711 	 */
47712 	duk__check_resend_status(thr);
47713 
47714 	for (;;) {
47715 		/* Process messages until we're no longer paused or we peek
47716 		 * and see there's nothing to read right now.
47717 		 */
47718 		DUK_DD(DUK_DDPRINT("top at loop top: %ld", (long) duk_get_top(thr)));
47719 		DUK_ASSERT(thr->heap->dbg_processing == 1);
47720 
47721 		while (thr->heap->dbg_read_cb == NULL && thr->heap->dbg_detaching) {
47722 			/* Detach is pending; can be triggered from outside the
47723 			 * debugger loop (e.g. Status notify write error) or by
47724 			 * previous message handling.  Call detached callback
47725 			 * here, in a controlled state, to ensure a possible
47726 			 * reattach inside the detached_cb is handled correctly.
47727 			 *
47728 			 * Recheck for detach in a while loop: an immediate
47729 			 * reattach involves a call to duk_debugger_attach()
47730 			 * which writes a debugger handshake line immediately
47731 			 * inside the API call.  If the transport write fails
47732 			 * for that handshake, we can immediately end up in a
47733 			 * "transport broken, detaching" case several times here.
47734 			 * Loop back until we're either cleanly attached or
47735 			 * fully detached.
47736 			 *
47737 			 * NOTE: Reset dbg_processing = 1 forcibly, in case we
47738 			 * re-attached; duk_debugger_attach() sets dbg_processing
47739 			 * to 0 at the moment.
47740 			 */
47741 
47742 			DUK_D(DUK_DPRINT("detach pending (dbg_read_cb == NULL, dbg_detaching != 0), call detach2"));
47743 
47744 			duk__debug_do_detach2(thr->heap);
47745 			thr->heap->dbg_processing = 1;  /* may be set to 0 by duk_debugger_attach() inside callback */
47746 
47747 			DUK_D(DUK_DPRINT("after detach2 (and possible reattach): dbg_read_cb=%s, dbg_detaching=%ld",
47748 			                 thr->heap->dbg_read_cb ? "not NULL" : "NULL", (long) thr->heap->dbg_detaching));
47749 		}
47750 		DUK_ASSERT(thr->heap->dbg_detaching == 0);  /* true even with reattach */
47751 		DUK_ASSERT(thr->heap->dbg_processing == 1);  /* even after a detach and possible reattach */
47752 
47753 		if (thr->heap->dbg_read_cb == NULL) {
47754 			DUK_D(DUK_DPRINT("debug connection broken (and not detaching), stop processing messages"));
47755 			break;
47756 		}
47757 
47758 		if (!DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) || no_block) {
47759 			if (!duk_debug_read_peek(thr)) {
47760 				/* Note: peek cannot currently trigger a detach
47761 				 * so the dbg_detaching == 0 assert outside the
47762 				 * loop is correct.
47763 				 */
47764 				DUK_D(DUK_DPRINT("processing debug message, peek indicated no data, stop processing messages"));
47765 				break;
47766 			}
47767 			DUK_D(DUK_DPRINT("processing debug message, peek indicated there is data, handle it"));
47768 		} else {
47769 			DUK_D(DUK_DPRINT("paused, process debug message, blocking if necessary"));
47770 		}
47771 
47772 		duk__check_resend_status(thr);
47773 		duk__debug_process_message(thr);
47774 		duk__check_resend_status(thr);
47775 
47776 		retval = 1;  /* processed one or more messages */
47777 	}
47778 
47779 	DUK_ASSERT(thr->heap->dbg_detaching == 0);
47780 	DUK_ASSERT(thr->heap->dbg_processing == 1);
47781 	thr->heap->dbg_processing = 0;
47782 
47783 	/* As an initial implementation, read flush after exiting the message
47784 	 * loop.  If transport is broken, this is a no-op (with debug logs).
47785 	 */
47786 	duk_debug_read_flush(thr);  /* this cannot initiate a detach */
47787 	DUK_ASSERT(thr->heap->dbg_detaching == 0);
47788 
47789 	DUK_DD(DUK_DDPRINT("top at exit: %ld", (long) duk_get_top(thr)));
47790 
47791 #if defined(DUK_USE_ASSERTIONS)
47792 	/* Easy to get wrong, so assert for it. */
47793 	DUK_ASSERT(entry_top == duk_get_top(thr));
47794 #endif
47795 
47796 	return retval;
47797 }
47798 
47799 /*
47800  *  Halt execution helper
47801  */
47802 
47803 /* Halt execution and enter a debugger message loop until execution is resumed
47804  * by the client.  PC for the current activation may be temporarily decremented
47805  * so that the "current" instruction will be shown by the client.  This helper
47806  * is callable from anywhere, also outside bytecode executor.
47807  */
47808 
47809 DUK_INTERNAL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev_pc) {
47810 	duk_activation *act;
47811 	duk_hcompfunc *fun;
47812 	duk_instr_t *old_pc = NULL;
47813 
47814 	DUK_ASSERT(thr != NULL);
47815 	DUK_ASSERT(thr->heap != NULL);
47816 	DUK_ASSERT(duk_debug_is_attached(thr->heap));
47817 	DUK_ASSERT(thr->heap->dbg_processing == 0);
47818 	DUK_ASSERT(!duk_debug_is_paused(thr->heap));
47819 
47820 	duk_debug_set_paused(thr->heap);
47821 
47822 	act = thr->callstack_curr;
47823 
47824 	/* NOTE: act may be NULL if an error is thrown outside of any activation,
47825 	 * which may happen in the case of, e.g. syntax errors.
47826 	 */
47827 
47828 	/* Decrement PC if that was requested, this requires a PC sync. */
47829 	if (act != NULL) {
47830 		duk_hthread_sync_currpc(thr);
47831 		old_pc = act->curr_pc;
47832 		fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
47833 
47834 		/* Short circuit if is safe: if act->curr_pc != NULL, 'fun' is
47835 		 * guaranteed to be a non-NULL ECMAScript function.
47836 		 */
47837 		DUK_ASSERT(act->curr_pc == NULL ||
47838 		           (fun != NULL && DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun)));
47839 		if (use_prev_pc &&
47840 		    act->curr_pc != NULL &&
47841 		    act->curr_pc > DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, fun)) {
47842 			act->curr_pc--;
47843 		}
47844 	}
47845 
47846 	/* Process debug messages until we are no longer paused. */
47847 
47848 	/* NOTE: This is a bit fragile.  It's important to ensure that
47849 	 * duk_debug_process_messages() never throws an error or
47850 	 * act->curr_pc will never be reset.
47851 	 */
47852 
47853 	thr->heap->dbg_state_dirty = 1;
47854 	while (DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap)) {
47855 		DUK_ASSERT(duk_debug_is_attached(thr->heap));
47856 		DUK_ASSERT(thr->heap->dbg_processing == 0);
47857 		duk_debug_process_messages(thr, 0 /*no_block*/);
47858 	}
47859 
47860 	/* XXX: Decrementing and restoring act->curr_pc works now, but if the
47861 	 * debugger message loop gains the ability to adjust the current PC
47862 	 * (e.g. a forced jump) restoring the PC here will break.  Another
47863 	 * approach would be to use a state flag for the "decrement 1 from
47864 	 * topmost activation's PC" and take it into account whenever dealing
47865 	 * with PC values.
47866 	 */
47867 	if (act != NULL) {
47868 		act->curr_pc = old_pc;  /* restore PC */
47869 	}
47870 }
47871 
47872 /*
47873  *  Breakpoint management
47874  */
47875 
47876 DUK_INTERNAL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstring *filename, duk_uint32_t line) {
47877 	duk_heap *heap;
47878 	duk_breakpoint *b;
47879 
47880 	/* Caller must trigger recomputation of active breakpoint list.  To
47881 	 * ensure stale values are not used if that doesn't happen, clear the
47882 	 * active breakpoint list here.
47883 	 */
47884 
47885 	DUK_ASSERT(thr != NULL);
47886 	DUK_ASSERT(filename != NULL);
47887 	heap = thr->heap;
47888 	DUK_ASSERT(heap != NULL);
47889 
47890 	if (heap->dbg_breakpoint_count >= DUK_HEAP_MAX_BREAKPOINTS) {
47891 		DUK_D(DUK_DPRINT("failed to add breakpoint for %O:%ld, all breakpoint slots used",
47892 		                 (duk_heaphdr *) filename, (long) line));
47893 		return -1;
47894 	}
47895 	heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
47896 	b = heap->dbg_breakpoints + (heap->dbg_breakpoint_count++);
47897 	b->filename = filename;
47898 	b->line = line;
47899 	DUK_HSTRING_INCREF(thr, filename);
47900 
47901 	return (duk_small_int_t) (heap->dbg_breakpoint_count - 1);  /* index */
47902 }
47903 
47904 DUK_INTERNAL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_uint_t breakpoint_index) {
47905 	duk_heap *heap;
47906 	duk_hstring *h;
47907 	duk_breakpoint *b;
47908 	duk_size_t move_size;
47909 
47910 	/* Caller must trigger recomputation of active breakpoint list.  To
47911 	 * ensure stale values are not used if that doesn't happen, clear the
47912 	 * active breakpoint list here.
47913 	 */
47914 
47915 	DUK_ASSERT(thr != NULL);
47916 	heap = thr->heap;
47917 	DUK_ASSERT(heap != NULL);
47918 	DUK_ASSERT(duk_debug_is_attached(thr->heap));
47919 	DUK_ASSERT_DISABLE(breakpoint_index >= 0);  /* unsigned */
47920 
47921 	if (breakpoint_index >= heap->dbg_breakpoint_count) {
47922 		DUK_D(DUK_DPRINT("invalid breakpoint index: %ld", (long) breakpoint_index));
47923 		return 0;
47924 	}
47925 	b = heap->dbg_breakpoints + breakpoint_index;
47926 
47927 	h = b->filename;
47928 	DUK_ASSERT(h != NULL);
47929 
47930 	move_size = sizeof(duk_breakpoint) * (heap->dbg_breakpoint_count - breakpoint_index - 1);
47931 	duk_memmove((void *) b,
47932 	            (const void *) (b + 1),
47933 	            (size_t) move_size);
47934 
47935 	heap->dbg_breakpoint_count--;
47936 	heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
47937 
47938 	DUK_HSTRING_DECREF(thr, h);  /* side effects */
47939 	DUK_UNREF(h);  /* w/o refcounting */
47940 
47941 	/* Breakpoint entries above the used area are left as garbage. */
47942 
47943 	return 1;
47944 }
47945 
47946 /*
47947  *  Misc state management
47948  */
47949 
47950 DUK_INTERNAL duk_bool_t duk_debug_is_attached(duk_heap *heap) {
47951 	return (heap->dbg_read_cb != NULL);
47952 }
47953 
47954 DUK_INTERNAL duk_bool_t duk_debug_is_paused(duk_heap *heap) {
47955 	return (DUK_HEAP_HAS_DEBUGGER_PAUSED(heap) != 0);
47956 }
47957 
47958 DUK_INTERNAL void duk_debug_set_paused(duk_heap *heap) {
47959 	if (duk_debug_is_paused(heap)) {
47960 		DUK_D(DUK_DPRINT("trying to set paused state when already paused, ignoring"));
47961 	} else {
47962 		DUK_HEAP_SET_DEBUGGER_PAUSED(heap);
47963 		heap->dbg_state_dirty = 1;
47964 		duk_debug_clear_pause_state(heap);
47965 		DUK_ASSERT(heap->ms_running == 0);  /* debugger can't be triggered within mark-and-sweep */
47966 		heap->ms_running = 2;  /* prevent mark-and-sweep, prevent refzero queueing */
47967 		heap->ms_prevent_count++;
47968 		DUK_ASSERT(heap->ms_prevent_count != 0);  /* Wrap. */
47969 		DUK_ASSERT(heap->heap_thread != NULL);
47970 	}
47971 }
47972 
47973 DUK_INTERNAL void duk_debug_clear_paused(duk_heap *heap) {
47974 	if (duk_debug_is_paused(heap)) {
47975 		DUK_HEAP_CLEAR_DEBUGGER_PAUSED(heap);
47976 		heap->dbg_state_dirty = 1;
47977 		duk_debug_clear_pause_state(heap);
47978 		DUK_ASSERT(heap->ms_running == 2);
47979 		DUK_ASSERT(heap->ms_prevent_count > 0);
47980 		heap->ms_prevent_count--;
47981 		heap->ms_running = 0;
47982 		DUK_ASSERT(heap->heap_thread != NULL);
47983 	} else {
47984 		DUK_D(DUK_DPRINT("trying to clear paused state when not paused, ignoring"));
47985 	}
47986 }
47987 
47988 DUK_INTERNAL void duk_debug_clear_pause_state(duk_heap *heap) {
47989 	heap->dbg_pause_flags = 0;
47990 	heap->dbg_pause_act = NULL;
47991 	heap->dbg_pause_startline = 0;
47992 }
47993 
47994 #else  /* DUK_USE_DEBUGGER_SUPPORT */
47995 
47996 /* No debugger support. */
47997 
47998 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
47999 
48000 /* automatic undefs */
48001 #undef DUK__DBG_TPORT_ENTER
48002 #undef DUK__DBG_TPORT_EXIT
48003 #undef DUK__SET_CONN_BROKEN
48004 /*
48005  *  Augmenting errors at their creation site and their throw site.
48006  *
48007  *  When errors are created, traceback data is added by built-in code
48008  *  and a user error handler (if defined) can process or replace the
48009  *  error.  Similarly, when errors are thrown, a user error handler
48010  *  (if defined) can process or replace the error.
48011  *
48012  *  Augmentation and other processing at error creation time is nice
48013  *  because an error is only created once, but it may be thrown and
48014  *  rethrown multiple times.  User error handler registered for processing
48015  *  an error at its throw site must be careful to handle rethrowing in
48016  *  a useful manner.
48017  *
48018  *  Error augmentation may throw an internal error (e.g. alloc error).
48019  *
48020  *  ECMAScript allows throwing any values, so all values cannot be
48021  *  augmented.  Currently, the built-in augmentation at error creation
48022  *  only augments error values which are Error instances (= have the
48023  *  built-in Error.prototype in their prototype chain) and are also
48024  *  extensible.  User error handlers have no limitations in this respect.
48025  */
48026 
48027 /* #include duk_internal.h -> already included */
48028 
48029 /*
48030  *  Helper for calling a user error handler.
48031  *
48032  *  'thr' must be the currently active thread; the error handler is called
48033  *  in its context.  The valstack of 'thr' must have the error value on
48034  *  top, and will be replaced by another error value based on the return
48035  *  value of the error handler.
48036  *
48037  *  The helper calls duk_handle_call() recursively in protected mode.
48038  *  Before that call happens, no longjmps should happen; as a consequence,
48039  *  we must assume that the valstack contains enough temporary space for
48040  *  arguments and such.
48041  *
48042  *  While the error handler runs, any errors thrown will not trigger a
48043  *  recursive error handler call (this is implemented using a heap level
48044  *  flag which will "follow" through any coroutines resumed inside the
48045  *  error handler).  If the error handler is not callable or throws an
48046  *  error, the resulting error replaces the original error (for Duktape
48047  *  internal errors, duk_error_throw.c further substitutes this error with
48048  *  a DoubleError which is not ideal).  This would be easy to change and
48049  *  even signal to the caller.
48050  *
48051  *  The user error handler is stored in 'Duktape.errCreate' or
48052  *  'Duktape.errThrow' depending on whether we're augmenting the error at
48053  *  creation or throw time.  There are several alternatives to this approach,
48054  *  see doc/error-objects.rst for discussion.
48055  *
48056  *  Note: since further longjmp()s may occur while calling the error handler
48057  *  (for many reasons, e.g. a labeled 'break' inside the handler), the
48058  *  caller can make no assumptions on the thr->heap->lj state after the
48059  *  call (this affects especially duk_error_throw.c).  This is not an issue
48060  *  as long as the caller writes to the lj state only after the error handler
48061  *  finishes.
48062  */
48063 
48064 #if defined(DUK_USE_ERRTHROW) || defined(DUK_USE_ERRCREATE)
48065 DUK_LOCAL void duk__err_augment_user(duk_hthread *thr, duk_small_uint_t stridx_cb) {
48066 	duk_tval *tv_hnd;
48067 	duk_int_t rc;
48068 
48069 	DUK_ASSERT(thr != NULL);
48070 	DUK_ASSERT(thr->heap != NULL);
48071 	DUK_ASSERT_STRIDX_VALID(stridx_cb);
48072 
48073 	if (thr->heap->augmenting_error) {
48074 		DUK_D(DUK_DPRINT("recursive call to error augmentation, ignore"));
48075 		return;
48076 	}
48077 
48078 	/*
48079 	 *  Check whether or not we have an error handler.
48080 	 *
48081 	 *  We must be careful of not triggering an error when looking up the
48082 	 *  property.  For instance, if the property is a getter, we don't want
48083 	 *  to call it, only plain values are allowed.  The value, if it exists,
48084 	 *  is not checked.  If the value is not a function, a TypeError happens
48085 	 *  when it is called and that error replaces the original one.
48086 	 */
48087 
48088 	DUK_ASSERT_VALSTACK_SPACE(thr, 4);  /* 3 entries actually needed below */
48089 
48090 	/* [ ... errval ] */
48091 
48092 	if (thr->builtins[DUK_BIDX_DUKTAPE] == NULL) {
48093 		/* When creating built-ins, some of the built-ins may not be set
48094 		 * and we want to tolerate that when throwing errors.
48095 		 */
48096 		DUK_DD(DUK_DDPRINT("error occurred when DUK_BIDX_DUKTAPE is NULL, ignoring"));
48097 		return;
48098 	}
48099 	tv_hnd = duk_hobject_find_entry_tval_ptr_stridx(thr->heap,
48100 	                                                thr->builtins[DUK_BIDX_DUKTAPE],
48101 	                                                stridx_cb);
48102 	if (tv_hnd == NULL) {
48103 		DUK_DD(DUK_DDPRINT("error handler does not exist or is not a plain value: %!T",
48104 		                   (duk_tval *) tv_hnd));
48105 		return;
48106 	}
48107 	DUK_DDD(DUK_DDDPRINT("error handler dump (callability not checked): %!T",
48108 	                     (duk_tval *) tv_hnd));
48109 	duk_push_tval(thr, tv_hnd);
48110 
48111 	/* [ ... errval errhandler ] */
48112 
48113 	duk_insert(thr, -2);  /* -> [ ... errhandler errval ] */
48114 	duk_push_undefined(thr);
48115 	duk_insert(thr, -2);  /* -> [ ... errhandler undefined(= this) errval ] */
48116 
48117 	/* [ ... errhandler undefined errval ] */
48118 
48119 	/*
48120 	 *  heap->augmenting_error prevents recursive re-entry and also causes
48121 	 *  call handling to use a larger (but not unbounded) call stack limit
48122 	 *  for the duration of error augmentation.
48123 	 *
48124 	 *  We ignore errors now: a success return and an error value both
48125 	 *  replace the original error value.  (This would be easy to change.)
48126 	 */
48127 
48128 	DUK_ASSERT(thr->heap->augmenting_error == 0);
48129 	thr->heap->augmenting_error = 1;
48130 
48131 	rc = duk_pcall_method(thr, 1);
48132 	DUK_UNREF(rc);  /* no need to check now: both success and error are OK */
48133 
48134 	DUK_ASSERT(thr->heap->augmenting_error == 1);
48135 	thr->heap->augmenting_error = 0;
48136 
48137 	/* [ ... errval ] */
48138 }
48139 #endif  /* DUK_USE_ERRTHROW || DUK_USE_ERRCREATE */
48140 
48141 /*
48142  *  Add ._Tracedata to an error on the stack top.
48143  */
48144 
48145 #if defined(DUK_USE_TRACEBACKS)
48146 DUK_LOCAL void duk__add_traceback(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_small_uint_t flags) {
48147 	duk_activation *act;
48148 	duk_int_t depth;
48149 	duk_int_t arr_size;
48150 	duk_tval *tv;
48151 	duk_hstring *s;
48152 	duk_uint32_t u32;
48153 	duk_double_t d;
48154 
48155 	DUK_ASSERT(thr != NULL);
48156 	DUK_ASSERT(thr_callstack != NULL);
48157 
48158 	/* [ ... error ] */
48159 
48160 	/*
48161 	 *  The traceback format is pretty arcane in an attempt to keep it compact
48162 	 *  and cheap to create.  It may change arbitrarily from version to version.
48163 	 *  It should be decoded/accessed through version specific accessors only.
48164 	 *
48165 	 *  See doc/error-objects.rst.
48166 	 */
48167 
48168 	DUK_DDD(DUK_DDDPRINT("adding traceback to object: %!T",
48169 	                     (duk_tval *) duk_get_tval(thr, -1)));
48170 
48171 	/* Preallocate array to correct size, so that we can just write out
48172 	 * the _Tracedata values into the array part.
48173 	 */
48174 	act = thr->callstack_curr;
48175 	depth = DUK_USE_TRACEBACK_DEPTH;
48176 	DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX);  /* callstack limits */
48177 	if (depth > (duk_int_t) thr_callstack->callstack_top) {
48178 		depth = (duk_int_t) thr_callstack->callstack_top;
48179 	}
48180 	if (depth > 0) {
48181 		if (flags & DUK_AUGMENT_FLAG_SKIP_ONE) {
48182 			DUK_ASSERT(act != NULL);
48183 			act = act->parent;
48184 			depth--;
48185 		}
48186 	}
48187 	arr_size = depth * 2;
48188 	if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
48189 		arr_size += 2;
48190 	}
48191 	if (c_filename) {
48192 		/* We need the C filename to be interned before getting the
48193 		 * array part pointer to avoid any GC interference while the
48194 		 * array part is populated.
48195 		 */
48196 		duk_push_string(thr, c_filename);
48197 		arr_size += 2;
48198 	}
48199 
48200 	/* XXX: Uninitialized would be OK.  Maybe add internal primitive to
48201 	 * push bare duk_harray with size?
48202 	 */
48203 	DUK_D(DUK_DPRINT("preallocated _Tracedata to %ld items", (long) arr_size));
48204 	tv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) arr_size);
48205 	duk_clear_prototype(thr, -1);
48206 	DUK_ASSERT(duk_is_bare_object(thr, -1));
48207 	DUK_ASSERT(arr_size == 0 || tv != NULL);
48208 
48209 	/* Compiler SyntaxErrors (and other errors) come first, and are
48210 	 * blamed by default (not flagged "noblame").
48211 	 */
48212 	if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
48213 		s = thr->compile_ctx->h_filename;
48214 		DUK_TVAL_SET_STRING(tv, s);
48215 		DUK_HSTRING_INCREF(thr, s);
48216 		tv++;
48217 
48218 		u32 = (duk_uint32_t) thr->compile_ctx->curr_token.start_line;  /* (flags<<32) + (line), flags = 0 */
48219 		DUK_TVAL_SET_U32(tv, u32);
48220 		tv++;
48221 	}
48222 
48223 	/* Filename/line from C macros (__FILE__, __LINE__) are added as an
48224 	 * entry with a special format: (string, number).  The number contains
48225 	 * the line and flags.
48226 	 */
48227 
48228 	/* [ ... error c_filename? arr ] */
48229 
48230 	if (c_filename) {
48231 		DUK_ASSERT(DUK_TVAL_IS_STRING(thr->valstack_top - 2));
48232 		s = DUK_TVAL_GET_STRING(thr->valstack_top - 2);  /* interned c_filename */
48233 		DUK_ASSERT(s != NULL);
48234 		DUK_TVAL_SET_STRING(tv, s);
48235 		DUK_HSTRING_INCREF(thr, s);
48236 		tv++;
48237 
48238 		d = ((flags & DUK_AUGMENT_FLAG_NOBLAME_FILELINE) ? ((duk_double_t) DUK_TB_FLAG_NOBLAME_FILELINE) * DUK_DOUBLE_2TO32 : 0.0) +
48239 		    (duk_double_t) c_line;
48240 		DUK_TVAL_SET_DOUBLE(tv, d);
48241 		tv++;
48242 	}
48243 
48244 	/* Traceback depth doesn't take into account the filename/line
48245 	 * special handling above (intentional).
48246 	 */
48247 	for (; depth-- > 0; act = act->parent) {
48248 		duk_uint32_t pc;
48249 		duk_tval *tv_src;
48250 
48251 		/* [... arr] */
48252 
48253 		DUK_ASSERT(act != NULL);  /* depth check above, assumes book-keeping is correct */
48254 		DUK_ASSERT_DISABLE(act->pc >= 0);  /* unsigned */
48255 
48256 		/* Add function object. */
48257 		tv_src = &act->tv_func;  /* object (function) or lightfunc */
48258 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_src) || DUK_TVAL_IS_LIGHTFUNC(tv_src));
48259 		DUK_TVAL_SET_TVAL(tv, tv_src);
48260 		DUK_TVAL_INCREF(thr, tv);
48261 		tv++;
48262 
48263 		/* Add a number containing: pc, activation flags.
48264 		 *
48265 		 * PC points to next instruction, find offending PC.  Note that
48266 		 * PC == 0 for native code.
48267 		 */
48268 		pc = (duk_uint32_t) duk_hthread_get_act_prev_pc(thr_callstack, act);
48269 		DUK_ASSERT_DISABLE(pc >= 0);  /* unsigned */
48270 		DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32);  /* assume PC is at most 32 bits and non-negative */
48271 		d = ((duk_double_t) act->flags) * DUK_DOUBLE_2TO32 + (duk_double_t) pc;
48272 		DUK_TVAL_SET_DOUBLE(tv, d);
48273 		tv++;
48274 	}
48275 
48276 #if defined(DUK_USE_ASSERTIONS)
48277 	{
48278 		duk_harray *a;
48279 		a = (duk_harray *) duk_known_hobject(thr, -1);
48280 		DUK_ASSERT(a != NULL);
48281 		DUK_ASSERT((duk_uint32_t) (tv - DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) a)) == a->length);
48282 		DUK_ASSERT(a->length == (duk_uint32_t) arr_size);
48283 		DUK_ASSERT(duk_is_bare_object(thr, -1));
48284 	}
48285 #endif
48286 
48287 	/* [ ... error c_filename? arr ] */
48288 
48289 	if (c_filename) {
48290 		duk_remove_m2(thr);
48291 	}
48292 
48293 	/* [ ... error arr ] */
48294 
48295 	duk_xdef_prop_stridx_short_wec(thr, -2, DUK_STRIDX_INT_TRACEDATA);  /* -> [ ... error ] */
48296 }
48297 #endif  /* DUK_USE_TRACEBACKS */
48298 
48299 /*
48300  *  Add .fileName and .lineNumber to an error on the stack top.
48301  */
48302 
48303 #if defined(DUK_USE_AUGMENT_ERROR_CREATE) && !defined(DUK_USE_TRACEBACKS)
48304 DUK_LOCAL void duk__add_fileline(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_small_uint_t flags) {
48305 #if defined(DUK_USE_ASSERTIONS)
48306 	duk_int_t entry_top;
48307 #endif
48308 
48309 #if defined(DUK_USE_ASSERTIONS)
48310 	entry_top = duk_get_top(thr);
48311 #endif
48312 
48313 	/*
48314 	 *  If tracebacks are disabled, 'fileName' and 'lineNumber' are added
48315 	 *  as plain own properties.  Since Error.prototype has accessors of
48316 	 *  the same name, we need to define own properties directly (cannot
48317 	 *  just use e.g. duk_put_prop_stridx).  Existing properties are not
48318 	 *  overwritten in case they already exist.
48319 	 */
48320 
48321 	if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
48322 		/* Compiler SyntaxError (or other error) gets the primary blame.
48323 		 * Currently no flag to prevent blaming.
48324 		 */
48325 		duk_push_uint(thr, (duk_uint_t) thr->compile_ctx->curr_token.start_line);
48326 		duk_push_hstring(thr, thr->compile_ctx->h_filename);
48327 	} else if (c_filename && (flags & DUK_AUGMENT_FLAG_NOBLAME_FILELINE) == 0) {
48328 		/* C call site gets blamed next, unless flagged not to do so.
48329 		 * XXX: file/line is disabled in minimal builds, so disable this
48330 		 * too when appropriate.
48331 		 */
48332 		duk_push_int(thr, c_line);
48333 		duk_push_string(thr, c_filename);
48334 	} else {
48335 		/* Finally, blame the innermost callstack entry which has a
48336 		 * .fileName property.
48337 		 */
48338 		duk_small_uint_t depth;
48339 		duk_uint32_t ecma_line;
48340 		duk_activation *act;
48341 
48342 		DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX);  /* callstack limits */
48343 		depth = DUK_USE_TRACEBACK_DEPTH;
48344 		if (depth > thr_callstack->callstack_top) {
48345 			depth = thr_callstack->callstack_top;
48346 		}
48347 		for (act = thr_callstack->callstack_curr; depth-- > 0; act = act->parent) {
48348 			duk_hobject *func;
48349 			duk_uint32_t pc;
48350 
48351 			DUK_ASSERT(act != NULL);
48352 			func = DUK_ACT_GET_FUNC(act);
48353 			if (func == NULL) {
48354 				/* Lightfunc, not blamed now. */
48355 				continue;
48356 			}
48357 
48358 			/* PC points to next instruction, find offending PC,
48359 			 * PC == 0 for native code.
48360 			 */
48361 			pc = duk_hthread_get_act_prev_pc(thr, act);  /* thr argument only used for thr->heap, so specific thread doesn't matter */
48362 			DUK_UNREF(pc);
48363 			DUK_ASSERT_DISABLE(pc >= 0);  /* unsigned */
48364 			DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32);  /* assume PC is at most 32 bits and non-negative */
48365 
48366 			duk_push_hobject(thr, func);
48367 
48368 			/* [ ... error func ] */
48369 
48370 			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_FILE_NAME);
48371 			if (!duk_is_string_notsymbol(thr, -1)) {
48372 				duk_pop_2(thr);
48373 				continue;
48374 			}
48375 
48376 			/* [ ... error func fileName ] */
48377 
48378 			ecma_line = 0;
48379 #if defined(DUK_USE_PC2LINE)
48380 			if (DUK_HOBJECT_IS_COMPFUNC(func)) {
48381 				ecma_line = duk_hobject_pc2line_query(thr, -2, (duk_uint_fast32_t) pc);
48382 			} else {
48383 				/* Native function, no relevant lineNumber. */
48384 			}
48385 #endif  /* DUK_USE_PC2LINE */
48386 			duk_push_u32(thr, ecma_line);
48387 
48388 			/* [ ... error func fileName lineNumber ] */
48389 
48390 			duk_replace(thr, -3);
48391 
48392 			/* [ ... error lineNumber fileName ] */
48393 			goto define_props;
48394 		}
48395 
48396 		/* No activation matches, use undefined for both .fileName and
48397 		 * .lineNumber (matches what we do with a _Tracedata based
48398 		 * no-match lookup.
48399 		 */
48400 		duk_push_undefined(thr);
48401 		duk_push_undefined(thr);
48402 	}
48403 
48404  define_props:
48405 	/* [ ... error lineNumber fileName ] */
48406 #if defined(DUK_USE_ASSERTIONS)
48407 	DUK_ASSERT(duk_get_top(thr) == entry_top + 2);
48408 #endif
48409 	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_C | DUK_PROPDESC_FLAG_NO_OVERWRITE);
48410 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LINE_NUMBER, DUK_PROPDESC_FLAGS_C | DUK_PROPDESC_FLAG_NO_OVERWRITE);
48411 }
48412 #endif  /* DUK_USE_AUGMENT_ERROR_CREATE && !DUK_USE_TRACEBACKS */
48413 
48414 /*
48415  *  Add line number to a compiler error.
48416  */
48417 
48418 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
48419 DUK_LOCAL void duk__add_compiler_error_line(duk_hthread *thr) {
48420 
48421 	/* Append a "(line NNN)" to the "message" property of any error
48422 	 * thrown during compilation.  Usually compilation errors are
48423 	 * SyntaxErrors but they can also be out-of-memory errors and
48424 	 * the like.
48425 	 */
48426 
48427 	/* [ ... error ] */
48428 
48429 	DUK_ASSERT(duk_is_object(thr, -1));
48430 
48431 	if (!(thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL)) {
48432 		return;
48433 	}
48434 
48435 	DUK_DDD(DUK_DDDPRINT("compile error, before adding line info: %!T",
48436 	                     (duk_tval *) duk_get_tval(thr, -1)));
48437 
48438 	if (duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_MESSAGE)) {
48439 		duk_bool_t at_end;
48440 
48441 		/* Best guesstimate that error occurred at end of input, token
48442 		 * truncated by end of input, etc.
48443 		 */
48444 #if 0
48445 		at_end = (thr->compile_ctx->curr_token.start_offset + 1 >= thr->compile_ctx->lex.input_length);
48446 		at_end = (thr->compile_ctx->lex.window[0].codepoint < 0 || thr->compile_ctx->lex.window[1].codepoint < 0);
48447 #endif
48448 		at_end = (thr->compile_ctx->lex.window[0].codepoint < 0);
48449 
48450 		DUK_D(DUK_DPRINT("syntax error, determined at_end=%ld; curr_token.start_offset=%ld, "
48451 		                 "lex.input_length=%ld, window[0].codepoint=%ld, window[1].codepoint=%ld",
48452 		                 (long) at_end,
48453 		                 (long) thr->compile_ctx->curr_token.start_offset,
48454 		                 (long) thr->compile_ctx->lex.input_length,
48455 		                 (long) thr->compile_ctx->lex.window[0].codepoint,
48456 		                 (long) thr->compile_ctx->lex.window[1].codepoint));
48457 
48458 		duk_push_sprintf(thr, " (line %ld%s)",
48459 		                 (long) thr->compile_ctx->curr_token.start_line,
48460 		                 at_end ? ", end of input" : "");
48461 		duk_concat(thr, 2);
48462 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE);
48463 	} else {
48464 		duk_pop(thr);
48465 	}
48466 
48467 	DUK_DDD(DUK_DDDPRINT("compile error, after adding line info: %!T",
48468 	                     (duk_tval *) duk_get_tval(thr, -1)));
48469 }
48470 #endif  /* DUK_USE_AUGMENT_ERROR_CREATE */
48471 
48472 /*
48473  *  Augment an error being created using Duktape specific properties
48474  *  like _Tracedata or .fileName/.lineNumber.
48475  */
48476 
48477 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
48478 DUK_LOCAL void duk__err_augment_builtin_create(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_hobject *obj, duk_small_uint_t flags) {
48479 #if defined(DUK_USE_ASSERTIONS)
48480 	duk_int_t entry_top;
48481 #endif
48482 
48483 #if defined(DUK_USE_ASSERTIONS)
48484 	entry_top = duk_get_top(thr);
48485 #endif
48486 	DUK_ASSERT(obj != NULL);
48487 
48488 	DUK_UNREF(obj);  /* unreferenced w/o tracebacks */
48489 
48490 	duk__add_compiler_error_line(thr);
48491 
48492 #if defined(DUK_USE_TRACEBACKS)
48493 	/* If tracebacks are enabled, the '_Tracedata' property is the only
48494 	 * thing we need: 'fileName' and 'lineNumber' are virtual properties
48495 	 * which use '_Tracedata'.  (Check _Tracedata only as own property.)
48496 	 */
48497 	if (duk_hobject_find_entry_tval_ptr_stridx(thr->heap, obj, DUK_STRIDX_INT_TRACEDATA) != NULL) {
48498 		DUK_DDD(DUK_DDDPRINT("error value already has a '_Tracedata' property, not modifying it"));
48499 	} else {
48500 		duk__add_traceback(thr, thr_callstack, c_filename, c_line, flags);
48501 	}
48502 #else
48503 	/* Without tracebacks the concrete .fileName and .lineNumber need
48504 	 * to be added directly.
48505 	 */
48506 	duk__add_fileline(thr, thr_callstack, c_filename, c_line, flags);
48507 #endif
48508 
48509 #if defined(DUK_USE_ASSERTIONS)
48510 	DUK_ASSERT(duk_get_top(thr) == entry_top);
48511 #endif
48512 }
48513 #endif  /* DUK_USE_AUGMENT_ERROR_CREATE */
48514 
48515 /*
48516  *  Augment an error at creation time with _Tracedata/fileName/lineNumber
48517  *  and allow a user error handler (if defined) to process/replace the error.
48518  *  The error to be augmented is at the stack top.
48519  *
48520  *  thr: thread containing the error value
48521  *  thr_callstack: thread which should be used for generating callstack etc.
48522  *  c_filename: C __FILE__ related to the error
48523  *  c_line: C __LINE__ related to the error
48524  *  flags & DUK_AUGMENT_FLAG_NOBLAME_FILELINE:
48525  *      if true, don't fileName/line as error source, otherwise use traceback
48526  *      (needed because user code filename/line are reported but internal ones
48527  *      are not)
48528  */
48529 
48530 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
48531 DUK_INTERNAL void duk_err_augment_error_create(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_small_uint_t flags) {
48532 	duk_hobject *obj;
48533 
48534 	DUK_ASSERT(thr != NULL);
48535 	DUK_ASSERT(thr_callstack != NULL);
48536 
48537 	/* [ ... error ] */
48538 
48539 	/*
48540 	 *  Criteria for augmenting:
48541 	 *
48542 	 *   - augmentation enabled in build (naturally)
48543 	 *   - error value internal prototype chain contains the built-in
48544 	 *     Error prototype object (i.e. 'val instanceof Error')
48545 	 *
48546 	 *  Additional criteria for built-in augmenting:
48547 	 *
48548 	 *   - error value is an extensible object
48549 	 */
48550 
48551 	obj = duk_get_hobject(thr, -1);
48552 	if (!obj) {
48553 		DUK_DDD(DUK_DDDPRINT("value is not an object, skip both built-in and user augment"));
48554 		return;
48555 	}
48556 	if (!duk_hobject_prototype_chain_contains(thr, obj, thr->builtins[DUK_BIDX_ERROR_PROTOTYPE], 1 /*ignore_loop*/)) {
48557 		/* If the value has a prototype loop, it's critical not to
48558 		 * throw here.  Instead, assume the value is not to be
48559 		 * augmented.
48560 		 */
48561 		DUK_DDD(DUK_DDDPRINT("value is not an error instance, skip both built-in and user augment"));
48562 		return;
48563 	}
48564 	if (DUK_HOBJECT_HAS_EXTENSIBLE(obj)) {
48565 		DUK_DDD(DUK_DDDPRINT("error meets criteria, built-in augment"));
48566 		duk__err_augment_builtin_create(thr, thr_callstack, c_filename, c_line, obj, flags);
48567 	} else {
48568 		DUK_DDD(DUK_DDDPRINT("error does not meet criteria, no built-in augment"));
48569 	}
48570 
48571 	/* [ ... error ] */
48572 
48573 #if defined(DUK_USE_ERRCREATE)
48574 	duk__err_augment_user(thr, DUK_STRIDX_ERR_CREATE);
48575 #endif
48576 }
48577 #endif  /* DUK_USE_AUGMENT_ERROR_CREATE */
48578 
48579 /*
48580  *  Augment an error at throw time; allow a user error handler (if defined)
48581  *  to process/replace the error.  The error to be augmented is at the
48582  *  stack top.
48583  */
48584 
48585 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
48586 DUK_INTERNAL void duk_err_augment_error_throw(duk_hthread *thr) {
48587 #if defined(DUK_USE_ERRTHROW)
48588 	duk__err_augment_user(thr, DUK_STRIDX_ERR_THROW);
48589 #endif  /* DUK_USE_ERRTHROW */
48590 }
48591 #endif  /* DUK_USE_AUGMENT_ERROR_THROW */
48592 /*
48593  *  Do a longjmp call, calling the fatal error handler if no
48594  *  catchpoint exists.
48595  */
48596 
48597 /* #include duk_internal.h -> already included */
48598 
48599 #if defined(DUK_USE_PREFER_SIZE)
48600 DUK_NORETURN(DUK_LOCAL_DECL void duk__uncaught_minimal(duk_hthread *thr));
48601 DUK_LOCAL void duk__uncaught_minimal(duk_hthread *thr) {
48602 	(void) duk_fatal(thr, "uncaught error");
48603 	DUK_WO_NORETURN(return;);
48604 }
48605 #endif
48606 
48607 #if 0
48608 DUK_NORETURN(DUK_LOCAL_DECL void duk__uncaught_readable(duk_hthread *thr));
48609 DUK_LOCAL void duk__uncaught_readable(duk_hthread *thr) {
48610 	const char *summary;
48611 	char buf[DUK_USE_FATAL_MAXLEN];
48612 
48613 	summary = duk_push_string_tval_readable(thr, &thr->heap->lj.value1);
48614 	DUK_SNPRINTF(buf, sizeof(buf), "uncaught: %s", summary);
48615 	buf[sizeof(buf) - 1] = (char) 0;
48616 	(void) duk_fatal(thr, (const char *) buf);
48617 	DUK_WO_NORETURN(return;);
48618 }
48619 #endif
48620 
48621 #if !defined(DUK_USE_PREFER_SIZE)
48622 DUK_NORETURN(DUK_LOCAL_DECL void duk__uncaught_error_aware(duk_hthread *thr));
48623 DUK_LOCAL void duk__uncaught_error_aware(duk_hthread *thr) {
48624 	const char *summary;
48625 	char buf[DUK_USE_FATAL_MAXLEN];
48626 
48627 	summary = duk_push_string_tval_readable_error(thr, &thr->heap->lj.value1);
48628 	DUK_ASSERT(summary != NULL);
48629 	DUK_SNPRINTF(buf, sizeof(buf), "uncaught: %s", summary);
48630 	buf[sizeof(buf) - 1] = (char) 0;
48631 	(void) duk_fatal(thr, (const char *) buf);
48632 	DUK_WO_NORETURN(return;);
48633 }
48634 #endif
48635 
48636 DUK_INTERNAL void duk_err_longjmp(duk_hthread *thr) {
48637 	DUK_ASSERT(thr != NULL);
48638 	DUK_ASSERT(thr->heap != NULL);
48639 
48640 	DUK_DD(DUK_DDPRINT("longjmp error: type=%d iserror=%d value1=%!T value2=%!T",
48641 	                   (int) thr->heap->lj.type, (int) thr->heap->lj.iserror,
48642 	                   &thr->heap->lj.value1, &thr->heap->lj.value2));
48643 
48644 	/* Prevent finalizer execution during error handling.  All error
48645 	 * handling sites will process pending finalizers once error handling
48646 	 * is complete and we're ready for the side effects.  Does not prevent
48647 	 * refzero freeing or mark-and-sweep during error handling.
48648 	 *
48649 	 * NOTE: when we come here some calling code may have used DECREF
48650 	 * NORZ macros without an explicit DUK_REFZERO_CHECK_xxx() call.
48651 	 * We don't want to do it here because it would just check for
48652 	 * pending finalizers and we prevent that explicitly.  Instead,
48653 	 * the error catcher will run the finalizers once error handling
48654 	 * is complete.
48655 	 */
48656 
48657 	DUK_ASSERT_LJSTATE_SET(thr->heap);
48658 
48659 	thr->heap->pf_prevent_count++;
48660 	DUK_ASSERT(thr->heap->pf_prevent_count != 0);  /* Wrap. */
48661 
48662 #if defined(DUK_USE_ASSERTIONS)
48663 	/* XXX: set this immediately when longjmp state is set */
48664 	DUK_ASSERT(thr->heap->error_not_allowed == 0);  /* Detect error within critical section. */
48665 	thr->heap->error_not_allowed = 1;
48666 #endif
48667 
48668 	DUK_DD(DUK_DDPRINT("about to longjmp, pf_prevent_count=%ld", (long) thr->heap->pf_prevent_count));
48669 
48670 	/* If we don't have a jmpbuf_ptr, there is little we can do except
48671 	 * cause a fatal error.  The caller's expectation is that we never
48672 	 * return.
48673 	 */
48674 	if (!thr->heap->lj.jmpbuf_ptr) {
48675 		DUK_D(DUK_DPRINT("uncaught error: type=%d iserror=%d value1=%!T value2=%!T",
48676 		                 (int) thr->heap->lj.type, (int) thr->heap->lj.iserror,
48677 		                 &thr->heap->lj.value1, &thr->heap->lj.value2));
48678 
48679 #if defined(DUK_USE_PREFER_SIZE)
48680 		duk__uncaught_minimal(thr);
48681 #else
48682 		duk__uncaught_error_aware(thr);
48683 #endif
48684 		DUK_UNREACHABLE();
48685 	}
48686 
48687 #if defined(DUK_USE_CPP_EXCEPTIONS)
48688 	throw duk_internal_exception();  /* dummy */
48689 #else
48690 	DUK_LONGJMP(thr->heap->lj.jmpbuf_ptr->jb);
48691 #endif
48692 
48693 	DUK_UNREACHABLE();
48694 }
48695 /*
48696  *  Error helpers
48697  */
48698 
48699 /* #include duk_internal.h -> already included */
48700 
48701 /*
48702  *  Helper to walk the thread chain and see if there is an active error
48703  *  catcher.  Protected calls or finally blocks aren't considered catching.
48704  */
48705 
48706 #if defined(DUK_USE_DEBUGGER_SUPPORT)
48707 DUK_LOCAL duk_bool_t duk__have_active_catcher(duk_hthread *thr) {
48708 	/* As noted above, a protected API call won't be counted as a
48709 	 * catcher.  This is usually convenient, e.g. in the case of a top-
48710 	 * level duk_pcall(), but may not always be desirable.  Perhaps add
48711 	 * an argument to treat them as catchers?
48712 	 */
48713 
48714 	duk_activation *act;
48715 	duk_catcher *cat;
48716 
48717 	DUK_ASSERT(thr != NULL);
48718 
48719 	for (; thr != NULL; thr = thr->resumer) {
48720 		for (act = thr->callstack_curr; act != NULL; act = act->parent) {
48721 			for (cat = act->cat; cat != NULL; cat = cat->parent) {
48722 				if (DUK_CAT_HAS_CATCH_ENABLED(cat)) {
48723 					return 1;  /* all we need to know */
48724 				}
48725 			}
48726 		}
48727 	}
48728 	return 0;
48729 }
48730 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
48731 
48732 /*
48733  *  Get prototype object for an integer error code.
48734  */
48735 
48736 DUK_INTERNAL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t code) {
48737 	switch (code) {
48738 	case DUK_ERR_EVAL_ERROR:
48739 		return thr->builtins[DUK_BIDX_EVAL_ERROR_PROTOTYPE];
48740 	case DUK_ERR_RANGE_ERROR:
48741 		return thr->builtins[DUK_BIDX_RANGE_ERROR_PROTOTYPE];
48742 	case DUK_ERR_REFERENCE_ERROR:
48743 		return thr->builtins[DUK_BIDX_REFERENCE_ERROR_PROTOTYPE];
48744 	case DUK_ERR_SYNTAX_ERROR:
48745 		return thr->builtins[DUK_BIDX_SYNTAX_ERROR_PROTOTYPE];
48746 	case DUK_ERR_TYPE_ERROR:
48747 		return thr->builtins[DUK_BIDX_TYPE_ERROR_PROTOTYPE];
48748 	case DUK_ERR_URI_ERROR:
48749 		return thr->builtins[DUK_BIDX_URI_ERROR_PROTOTYPE];
48750 	case DUK_ERR_ERROR:
48751 	default:
48752 		return thr->builtins[DUK_BIDX_ERROR_PROTOTYPE];
48753 	}
48754 }
48755 
48756 /*
48757  *  Helper for debugger throw notify and pause-on-uncaught integration.
48758  */
48759 
48760 #if defined(DUK_USE_DEBUGGER_SUPPORT)
48761 DUK_INTERNAL void duk_err_check_debugger_integration(duk_hthread *thr) {
48762 	duk_bool_t uncaught;
48763 	duk_tval *tv_obj;
48764 
48765 	/* If something is thrown with the debugger attached and nobody will
48766 	 * catch it, execution is paused before the longjmp, turning over
48767 	 * control to the debug client.  This allows local state to be examined
48768 	 * before the stack is unwound.  Errors are not intercepted when debug
48769 	 * message loop is active (e.g. for Eval).
48770 	 */
48771 
48772 	DUK_ASSERT(thr != NULL);
48773 	DUK_ASSERT(thr->heap != NULL);
48774 
48775 	/* XXX: Allow customizing the pause and notify behavior at runtime
48776 	 * using debugger runtime flags.  For now the behavior is fixed using
48777 	 * config options.
48778 	 */
48779 
48780 	if (!duk_debug_is_attached(thr->heap) ||
48781 	    thr->heap->dbg_processing ||
48782 	    thr->heap->lj.type != DUK_LJ_TYPE_THROW ||
48783 	    thr->heap->creating_error) {
48784 		DUK_D(DUK_DPRINT("skip debugger error integration; not attached, debugger processing, not THROW, or error thrown while creating error"));
48785 		return;
48786 	}
48787 
48788 	/* Don't intercept a DoubleError, we may have caused the initial double
48789 	 * fault and attempting to intercept it will cause us to be called
48790 	 * recursively and exhaust the C stack.  (This should no longer happen
48791 	 * for the initial throw because DoubleError path doesn't do a debugger
48792 	 * integration check, but it might happen for rethrows.)
48793 	 */
48794 	tv_obj = &thr->heap->lj.value1;
48795 	if (DUK_TVAL_IS_OBJECT(tv_obj) && DUK_TVAL_GET_OBJECT(tv_obj) == thr->builtins[DUK_BIDX_DOUBLE_ERROR]) {
48796 		DUK_D(DUK_DPRINT("built-in DoubleError instance (re)thrown, not intercepting"));
48797 		return;
48798 	}
48799 
48800 	uncaught = !duk__have_active_catcher(thr);
48801 
48802 	/* Debugger code expects the value at stack top.  This also serves
48803 	 * as a backup: we need to store/restore the longjmp state because
48804 	 * when the debugger is paused Eval commands may be executed and
48805 	 * they can arbitrarily clobber the longjmp state.
48806 	 */
48807 	duk_push_tval(thr, tv_obj);
48808 
48809 	/* Store and reset longjmp state. */
48810 	DUK_ASSERT_LJSTATE_SET(thr->heap);
48811 	DUK_TVAL_DECREF_NORZ(thr, tv_obj);
48812 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));  /* Always for THROW type. */
48813 	DUK_TVAL_SET_UNDEFINED(tv_obj);
48814 	thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
48815 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
48816 
48817 #if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
48818 	/* Report it to the debug client */
48819 	DUK_D(DUK_DPRINT("throw with debugger attached, report to client"));
48820 	duk_debug_send_throw(thr, uncaught);
48821 #endif
48822 
48823 	if (uncaught) {
48824 		if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_UNCAUGHT_ERROR) {
48825 			DUK_D(DUK_DPRINT("PAUSE TRIGGERED by uncaught error"));
48826 			duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
48827 		}
48828 	} else {
48829 		if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_CAUGHT_ERROR) {
48830 			DUK_D(DUK_DPRINT("PAUSE TRIGGERED by caught error"));
48831 			duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
48832 		}
48833 	}
48834 
48835 	/* Restore longjmp state. */
48836 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
48837 	thr->heap->lj.type = DUK_LJ_TYPE_THROW;
48838 	tv_obj = DUK_GET_TVAL_NEGIDX(thr, -1);
48839 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value1));
48840 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));
48841 	DUK_TVAL_SET_TVAL(&thr->heap->lj.value1, tv_obj);
48842 	DUK_TVAL_INCREF(thr, tv_obj);
48843 	DUK_ASSERT_LJSTATE_SET(thr->heap);
48844 
48845 	duk_pop(thr);
48846 }
48847 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
48848 
48849 /*
48850  *  Helpers for setting up heap longjmp state.
48851  */
48852 
48853 DUK_INTERNAL void duk_err_setup_ljstate1(duk_hthread *thr, duk_small_uint_t lj_type, duk_tval *tv_val) {
48854 	duk_heap *heap;
48855 
48856 	DUK_ASSERT(thr != NULL);
48857 	heap = thr->heap;
48858 	DUK_ASSERT(heap != NULL);
48859 	DUK_ASSERT(tv_val != NULL);
48860 
48861 	DUK_ASSERT_LJSTATE_UNSET(heap);
48862 
48863 	heap->lj.type = lj_type;
48864 	DUK_TVAL_SET_TVAL(&heap->lj.value1, tv_val);
48865 	DUK_TVAL_INCREF(thr, tv_val);
48866 
48867 	DUK_ASSERT_LJSTATE_SET(heap);
48868 }
48869 /*
48870  *  Create and throw an ECMAScript error object based on a code and a message.
48871  *
48872  *  Used when we throw errors internally.  ECMAScript generated error objects
48873  *  are created by ECMAScript code, and the throwing is handled by the bytecode
48874  *  executor.
48875  */
48876 
48877 /* #include duk_internal.h -> already included */
48878 
48879 /*
48880  *  Create and throw an error (originating from Duktape internally)
48881  *
48882  *  Push an error object on top of the stack, possibly throw augmenting
48883  *  the error, and finally longjmp.
48884  *
48885  *  If an error occurs while we're dealing with the current error, we might
48886  *  enter an infinite recursion loop.  This is prevented by detecting a
48887  *  "double fault" through the heap->creating_error flag; the recursion
48888  *  then stops at the second level.
48889  */
48890 
48891 #if defined(DUK_USE_VERBOSE_ERRORS)
48892 DUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code, const char *msg, const char *filename, duk_int_t line) {
48893 #else
48894 DUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code) {
48895 #endif
48896 #if defined(DUK_USE_VERBOSE_ERRORS)
48897 	DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld, msg=%s, filename=%s, line=%ld",
48898 	                   (long) code, (const char *) msg,
48899 	                   (const char *) filename, (long) line));
48900 #else
48901 	DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld", (long) code));
48902 #endif
48903 
48904 	DUK_ASSERT(thr != NULL);
48905 
48906 	/* Even though nested call is possible because we throw an error when
48907 	 * trying to create an error, the potential errors must happen before
48908 	 * the longjmp state is configured.
48909 	 */
48910 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
48911 
48912 	/* Sync so that augmentation sees up-to-date activations, NULL
48913 	 * thr->ptr_curr_pc so that it's not used if side effects occur
48914 	 * in augmentation or longjmp handling.
48915 	 */
48916 	duk_hthread_sync_and_null_currpc(thr);
48917 
48918 	/*
48919 	 *  Create and push an error object onto the top of stack.
48920 	 *  The error is potentially augmented before throwing.
48921 	 *
48922 	 *  If a "double error" occurs, use a fixed error instance
48923 	 *  to avoid further trouble.
48924 	 */
48925 
48926 	if (thr->heap->creating_error) {
48927 		duk_tval tv_val;
48928 		duk_hobject *h_err;
48929 
48930 		thr->heap->creating_error = 0;
48931 
48932 		h_err = thr->builtins[DUK_BIDX_DOUBLE_ERROR];
48933 		if (h_err != NULL) {
48934 			DUK_D(DUK_DPRINT("double fault detected -> use built-in fixed 'double error' instance"));
48935 			DUK_TVAL_SET_OBJECT(&tv_val, h_err);
48936 		} else {
48937 			DUK_D(DUK_DPRINT("double fault detected; there is no built-in fixed 'double error' instance "
48938 			                 "-> use the error code as a number"));
48939 			DUK_TVAL_SET_I32(&tv_val, (duk_int32_t) code);
48940 		}
48941 
48942 		duk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, &tv_val);
48943 
48944 		/* No augmentation to avoid any allocations or side effects. */
48945 	} else {
48946 		/* Prevent infinite recursion.  Extra call stack and C
48947 		 * recursion headroom (see GH-191) is added for augmentation.
48948 		 * That is now signalled by heap->augmenting error and taken
48949 		 * into account in call handling without an explicit limit bump.
48950 		 */
48951 		thr->heap->creating_error = 1;
48952 
48953 		duk_require_stack(thr, 1);
48954 
48955 		/* XXX: usually unnecessary '%s' formatting here, but cannot
48956 		 * use 'msg' as a format string directly.
48957 		 */
48958 #if defined(DUK_USE_VERBOSE_ERRORS)
48959 		duk_push_error_object_raw(thr,
48960 		                          code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
48961 		                          filename,
48962 		                          line,
48963 		                          "%s",
48964 		                          (const char *) msg);
48965 #else
48966 		duk_push_error_object_raw(thr,
48967 		                          code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
48968 		                          NULL,
48969 		                          0,
48970 		                          NULL);
48971 #endif
48972 
48973 		/* Note that an alloc error may happen during error augmentation.
48974 		 * This may happen both when the original error is an alloc error
48975 		 * and when it's something else.  Because any error in augmentation
48976 		 * must be handled correctly anyway, there's no special check for
48977 		 * avoiding it for alloc errors (this differs from Duktape 1.x).
48978 		 */
48979 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
48980 		DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT (before throw augment)",
48981 		                     (duk_tval *) duk_get_tval(thr, -1)));
48982 		duk_err_augment_error_throw(thr);
48983 #endif
48984 
48985 		duk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, DUK_GET_TVAL_NEGIDX(thr, -1));
48986 		thr->heap->creating_error = 0;
48987 
48988 		/* Error is now created and we assume no errors can occur any
48989 		 * more.  Check for debugger Throw integration only when the
48990 		 * error is complete.  If we enter debugger message loop,
48991 		 * creating_error must be 0 so that errors can be thrown in
48992 		 * the paused state, e.g. in Eval commands.
48993 		 */
48994 #if defined(DUK_USE_DEBUGGER_SUPPORT)
48995 		duk_err_check_debugger_integration(thr);
48996 #endif
48997 	}
48998 
48999 	/*
49000 	 *  Finally, longjmp
49001 	 */
49002 
49003 	DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT, %!iT (after throw augment)",
49004 	                     (duk_tval *) &thr->heap->lj.value1, (duk_tval *) &thr->heap->lj.value2));
49005 
49006 	duk_err_longjmp(thr);
49007 	DUK_UNREACHABLE();
49008 }
49009 
49010 /*
49011  *  Helper for C function call negative return values.
49012  */
49013 
49014 DUK_INTERNAL void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc) {
49015 	DUK_ASSERT(thr != NULL);
49016 	DUK_ASSERT(rc < 0);
49017 
49018 	/*
49019 	 *  The __FILE__ and __LINE__ information is intentionally not used in the
49020 	 *  creation of the error object, as it isn't useful in the tracedata.  The
49021 	 *  tracedata still contains the function which returned the negative return
49022 	 *  code, and having the file/line of this function isn't very useful.
49023 	 *
49024 	 *  The error messages for DUK_RET_xxx shorthand are intentionally very
49025 	 *  minimal: they're only really useful for low memory targets.
49026 	 */
49027 
49028 	duk_error_raw(thr, -rc, NULL, 0, "error (rc %ld)", (long) rc);
49029 	DUK_WO_NORETURN(return;);
49030 }
49031 /*
49032  *  duk_hbuffer allocation and freeing.
49033  */
49034 
49035 /* #include duk_internal.h -> already included */
49036 
49037 /* Allocate a new duk_hbuffer of a certain type and return a pointer to it
49038  * (NULL on error).  Write buffer data pointer to 'out_bufdata' (only if
49039  * allocation successful).
49040  */
49041 DUK_INTERNAL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata) {
49042 	duk_hbuffer *res = NULL;
49043 	duk_size_t header_size;
49044 	duk_size_t alloc_size;
49045 
49046 	DUK_ASSERT(heap != NULL);
49047 	DUK_ASSERT(out_bufdata != NULL);
49048 
49049 	DUK_DDD(DUK_DDDPRINT("allocate hbuffer"));
49050 
49051 	/* Size sanity check.  Should not be necessary because caller is
49052 	 * required to check this, but we don't want to cause a segfault
49053 	 * if the size wraps either in duk_size_t computation or when
49054 	 * storing the size in a 16-bit field.
49055 	 */
49056 	if (size > DUK_HBUFFER_MAX_BYTELEN) {
49057 		DUK_D(DUK_DPRINT("hbuffer alloc failed: size too large: %ld", (long) size));
49058 		return NULL;  /* no need to write 'out_bufdata' */
49059 	}
49060 
49061 	if (flags & DUK_BUF_FLAG_EXTERNAL) {
49062 		header_size = sizeof(duk_hbuffer_external);
49063 		alloc_size = sizeof(duk_hbuffer_external);
49064 	} else if (flags & DUK_BUF_FLAG_DYNAMIC) {
49065 		header_size = sizeof(duk_hbuffer_dynamic);
49066 		alloc_size = sizeof(duk_hbuffer_dynamic);
49067 	} else {
49068 		header_size = sizeof(duk_hbuffer_fixed);
49069 		alloc_size = sizeof(duk_hbuffer_fixed) + size;
49070 		DUK_ASSERT(alloc_size >= sizeof(duk_hbuffer_fixed));  /* no wrapping */
49071 	}
49072 
49073 	res = (duk_hbuffer *) DUK_ALLOC(heap, alloc_size);
49074 	if (DUK_UNLIKELY(res == NULL)) {
49075 		goto alloc_error;
49076 	}
49077 
49078 	/* zero everything unless requested not to do so */
49079 #if defined(DUK_USE_ZERO_BUFFER_DATA)
49080 	duk_memzero((void *) res,
49081 	            (flags & DUK_BUF_FLAG_NOZERO) ? header_size : alloc_size);
49082 #else
49083 	duk_memzero((void *) res, header_size);
49084 #endif
49085 
49086 	if (flags & DUK_BUF_FLAG_EXTERNAL) {
49087 		duk_hbuffer_external *h;
49088 		h = (duk_hbuffer_external *) res;
49089 		DUK_UNREF(h);
49090 		*out_bufdata = NULL;
49091 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
49092 #if defined(DUK_USE_HEAPPTR16)
49093 /* the compressed pointer is zeroed which maps to NULL, so nothing to do. */
49094 #else
49095 		DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap, h, NULL);
49096 #endif
49097 #endif
49098 		DUK_ASSERT(DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap, h) == NULL);
49099 	} else if (flags & DUK_BUF_FLAG_DYNAMIC) {
49100 		duk_hbuffer_dynamic *h = (duk_hbuffer_dynamic *) res;
49101 		void *ptr;
49102 
49103 		if (size > 0) {
49104 			DUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL));  /* alloc external with size zero */
49105 			DUK_DDD(DUK_DDDPRINT("dynamic buffer with nonzero size, alloc actual buffer"));
49106 #if defined(DUK_USE_ZERO_BUFFER_DATA)
49107 			ptr = DUK_ALLOC_ZEROED(heap, size);
49108 #else
49109 			ptr = DUK_ALLOC(heap, size);
49110 #endif
49111 			if (DUK_UNLIKELY(ptr == NULL)) {
49112 				/* Because size > 0, NULL check is correct */
49113 				goto alloc_error;
49114 			}
49115 			*out_bufdata = ptr;
49116 
49117 			DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, h, ptr);
49118 		} else {
49119 			*out_bufdata = NULL;
49120 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
49121 #if defined(DUK_USE_HEAPPTR16)
49122 /* the compressed pointer is zeroed which maps to NULL, so nothing to do. */
49123 #else
49124 			DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, h, NULL);
49125 #endif
49126 #endif
49127 			DUK_ASSERT(DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, h) == NULL);
49128 		}
49129 	} else {
49130 		*out_bufdata = (void *) ((duk_hbuffer_fixed *) (void *) res + 1);
49131 	}
49132 
49133 	DUK_HBUFFER_SET_SIZE(res, size);
49134 
49135 	DUK_HEAPHDR_SET_TYPE(&res->hdr, DUK_HTYPE_BUFFER);
49136 	if (flags & DUK_BUF_FLAG_DYNAMIC) {
49137 		DUK_HBUFFER_SET_DYNAMIC(res);
49138 		if (flags & DUK_BUF_FLAG_EXTERNAL) {
49139 			DUK_HBUFFER_SET_EXTERNAL(res);
49140 		}
49141 	} else {
49142 		DUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL));
49143 	}
49144         DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &res->hdr);
49145 
49146 	DUK_DDD(DUK_DDDPRINT("allocated hbuffer: %p", (void *) res));
49147 	return res;
49148 
49149  alloc_error:
49150 	DUK_DD(DUK_DDPRINT("hbuffer allocation failed"));
49151 
49152 	DUK_FREE(heap, res);
49153 	return NULL;  /* no need to write 'out_bufdata' */
49154 }
49155 
49156 /* For indirect allocs. */
49157 
49158 DUK_INTERNAL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud) {
49159 	duk_hbuffer_dynamic *buf = (duk_hbuffer_dynamic *) ud;
49160 	DUK_UNREF(heap);
49161 	return (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, buf);
49162 }
49163 /*
49164  *  duk_hbuffer assertion helpers
49165  */
49166 
49167 /* #include duk_internal.h -> already included */
49168 
49169 #if defined(DUK_USE_ASSERTIONS)
49170 
49171 DUK_INTERNAL void duk_hbuffer_assert_valid(duk_hbuffer *h) {
49172 	DUK_ASSERT(h != NULL);
49173 }
49174 
49175 #endif  /* DUK_USE_ASSERTIONS */
49176 /*
49177  *  duk_hbuffer operations such as resizing and inserting/appending data to
49178  *  a dynamic buffer.
49179  */
49180 
49181 /* #include duk_internal.h -> already included */
49182 
49183 /*
49184  *  Resizing
49185  */
49186 
49187 DUK_INTERNAL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size) {
49188 	void *res;
49189 	duk_size_t prev_size;
49190 
49191 	DUK_ASSERT(thr != NULL);
49192 	DUK_ASSERT(buf != NULL);
49193 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
49194 	DUK_ASSERT(!DUK_HBUFFER_HAS_EXTERNAL(buf));
49195 
49196 	/*
49197 	 *  Maximum size check
49198 	 */
49199 
49200 	if (new_size > DUK_HBUFFER_MAX_BYTELEN) {
49201 		DUK_ERROR_RANGE(thr, "buffer too long");
49202 		DUK_WO_NORETURN(return;);
49203 	}
49204 
49205 	/*
49206 	 *  Note: use indirect realloc variant just in case mark-and-sweep
49207 	 *  (finalizers) might resize this same buffer during garbage
49208 	 *  collection.
49209 	 */
49210 
49211 	res = DUK_REALLOC_INDIRECT(thr->heap, duk_hbuffer_get_dynalloc_ptr, (void *) buf, new_size);
49212 	if (DUK_LIKELY(res != NULL || new_size == 0)) {
49213 		/* 'res' may be NULL if new allocation size is 0. */
49214 
49215 		DUK_DDD(DUK_DDDPRINT("resized dynamic buffer %p:%ld -> %p:%ld",
49216 		                     (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, buf),
49217 		                     (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(buf),
49218 		                     (void *) res,
49219 		                     (long) new_size));
49220 
49221 		/*
49222 		 *  The entire allocated buffer area, regardless of actual used
49223 		 *  size, is kept zeroed in resizes for simplicity.  If the buffer
49224 		 *  is grown, zero the new part.
49225 		 */
49226 
49227 		prev_size = DUK_HBUFFER_DYNAMIC_GET_SIZE(buf);
49228 		if (new_size > prev_size) {
49229 			DUK_ASSERT(new_size - prev_size > 0);
49230 #if defined(DUK_USE_ZERO_BUFFER_DATA)
49231 			duk_memzero((void *) ((char *) res + prev_size),
49232 			            (duk_size_t) (new_size - prev_size));
49233 #endif
49234 		}
49235 
49236 		DUK_HBUFFER_DYNAMIC_SET_SIZE(buf, new_size);
49237 		DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(thr->heap, buf, res);
49238 	} else {
49239 		DUK_ERROR_ALLOC_FAILED(thr);
49240 		DUK_WO_NORETURN(return;);
49241 	}
49242 
49243 	DUK_ASSERT(res != NULL || new_size == 0);
49244 }
49245 
49246 DUK_INTERNAL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf) {
49247 	DUK_ASSERT(thr != NULL);
49248 	DUK_ASSERT(buf != NULL);
49249 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
49250 	DUK_ASSERT(!DUK_HBUFFER_HAS_EXTERNAL(buf));
49251 
49252 	duk_hbuffer_resize(thr, buf, 0);
49253 }
49254 /* #include duk_internal.h -> already included */
49255 
49256 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
49257 DUK_INTERNAL duk_uint_t duk_hbufobj_clamp_bytelength(duk_hbufobj *h_bufobj, duk_uint_t len) {
49258 	duk_uint_t buf_size;
49259 	duk_uint_t buf_avail;
49260 
49261 	DUK_ASSERT(h_bufobj != NULL);
49262 	DUK_ASSERT(h_bufobj->buf != NULL);
49263 
49264 	buf_size = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_bufobj->buf);
49265 	if (h_bufobj->offset > buf_size) {
49266 		/* Slice starting point is beyond current length. */
49267 		return 0;
49268 	}
49269 	buf_avail = buf_size - h_bufobj->offset;
49270 
49271 	return buf_avail >= len ? len : buf_avail;
49272 }
49273 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
49274 /*
49275  *  duk_heap allocation and freeing.
49276  */
49277 
49278 /* #include duk_internal.h -> already included */
49279 
49280 #if defined(DUK_USE_ROM_STRINGS)
49281 /* Fixed seed value used with ROM strings. */
49282 #define DUK__FIXED_HASH_SEED       0xabcd1234
49283 #endif
49284 
49285 /*
49286  *  Free a heap object.
49287  *
49288  *  Free heap object and its internal (non-heap) pointers.  Assumes that
49289  *  caller has removed the object from heap allocated list or the string
49290  *  intern table, and any weak references (which strings may have) have
49291  *  been already dealt with.
49292  */
49293 
49294 DUK_INTERNAL void duk_free_hobject(duk_heap *heap, duk_hobject *h) {
49295 	DUK_ASSERT(heap != NULL);
49296 	DUK_ASSERT(h != NULL);
49297 
49298 	DUK_FREE(heap, DUK_HOBJECT_GET_PROPS(heap, h));
49299 
49300 	if (DUK_HOBJECT_IS_COMPFUNC(h)) {
49301 		duk_hcompfunc *f = (duk_hcompfunc *) h;
49302 		DUK_UNREF(f);
49303 		/* Currently nothing to free; 'data' is a heap object */
49304 	} else if (DUK_HOBJECT_IS_NATFUNC(h)) {
49305 		duk_hnatfunc *f = (duk_hnatfunc *) h;
49306 		DUK_UNREF(f);
49307 		/* Currently nothing to free */
49308 	} else if (DUK_HOBJECT_IS_THREAD(h)) {
49309 		duk_hthread *t = (duk_hthread *) h;
49310 		duk_activation *act;
49311 
49312 		DUK_FREE(heap, t->valstack);
49313 
49314 		/* Don't free h->resumer because it exists in the heap.
49315 		 * Callstack entries also contain function pointers which
49316 		 * are not freed for the same reason.  They are decref
49317 		 * finalized and the targets are freed if necessary based
49318 		 * on their refcount (or reachability).
49319 		 */
49320 		for (act = t->callstack_curr; act != NULL;) {
49321 			duk_activation *act_next;
49322 			duk_catcher *cat;
49323 
49324 			for (cat = act->cat; cat != NULL;) {
49325 				duk_catcher *cat_next;
49326 
49327 				cat_next = cat->parent;
49328 				DUK_FREE(heap, (void *) cat);
49329 				cat = cat_next;
49330 			}
49331 
49332 			act_next = act->parent;
49333 			DUK_FREE(heap, (void *) act);
49334 			act = act_next;
49335 		}
49336 
49337 		/* XXX: with 'caller' property the callstack would need
49338 		 * to be unwound to update the 'caller' properties of
49339 		 * functions in the callstack.
49340 		 */
49341 	} else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {
49342 		duk_hboundfunc *f = (duk_hboundfunc *) (void *) h;
49343 
49344 		DUK_FREE(heap, f->args);
49345 	}
49346 
49347 	DUK_FREE(heap, (void *) h);
49348 }
49349 
49350 DUK_INTERNAL void duk_free_hbuffer(duk_heap *heap, duk_hbuffer *h) {
49351 	DUK_ASSERT(heap != NULL);
49352 	DUK_ASSERT(h != NULL);
49353 
49354 	if (DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h)) {
49355 		duk_hbuffer_dynamic *g = (duk_hbuffer_dynamic *) h;
49356 		DUK_DDD(DUK_DDDPRINT("free dynamic buffer %p", (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, g)));
49357 		DUK_FREE(heap, DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, g));
49358 	}
49359 	DUK_FREE(heap, (void *) h);
49360 }
49361 
49362 DUK_INTERNAL void duk_free_hstring(duk_heap *heap, duk_hstring *h) {
49363 	DUK_ASSERT(heap != NULL);
49364 	DUK_ASSERT(h != NULL);
49365 
49366 	DUK_UNREF(heap);
49367 	DUK_UNREF(h);
49368 
49369 #if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_FREE)
49370 	if (DUK_HSTRING_HAS_EXTDATA(h)) {
49371 		DUK_DDD(DUK_DDDPRINT("free extstr: hstring %!O, extdata: %p",
49372 		                     h, DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h)));
49373 		DUK_USE_EXTSTR_FREE(heap->heap_udata, (const void *) DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h));
49374 	}
49375 #endif
49376 	DUK_FREE(heap, (void *) h);
49377 }
49378 
49379 DUK_INTERNAL void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr) {
49380 	DUK_ASSERT(heap);
49381 	DUK_ASSERT(hdr);
49382 
49383 	DUK_DDD(DUK_DDDPRINT("free heaphdr %p, htype %ld", (void *) hdr, (long) DUK_HEAPHDR_GET_TYPE(hdr)));
49384 
49385 	switch (DUK_HEAPHDR_GET_TYPE(hdr)) {
49386 	case DUK_HTYPE_STRING:
49387 		duk_free_hstring(heap, (duk_hstring *) hdr);
49388 		break;
49389 	case DUK_HTYPE_OBJECT:
49390 		duk_free_hobject(heap, (duk_hobject *) hdr);
49391 		break;
49392 	default:
49393 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) == DUK_HTYPE_BUFFER);
49394 		duk_free_hbuffer(heap, (duk_hbuffer *) hdr);
49395 	}
49396 
49397 }
49398 
49399 /*
49400  *  Free the heap.
49401  *
49402  *  Frees heap-related non-heap-tracked allocations such as the
49403  *  string intern table; then frees the heap allocated objects;
49404  *  and finally frees the heap structure itself.  Reference counts
49405  *  and GC markers are ignored (and not updated) in this process,
49406  *  and finalizers won't be called.
49407  *
49408  *  The heap pointer and heap object pointers must not be used
49409  *  after this call.
49410  */
49411 
49412 #if defined(DUK_USE_CACHE_ACTIVATION)
49413 DUK_LOCAL duk_size_t duk__heap_free_activation_freelist(duk_heap *heap) {
49414 	duk_activation *act;
49415 	duk_activation *act_next;
49416 	duk_size_t count_act = 0;
49417 
49418 	for (act = heap->activation_free; act != NULL;) {
49419 		act_next = act->parent;
49420 		DUK_FREE(heap, (void *) act);
49421 		act = act_next;
49422 #if defined(DUK_USE_DEBUG)
49423 		count_act++;
49424 #endif
49425 	}
49426 	heap->activation_free = NULL;  /* needed when called from mark-and-sweep */
49427 	return count_act;
49428 }
49429 #endif  /* DUK_USE_CACHE_ACTIVATION */
49430 
49431 #if defined(DUK_USE_CACHE_CATCHER)
49432 DUK_LOCAL duk_size_t duk__heap_free_catcher_freelist(duk_heap *heap) {
49433 	duk_catcher *cat;
49434 	duk_catcher *cat_next;
49435 	duk_size_t count_cat = 0;
49436 
49437 	for (cat = heap->catcher_free; cat != NULL;) {
49438 		cat_next = cat->parent;
49439 		DUK_FREE(heap, (void *) cat);
49440 		cat = cat_next;
49441 #if defined(DUK_USE_DEBUG)
49442 		count_cat++;
49443 #endif
49444 	}
49445 	heap->catcher_free = NULL;  /* needed when called from mark-and-sweep */
49446 
49447 	return count_cat;
49448 }
49449 #endif  /* DUK_USE_CACHE_CATCHER */
49450 
49451 DUK_INTERNAL void duk_heap_free_freelists(duk_heap *heap) {
49452 	duk_size_t count_act = 0;
49453 	duk_size_t count_cat = 0;
49454 
49455 #if defined(DUK_USE_CACHE_ACTIVATION)
49456 	count_act = duk__heap_free_activation_freelist(heap);
49457 #endif
49458 #if defined(DUK_USE_CACHE_CATCHER)
49459 	count_cat = duk__heap_free_catcher_freelist(heap);
49460 #endif
49461 	DUK_UNREF(heap);
49462 	DUK_UNREF(count_act);
49463 	DUK_UNREF(count_cat);
49464 
49465 	DUK_D(DUK_DPRINT("freed %ld activation freelist entries, %ld catcher freelist entries",
49466 	                 (long) count_act, (long) count_cat));
49467 }
49468 
49469 DUK_LOCAL void duk__free_allocated(duk_heap *heap) {
49470 	duk_heaphdr *curr;
49471 	duk_heaphdr *next;
49472 
49473 	curr = heap->heap_allocated;
49474 	while (curr) {
49475 		/* We don't log or warn about freeing zero refcount objects
49476 		 * because they may happen with finalizer processing.
49477 		 */
49478 
49479 		DUK_DDD(DUK_DDDPRINT("FINALFREE (allocated): %!iO",
49480 		                     (duk_heaphdr *) curr));
49481 		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
49482 		duk_heap_free_heaphdr_raw(heap, curr);
49483 		curr = next;
49484 	}
49485 }
49486 
49487 #if defined(DUK_USE_FINALIZER_SUPPORT)
49488 DUK_LOCAL void duk__free_finalize_list(duk_heap *heap) {
49489 	duk_heaphdr *curr;
49490 	duk_heaphdr *next;
49491 
49492 	curr = heap->finalize_list;
49493 	while (curr) {
49494 		DUK_DDD(DUK_DDDPRINT("FINALFREE (finalize_list): %!iO",
49495 		                     (duk_heaphdr *) curr));
49496 		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
49497 		duk_heap_free_heaphdr_raw(heap, curr);
49498 		curr = next;
49499 	}
49500 }
49501 #endif  /* DUK_USE_FINALIZER_SUPPORT */
49502 
49503 DUK_LOCAL void duk__free_stringtable(duk_heap *heap) {
49504 	/* strings are only tracked by stringtable */
49505 	duk_heap_strtable_free(heap);
49506 }
49507 
49508 #if defined(DUK_USE_FINALIZER_SUPPORT)
49509 DUK_LOCAL void duk__free_run_finalizers(duk_heap *heap) {
49510 	duk_heaphdr *curr;
49511 	duk_uint_t round_no;
49512 	duk_size_t count_all;
49513 	duk_size_t count_finalized;
49514 	duk_size_t curr_limit;
49515 
49516 	DUK_ASSERT(heap != NULL);
49517 
49518 #if defined(DUK_USE_REFERENCE_COUNTING)
49519 	DUK_ASSERT(heap->refzero_list == NULL);  /* refzero not running -> must be empty */
49520 #endif
49521 	DUK_ASSERT(heap->finalize_list == NULL);  /* mark-and-sweep last pass */
49522 
49523 	if (heap->heap_thread == NULL) {
49524 		/* May happen when heap allocation fails right off.  There
49525 		 * cannot be any finalizable objects in this case.
49526 		 */
49527 		DUK_D(DUK_DPRINT("no heap_thread in heap destruct, assume no finalizable objects"));
49528 		return;
49529 	}
49530 
49531 	/* Prevent finalize_list processing and mark-and-sweep entirely.
49532 	 * Setting ms_running != 0 also prevents refzero handling from moving
49533 	 * objects away from the heap_allocated list.  The flag name is a bit
49534 	 * misleading here.
49535 	 *
49536 	 * Use a distinct value for ms_running here (== 2) so that assertions
49537 	 * can detect this situation separate from the normal runtime
49538 	 * mark-and-sweep case.  This allows better assertions (GH-2030).
49539 	 */
49540 	DUK_ASSERT(heap->pf_prevent_count == 0);
49541 	DUK_ASSERT(heap->ms_running == 0);
49542 	DUK_ASSERT(heap->ms_prevent_count == 0);
49543 	heap->pf_prevent_count = 1;
49544 	heap->ms_running = 2;  /* Use distinguishable value. */
49545 	heap->ms_prevent_count = 1;  /* Bump, because mark-and-sweep assumes it's bumped when ms_running is set. */
49546 
49547 	curr_limit = 0;  /* suppress warning, not used */
49548 	for (round_no = 0; ; round_no++) {
49549 		curr = heap->heap_allocated;
49550 		count_all = 0;
49551 		count_finalized = 0;
49552 		while (curr) {
49553 			count_all++;
49554 			if (DUK_HEAPHDR_IS_OBJECT(curr)) {
49555 				/* Only objects in heap_allocated may have finalizers.  Check that
49556 				 * the object itself has a _Finalizer property (own or inherited)
49557 				 * so that we don't execute finalizers for e.g. Proxy objects.
49558 				 */
49559 				DUK_ASSERT(curr != NULL);
49560 
49561 				if (DUK_HOBJECT_HAS_FINALIZER_FAST(heap, (duk_hobject *) curr)) {
49562 					if (!DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) curr)) {
49563 						DUK_ASSERT(DUK_HEAP_HAS_FINALIZER_NORESCUE(heap));  /* maps to finalizer 2nd argument */
49564 						duk_heap_run_finalizer(heap, (duk_hobject *) curr);
49565 						count_finalized++;
49566 					}
49567 				}
49568 			}
49569 			curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
49570 		}
49571 
49572 		/* Each round of finalizer execution may spawn new finalizable objects
49573 		 * which is normal behavior for some applications.  Allow multiple
49574 		 * rounds of finalization, but use a shrinking limit based on the
49575 		 * first round to detect the case where a runaway finalizer creates
49576 		 * an unbounded amount of new finalizable objects.  Finalizer rescue
49577 		 * is not supported: the semantics are unclear because most of the
49578 		 * objects being finalized here are already reachable.  The finalizer
49579 		 * is given a boolean to indicate that rescue is not possible.
49580 		 *
49581 		 * See discussion in: https://github.com/svaarala/duktape/pull/473
49582 		 */
49583 
49584 		if (round_no == 0) {
49585 			/* Cannot wrap: each object is at least 8 bytes so count is
49586 			 * at most 1/8 of that.
49587 			 */
49588 			curr_limit = count_all * 2;
49589 		} else {
49590 			curr_limit = (curr_limit * 3) / 4;   /* Decrease by 25% every round */
49591 		}
49592 		DUK_D(DUK_DPRINT("finalizer round %ld complete, %ld objects, tried to execute %ld finalizers, current limit is %ld",
49593 		                 (long) round_no, (long) count_all, (long) count_finalized, (long) curr_limit));
49594 
49595 		if (count_finalized == 0) {
49596 			DUK_D(DUK_DPRINT("no more finalizable objects, forced finalization finished"));
49597 			break;
49598 		}
49599 		if (count_finalized >= curr_limit) {
49600 			DUK_D(DUK_DPRINT("finalizer count above limit, potentially runaway finalizer; skip remaining finalizers"));
49601 			break;
49602 		}
49603 	}
49604 
49605 	DUK_ASSERT(heap->ms_running == 2);
49606 	DUK_ASSERT(heap->pf_prevent_count == 1);
49607 	heap->ms_running = 0;
49608 	heap->pf_prevent_count = 0;
49609 }
49610 #endif  /* DUK_USE_FINALIZER_SUPPORT */
49611 
49612 DUK_INTERNAL void duk_heap_free(duk_heap *heap) {
49613 	DUK_D(DUK_DPRINT("free heap: %p", (void *) heap));
49614 
49615 #if defined(DUK_USE_DEBUG)
49616 	duk_heap_strtable_dump(heap);
49617 #endif
49618 
49619 #if defined(DUK_USE_DEBUGGER_SUPPORT)
49620 	/* Detach a debugger if attached (can be called multiple times)
49621 	 * safely.
49622 	 */
49623 	/* XXX: Add a flag to reject an attempt to re-attach?  Otherwise
49624 	 * the detached callback may immediately reattach.
49625 	 */
49626 	duk_debug_do_detach(heap);
49627 #endif
49628 
49629 	/* Execute finalizers before freeing the heap, even for reachable
49630 	 * objects.  This gives finalizers the chance to free any native
49631 	 * resources like file handles, allocations made outside Duktape,
49632 	 * etc.  This is quite tricky to get right, so that all finalizer
49633 	 * guarantees are honored.
49634 	 *
49635 	 * Run mark-and-sweep a few times just in case (unreachable object
49636 	 * finalizers run already here).  The last round must rescue objects
49637 	 * from the previous round without running any more finalizers.  This
49638 	 * ensures rescued objects get their FINALIZED flag cleared so that
49639 	 * their finalizer is called once more in forced finalization to
49640 	 * satisfy finalizer guarantees.  However, we don't want to run any
49641 	 * more finalizers because that'd required one more loop, and so on.
49642 	 *
49643 	 * XXX: this perhaps requires an execution time limit.
49644 	 */
49645 	DUK_D(DUK_DPRINT("execute finalizers before freeing heap"));
49646 	DUK_ASSERT(heap->pf_skip_finalizers == 0);
49647 	DUK_D(DUK_DPRINT("forced gc #1 in heap destruction"));
49648 	duk_heap_mark_and_sweep(heap, 0);
49649 	DUK_D(DUK_DPRINT("forced gc #2 in heap destruction"));
49650 	duk_heap_mark_and_sweep(heap, 0);
49651 	DUK_D(DUK_DPRINT("forced gc #3 in heap destruction (don't run finalizers)"));
49652 	heap->pf_skip_finalizers = 1;
49653 	duk_heap_mark_and_sweep(heap, 0);  /* Skip finalizers; queue finalizable objects to heap_allocated. */
49654 
49655 	/* There are never objects in refzero_list at this point, or at any
49656 	 * point beyond a DECREF (even a DECREF_NORZ).  Since Duktape 2.1
49657 	 * refzero_list processing is side effect free, so it is always
49658 	 * processed to completion by a DECREF initially triggering a zero
49659 	 * refcount.
49660 	 */
49661 #if defined(DUK_USE_REFERENCE_COUNTING)
49662 	DUK_ASSERT(heap->refzero_list == NULL);  /* Always processed to completion inline. */
49663 #endif
49664 #if defined(DUK_USE_FINALIZER_SUPPORT)
49665 	DUK_ASSERT(heap->finalize_list == NULL);  /* Last mark-and-sweep with skip_finalizers. */
49666 #endif
49667 
49668 #if defined(DUK_USE_FINALIZER_SUPPORT)
49669 	DUK_D(DUK_DPRINT("run finalizers for remaining finalizable objects"));
49670 	DUK_HEAP_SET_FINALIZER_NORESCUE(heap);  /* Rescue no longer supported. */
49671 	duk__free_run_finalizers(heap);
49672 #endif  /* DUK_USE_FINALIZER_SUPPORT */
49673 
49674 	/* Note: heap->heap_thread, heap->curr_thread, and heap->heap_object
49675 	 * are on the heap allocated list.
49676 	 */
49677 
49678 	DUK_D(DUK_DPRINT("freeing temporary freelists"));
49679 	duk_heap_free_freelists(heap);
49680 
49681 	DUK_D(DUK_DPRINT("freeing heap_allocated of heap: %p", (void *) heap));
49682 	duk__free_allocated(heap);
49683 
49684 #if defined(DUK_USE_REFERENCE_COUNTING)
49685 	DUK_ASSERT(heap->refzero_list == NULL);  /* Always processed to completion inline. */
49686 #endif
49687 
49688 #if defined(DUK_USE_FINALIZER_SUPPORT)
49689 	DUK_D(DUK_DPRINT("freeing finalize_list of heap: %p", (void *) heap));
49690 	duk__free_finalize_list(heap);
49691 #endif
49692 
49693 	DUK_D(DUK_DPRINT("freeing string table of heap: %p", (void *) heap));
49694 	duk__free_stringtable(heap);
49695 
49696 	DUK_D(DUK_DPRINT("freeing heap structure: %p", (void *) heap));
49697 	heap->free_func(heap->heap_udata, heap);
49698 }
49699 
49700 /*
49701  *  Allocate a heap.
49702  *
49703  *  String table is initialized with built-in strings from genbuiltins.py,
49704  *  either by dynamically creating the strings or by referring to ROM strings.
49705  */
49706 
49707 #if defined(DUK_USE_ROM_STRINGS)
49708 DUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap) {
49709 #if defined(DUK_USE_ASSERTIONS)
49710 	duk_small_uint_t i;
49711 #endif
49712 
49713 	DUK_UNREF(heap);
49714 
49715 	/* With ROM-based strings, heap->strs[] and thr->strs[] are omitted
49716 	 * so nothing to initialize for strs[].
49717 	 */
49718 
49719 #if defined(DUK_USE_ASSERTIONS)
49720 	for (i = 0; i < sizeof(duk_rom_strings_lookup) / sizeof(const duk_hstring *); i++) {
49721 		const duk_hstring *h;
49722 		duk_uint32_t hash;
49723 
49724 		h = duk_rom_strings_lookup[i];
49725 		while (h != NULL) {
49726 			hash = duk_heap_hashstring(heap, (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
49727 			DUK_DD(DUK_DDPRINT("duk_rom_strings_lookup[%d] -> hash 0x%08lx, computed 0x%08lx",
49728 			                   (int) i, (unsigned long) DUK_HSTRING_GET_HASH(h), (unsigned long) hash));
49729 			DUK_ASSERT(hash == (duk_uint32_t) DUK_HSTRING_GET_HASH(h));
49730 
49731 			h = (const duk_hstring *) h->hdr.h_next;
49732 		}
49733 	}
49734 #endif
49735 	return 1;
49736 }
49737 #else  /* DUK_USE_ROM_STRINGS */
49738 
49739 DUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap) {
49740 	duk_bitdecoder_ctx bd_ctx;
49741 	duk_bitdecoder_ctx *bd = &bd_ctx;  /* convenience */
49742 	duk_small_uint_t i;
49743 
49744 	duk_memzero(&bd_ctx, sizeof(bd_ctx));
49745 	bd->data = (const duk_uint8_t *) duk_strings_data;
49746 	bd->length = (duk_size_t) DUK_STRDATA_DATA_LENGTH;
49747 
49748 	for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
49749 		duk_uint8_t tmp[DUK_STRDATA_MAX_STRLEN];
49750 		duk_small_uint_t len;
49751 		duk_hstring *h;
49752 
49753 		len = duk_bd_decode_bitpacked_string(bd, tmp);
49754 
49755 		/* No need to length check string: it will never exceed even
49756 		 * the 16-bit length maximum.
49757 		 */
49758 		DUK_ASSERT(len <= 0xffffUL);
49759 		DUK_DDD(DUK_DDDPRINT("intern built-in string %ld", (long) i));
49760 		h = duk_heap_strtable_intern(heap, tmp, len);
49761 		if (!h) {
49762 			goto failed;
49763 		}
49764 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h));
49765 
49766 		/* Special flags checks.  Since these strings are always
49767 		 * reachable and a string cannot appear twice in the string
49768 		 * table, there's no need to check/set these flags elsewhere.
49769 		 * The 'internal' flag is set by string intern code.
49770 		 */
49771 		if (i == DUK_STRIDX_EVAL || i == DUK_STRIDX_LC_ARGUMENTS) {
49772 			DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(h);
49773 		}
49774 		if (i >= DUK_STRIDX_START_RESERVED && i < DUK_STRIDX_END_RESERVED) {
49775 			DUK_HSTRING_SET_RESERVED_WORD(h);
49776 			if (i >= DUK_STRIDX_START_STRICT_RESERVED) {
49777 				DUK_HSTRING_SET_STRICT_RESERVED_WORD(h);
49778 			}
49779 		}
49780 
49781 		DUK_DDD(DUK_DDDPRINT("interned: %!O", (duk_heaphdr *) h));
49782 
49783 		/* XXX: The incref macro takes a thread pointer but doesn't
49784 		 * use it right now.
49785 		 */
49786 		DUK_HSTRING_INCREF(_never_referenced_, h);
49787 
49788 #if defined(DUK_USE_HEAPPTR16)
49789 		heap->strs16[i] = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
49790 #else
49791 		heap->strs[i] = h;
49792 #endif
49793 	}
49794 
49795 	return 1;
49796 
49797  failed:
49798 	return 0;
49799 }
49800 #endif  /* DUK_USE_ROM_STRINGS */
49801 
49802 DUK_LOCAL duk_bool_t duk__init_heap_thread(duk_heap *heap) {
49803 	duk_hthread *thr;
49804 
49805 	DUK_D(DUK_DPRINT("heap init: alloc heap thread"));
49806 	thr = duk_hthread_alloc_unchecked(heap,
49807 	                                  DUK_HOBJECT_FLAG_EXTENSIBLE |
49808 	                                  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_THREAD));
49809 	if (thr == NULL) {
49810 		DUK_D(DUK_DPRINT("failed to alloc heap_thread"));
49811 		return 0;
49812 	}
49813 	thr->state = DUK_HTHREAD_STATE_INACTIVE;
49814 #if defined(DUK_USE_ROM_STRINGS)
49815 	/* No strs[] pointer. */
49816 #else  /* DUK_USE_ROM_STRINGS */
49817 #if defined(DUK_USE_HEAPPTR16)
49818 	thr->strs16 = heap->strs16;
49819 #else
49820 	thr->strs = heap->strs;
49821 #endif
49822 #endif  /* DUK_USE_ROM_STRINGS */
49823 
49824 	heap->heap_thread = thr;
49825 	DUK_HTHREAD_INCREF(thr, thr);  /* Note: first argument not really used */
49826 
49827 	/* 'thr' is now reachable */
49828 
49829 	DUK_D(DUK_DPRINT("heap init: init heap thread stacks"));
49830 	if (!duk_hthread_init_stacks(heap, thr)) {
49831 		return 0;
49832 	}
49833 
49834 	/* XXX: this may now fail, and is not handled correctly */
49835 	duk_hthread_create_builtin_objects(thr);
49836 
49837 	/* default prototype */
49838 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) thr, thr->builtins[DUK_BIDX_THREAD_PROTOTYPE]);
49839 
49840 	return 1;
49841 }
49842 
49843 #if defined(DUK_USE_DEBUG)
49844 #define DUK__DUMPSZ(t)  do { \
49845 		DUK_D(DUK_DPRINT("" #t "=%ld", (long) sizeof(t))); \
49846 	} while (0)
49847 
49848 /* These is not 100% because format would need to be non-portable "long long".
49849  * Also print out as doubles to catch cases where the "long" type is not wide
49850  * enough; the limits will then not be printed accurately but the magnitude
49851  * will be correct.
49852  */
49853 #define DUK__DUMPLM_SIGNED_RAW(t,a,b)  do { \
49854 		DUK_D(DUK_DPRINT(t "=[%ld,%ld]=[%lf,%lf]", \
49855 		                 (long) (a), (long) (b), \
49856 		                 (double) (a), (double) (b))); \
49857 	} while (0)
49858 #define DUK__DUMPLM_UNSIGNED_RAW(t,a,b)  do { \
49859 		DUK_D(DUK_DPRINT(t "=[%lu,%lu]=[%lf,%lf]", \
49860 		                 (unsigned long) (a), (unsigned long) (b), \
49861 		                 (double) (a), (double) (b))); \
49862 	} while (0)
49863 #define DUK__DUMPLM_SIGNED(t)  do { \
49864 		DUK__DUMPLM_SIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
49865 	} while (0)
49866 #define DUK__DUMPLM_UNSIGNED(t)  do { \
49867 		DUK__DUMPLM_UNSIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
49868 	} while (0)
49869 
49870 DUK_LOCAL void duk__dump_type_sizes(void) {
49871 	DUK_D(DUK_DPRINT("sizeof()"));
49872 
49873 	/* basic platform types */
49874 	DUK__DUMPSZ(char);
49875 	DUK__DUMPSZ(short);
49876 	DUK__DUMPSZ(int);
49877 	DUK__DUMPSZ(long);
49878 	DUK__DUMPSZ(double);
49879 	DUK__DUMPSZ(void *);
49880 	DUK__DUMPSZ(size_t);
49881 
49882 	/* basic types from duk_features.h */
49883 	DUK__DUMPSZ(duk_uint8_t);
49884 	DUK__DUMPSZ(duk_int8_t);
49885 	DUK__DUMPSZ(duk_uint16_t);
49886 	DUK__DUMPSZ(duk_int16_t);
49887 	DUK__DUMPSZ(duk_uint32_t);
49888 	DUK__DUMPSZ(duk_int32_t);
49889 	DUK__DUMPSZ(duk_uint64_t);
49890 	DUK__DUMPSZ(duk_int64_t);
49891 	DUK__DUMPSZ(duk_uint_least8_t);
49892 	DUK__DUMPSZ(duk_int_least8_t);
49893 	DUK__DUMPSZ(duk_uint_least16_t);
49894 	DUK__DUMPSZ(duk_int_least16_t);
49895 	DUK__DUMPSZ(duk_uint_least32_t);
49896 	DUK__DUMPSZ(duk_int_least32_t);
49897 #if defined(DUK_USE_64BIT_OPS)
49898 	DUK__DUMPSZ(duk_uint_least64_t);
49899 	DUK__DUMPSZ(duk_int_least64_t);
49900 #endif
49901 	DUK__DUMPSZ(duk_uint_fast8_t);
49902 	DUK__DUMPSZ(duk_int_fast8_t);
49903 	DUK__DUMPSZ(duk_uint_fast16_t);
49904 	DUK__DUMPSZ(duk_int_fast16_t);
49905 	DUK__DUMPSZ(duk_uint_fast32_t);
49906 	DUK__DUMPSZ(duk_int_fast32_t);
49907 #if defined(DUK_USE_64BIT_OPS)
49908 	DUK__DUMPSZ(duk_uint_fast64_t);
49909 	DUK__DUMPSZ(duk_int_fast64_t);
49910 #endif
49911 	DUK__DUMPSZ(duk_uintptr_t);
49912 	DUK__DUMPSZ(duk_intptr_t);
49913 	DUK__DUMPSZ(duk_uintmax_t);
49914 	DUK__DUMPSZ(duk_intmax_t);
49915 	DUK__DUMPSZ(duk_double_t);
49916 
49917 	/* important chosen base types */
49918 	DUK__DUMPSZ(duk_int_t);
49919 	DUK__DUMPSZ(duk_uint_t);
49920 	DUK__DUMPSZ(duk_int_fast_t);
49921 	DUK__DUMPSZ(duk_uint_fast_t);
49922 	DUK__DUMPSZ(duk_small_int_t);
49923 	DUK__DUMPSZ(duk_small_uint_t);
49924 	DUK__DUMPSZ(duk_small_int_fast_t);
49925 	DUK__DUMPSZ(duk_small_uint_fast_t);
49926 
49927 	/* some derived types */
49928 	DUK__DUMPSZ(duk_codepoint_t);
49929 	DUK__DUMPSZ(duk_ucodepoint_t);
49930 	DUK__DUMPSZ(duk_idx_t);
49931 	DUK__DUMPSZ(duk_errcode_t);
49932 	DUK__DUMPSZ(duk_uarridx_t);
49933 
49934 	/* tval */
49935 	DUK__DUMPSZ(duk_double_union);
49936 	DUK__DUMPSZ(duk_tval);
49937 
49938 	/* structs from duk_forwdecl.h */
49939 	DUK__DUMPSZ(duk_jmpbuf);  /* just one 'int' for C++ exceptions */
49940 	DUK__DUMPSZ(duk_heaphdr);
49941 	DUK__DUMPSZ(duk_heaphdr_string);
49942 	DUK__DUMPSZ(duk_hstring);
49943 	DUK__DUMPSZ(duk_hstring_external);
49944 	DUK__DUMPSZ(duk_hobject);
49945 	DUK__DUMPSZ(duk_harray);
49946 	DUK__DUMPSZ(duk_hcompfunc);
49947 	DUK__DUMPSZ(duk_hnatfunc);
49948 	DUK__DUMPSZ(duk_hdecenv);
49949 	DUK__DUMPSZ(duk_hobjenv);
49950 	DUK__DUMPSZ(duk_hthread);
49951 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
49952 	DUK__DUMPSZ(duk_hbufobj);
49953 #endif
49954 	DUK__DUMPSZ(duk_hproxy);
49955 	DUK__DUMPSZ(duk_hbuffer);
49956 	DUK__DUMPSZ(duk_hbuffer_fixed);
49957 	DUK__DUMPSZ(duk_hbuffer_dynamic);
49958 	DUK__DUMPSZ(duk_hbuffer_external);
49959 	DUK__DUMPSZ(duk_propaccessor);
49960 	DUK__DUMPSZ(duk_propvalue);
49961 	DUK__DUMPSZ(duk_propdesc);
49962 	DUK__DUMPSZ(duk_heap);
49963 	DUK__DUMPSZ(duk_activation);
49964 	DUK__DUMPSZ(duk_catcher);
49965 	DUK__DUMPSZ(duk_strcache_entry);
49966 	DUK__DUMPSZ(duk_litcache_entry);
49967 	DUK__DUMPSZ(duk_ljstate);
49968 	DUK__DUMPSZ(duk_fixedbuffer);
49969 	DUK__DUMPSZ(duk_bitdecoder_ctx);
49970 	DUK__DUMPSZ(duk_bitencoder_ctx);
49971 	DUK__DUMPSZ(duk_token);
49972 	DUK__DUMPSZ(duk_re_token);
49973 	DUK__DUMPSZ(duk_lexer_point);
49974 	DUK__DUMPSZ(duk_lexer_ctx);
49975 	DUK__DUMPSZ(duk_compiler_instr);
49976 	DUK__DUMPSZ(duk_compiler_func);
49977 	DUK__DUMPSZ(duk_compiler_ctx);
49978 	DUK__DUMPSZ(duk_re_matcher_ctx);
49979 	DUK__DUMPSZ(duk_re_compiler_ctx);
49980 }
49981 DUK_LOCAL void duk__dump_type_limits(void) {
49982 	DUK_D(DUK_DPRINT("limits"));
49983 
49984 	/* basic types */
49985 	DUK__DUMPLM_SIGNED(INT8);
49986 	DUK__DUMPLM_UNSIGNED(UINT8);
49987 	DUK__DUMPLM_SIGNED(INT_FAST8);
49988 	DUK__DUMPLM_UNSIGNED(UINT_FAST8);
49989 	DUK__DUMPLM_SIGNED(INT_LEAST8);
49990 	DUK__DUMPLM_UNSIGNED(UINT_LEAST8);
49991 	DUK__DUMPLM_SIGNED(INT16);
49992 	DUK__DUMPLM_UNSIGNED(UINT16);
49993 	DUK__DUMPLM_SIGNED(INT_FAST16);
49994 	DUK__DUMPLM_UNSIGNED(UINT_FAST16);
49995 	DUK__DUMPLM_SIGNED(INT_LEAST16);
49996 	DUK__DUMPLM_UNSIGNED(UINT_LEAST16);
49997 	DUK__DUMPLM_SIGNED(INT32);
49998 	DUK__DUMPLM_UNSIGNED(UINT32);
49999 	DUK__DUMPLM_SIGNED(INT_FAST32);
50000 	DUK__DUMPLM_UNSIGNED(UINT_FAST32);
50001 	DUK__DUMPLM_SIGNED(INT_LEAST32);
50002 	DUK__DUMPLM_UNSIGNED(UINT_LEAST32);
50003 #if defined(DUK_USE_64BIT_OPS)
50004 	DUK__DUMPLM_SIGNED(INT64);
50005 	DUK__DUMPLM_UNSIGNED(UINT64);
50006 	DUK__DUMPLM_SIGNED(INT_FAST64);
50007 	DUK__DUMPLM_UNSIGNED(UINT_FAST64);
50008 	DUK__DUMPLM_SIGNED(INT_LEAST64);
50009 	DUK__DUMPLM_UNSIGNED(UINT_LEAST64);
50010 #endif
50011 	DUK__DUMPLM_SIGNED(INTPTR);
50012 	DUK__DUMPLM_UNSIGNED(UINTPTR);
50013 	DUK__DUMPLM_SIGNED(INTMAX);
50014 	DUK__DUMPLM_UNSIGNED(UINTMAX);
50015 
50016 	/* derived types */
50017 	DUK__DUMPLM_SIGNED(INT);
50018 	DUK__DUMPLM_UNSIGNED(UINT);
50019 	DUK__DUMPLM_SIGNED(INT_FAST);
50020 	DUK__DUMPLM_UNSIGNED(UINT_FAST);
50021 	DUK__DUMPLM_SIGNED(SMALL_INT);
50022 	DUK__DUMPLM_UNSIGNED(SMALL_UINT);
50023 	DUK__DUMPLM_SIGNED(SMALL_INT_FAST);
50024 	DUK__DUMPLM_UNSIGNED(SMALL_UINT_FAST);
50025 }
50026 
50027 DUK_LOCAL void duk__dump_misc_options(void) {
50028 	DUK_D(DUK_DPRINT("DUK_VERSION: %ld", (long) DUK_VERSION));
50029 	DUK_D(DUK_DPRINT("DUK_GIT_DESCRIBE: %s", DUK_GIT_DESCRIBE));
50030 	DUK_D(DUK_DPRINT("OS string: %s", DUK_USE_OS_STRING));
50031 	DUK_D(DUK_DPRINT("architecture string: %s", DUK_USE_ARCH_STRING));
50032 	DUK_D(DUK_DPRINT("compiler string: %s", DUK_USE_COMPILER_STRING));
50033 	DUK_D(DUK_DPRINT("debug level: %ld", (long) DUK_USE_DEBUG_LEVEL));
50034 #if defined(DUK_USE_PACKED_TVAL)
50035 	DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: yes"));
50036 #else
50037 	DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: no"));
50038 #endif
50039 #if defined(DUK_USE_VARIADIC_MACROS)
50040 	DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: yes"));
50041 #else
50042 	DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: no"));
50043 #endif
50044 #if defined(DUK_USE_INTEGER_LE)
50045 	DUK_D(DUK_DPRINT("integer endianness: little"));
50046 #elif defined(DUK_USE_INTEGER_ME)
50047 	DUK_D(DUK_DPRINT("integer endianness: mixed"));
50048 #elif defined(DUK_USE_INTEGER_BE)
50049 	DUK_D(DUK_DPRINT("integer endianness: big"));
50050 #else
50051 	DUK_D(DUK_DPRINT("integer endianness: ???"));
50052 #endif
50053 #if defined(DUK_USE_DOUBLE_LE)
50054 	DUK_D(DUK_DPRINT("IEEE double endianness: little"));
50055 #elif defined(DUK_USE_DOUBLE_ME)
50056 	DUK_D(DUK_DPRINT("IEEE double endianness: mixed"));
50057 #elif defined(DUK_USE_DOUBLE_BE)
50058 	DUK_D(DUK_DPRINT("IEEE double endianness: big"));
50059 #else
50060 	DUK_D(DUK_DPRINT("IEEE double endianness: ???"));
50061 #endif
50062 }
50063 #endif  /* DUK_USE_DEBUG */
50064 
50065 DUK_INTERNAL
50066 duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
50067                          duk_realloc_function realloc_func,
50068                          duk_free_function free_func,
50069                          void *heap_udata,
50070                          duk_fatal_function fatal_func) {
50071 	duk_heap *res = NULL;
50072 	duk_uint32_t st_initsize;
50073 
50074 	DUK_D(DUK_DPRINT("allocate heap"));
50075 
50076 	/*
50077 	 *  Random config sanity asserts
50078 	 */
50079 
50080 	DUK_ASSERT(DUK_USE_STRTAB_MINSIZE >= 64);
50081 
50082 	DUK_ASSERT((DUK_HTYPE_STRING & 0x01U) == 0);
50083 	DUK_ASSERT((DUK_HTYPE_BUFFER & 0x01U) == 0);
50084 	DUK_ASSERT((DUK_HTYPE_OBJECT & 0x01U) == 1);  /* DUK_HEAPHDR_IS_OBJECT() relies ont his. */
50085 
50086 	/*
50087 	 *  Debug dump type sizes
50088 	 */
50089 
50090 #if defined(DUK_USE_DEBUG)
50091 	duk__dump_misc_options();
50092 	duk__dump_type_sizes();
50093 	duk__dump_type_limits();
50094 #endif
50095 
50096 	/*
50097 	 *  If selftests enabled, run them as early as possible.
50098 	 */
50099 
50100 #if defined(DUK_USE_SELF_TESTS)
50101 	DUK_D(DUK_DPRINT("run self tests"));
50102 	if (duk_selftest_run_tests(alloc_func, realloc_func, free_func, heap_udata) > 0) {
50103 		fatal_func(heap_udata, "self test(s) failed");
50104 	}
50105 	DUK_D(DUK_DPRINT("self tests passed"));
50106 #endif
50107 
50108 	/*
50109 	 *  Important assert-like checks that should be enabled even
50110 	 *  when assertions are otherwise not enabled.
50111 	 */
50112 
50113 #if defined(DUK_USE_EXEC_REGCONST_OPTIMIZE)
50114 	/* Can't check sizeof() using preprocessor so explicit check.
50115 	 * This will be optimized away in practice; unfortunately a
50116 	 * warning is generated on some compilers as a result.
50117 	 */
50118 #if defined(DUK_USE_PACKED_TVAL)
50119 	if (sizeof(duk_tval) != 8) {
50120 #else
50121 	if (sizeof(duk_tval) != 16) {
50122 #endif
50123 		fatal_func(heap_udata, "sizeof(duk_tval) not 8 or 16, cannot use DUK_USE_EXEC_REGCONST_OPTIMIZE option");
50124 	}
50125 #endif  /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
50126 
50127 	/*
50128 	 *  Computed values (e.g. INFINITY)
50129 	 */
50130 
50131 #if defined(DUK_USE_COMPUTED_NAN)
50132 	do {
50133 		/* Workaround for some exotic platforms where NAN is missing
50134 		 * and the expression (0.0 / 0.0) does NOT result in a NaN.
50135 		 * Such platforms use the global 'duk_computed_nan' which must
50136 		 * be initialized at runtime.  Use 'volatile' to ensure that
50137 		 * the compiler will actually do the computation and not try
50138 		 * to do constant folding which might result in the original
50139 		 * problem.
50140 		 */
50141 		volatile double dbl1 = 0.0;
50142 		volatile double dbl2 = 0.0;
50143 		duk_computed_nan = dbl1 / dbl2;
50144 	} while (0);
50145 #endif
50146 
50147 #if defined(DUK_USE_COMPUTED_INFINITY)
50148 	do {
50149 		/* Similar workaround for INFINITY. */
50150 		volatile double dbl1 = 1.0;
50151 		volatile double dbl2 = 0.0;
50152 		duk_computed_infinity = dbl1 / dbl2;
50153 	} while (0);
50154 #endif
50155 
50156 	/*
50157 	 *  Allocate heap struct
50158 	 *
50159 	 *  Use a raw call, all macros expect the heap to be initialized
50160 	 */
50161 
50162 #if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 1)
50163 	goto failed;
50164 #endif
50165 	DUK_D(DUK_DPRINT("alloc duk_heap object"));
50166 	res = (duk_heap *) alloc_func(heap_udata, sizeof(duk_heap));
50167 	if (!res) {
50168 		goto failed;
50169 	}
50170 
50171 	/*
50172 	 *  Zero the struct, and start initializing roughly in order
50173 	 */
50174 
50175 	duk_memzero(res, sizeof(*res));
50176 #if defined(DUK_USE_ASSERTIONS)
50177 	res->heap_initializing = 1;
50178 #endif
50179 
50180 	/* explicit NULL inits */
50181 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
50182 	res->heap_udata = NULL;
50183 	res->heap_allocated = NULL;
50184 #if defined(DUK_USE_REFERENCE_COUNTING)
50185 	res->refzero_list = NULL;
50186 #endif
50187 #if defined(DUK_USE_FINALIZER_SUPPORT)
50188 	res->finalize_list = NULL;
50189 #if defined(DUK_USE_ASSERTIONS)
50190 	res->currently_finalizing = NULL;
50191 #endif
50192 #endif
50193 #if defined(DUK_USE_CACHE_ACTIVATION)
50194 	res->activation_free = NULL;
50195 #endif
50196 #if defined(DUK_USE_CACHE_CATCHER)
50197 	res->catcher_free = NULL;
50198 #endif
50199 	res->heap_thread = NULL;
50200 	res->curr_thread = NULL;
50201 	res->heap_object = NULL;
50202 #if defined(DUK_USE_STRTAB_PTRCOMP)
50203 	res->strtable16 = NULL;
50204 #else
50205 	res->strtable = NULL;
50206 #endif
50207 #if defined(DUK_USE_ROM_STRINGS)
50208 	/* no res->strs[] */
50209 #else  /* DUK_USE_ROM_STRINGS */
50210 #if defined(DUK_USE_HEAPPTR16)
50211 	/* res->strs16[] is zeroed and zero decodes to NULL, so no NULL inits. */
50212 #else
50213 	{
50214 		duk_small_uint_t i;
50215 	        for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
50216 			res->strs[i] = NULL;
50217 	        }
50218 	}
50219 #endif
50220 #endif  /* DUK_USE_ROM_STRINGS */
50221 #if defined(DUK_USE_DEBUGGER_SUPPORT)
50222 	res->dbg_read_cb = NULL;
50223 	res->dbg_write_cb = NULL;
50224 	res->dbg_peek_cb = NULL;
50225 	res->dbg_read_flush_cb = NULL;
50226 	res->dbg_write_flush_cb = NULL;
50227 	res->dbg_request_cb = NULL;
50228 	res->dbg_udata = NULL;
50229 	res->dbg_pause_act = NULL;
50230 #endif
50231 #endif  /* DUK_USE_EXPLICIT_NULL_INIT */
50232 
50233 	res->alloc_func = alloc_func;
50234 	res->realloc_func = realloc_func;
50235 	res->free_func = free_func;
50236 	res->heap_udata = heap_udata;
50237 	res->fatal_func = fatal_func;
50238 
50239 	/* XXX: for now there's a pointer packing zero assumption, i.e.
50240 	 * NULL <=> compressed pointer 0.  If this is removed, may need
50241 	 * to precompute e.g. null16 here.
50242 	 */
50243 
50244 	/* res->ms_trigger_counter == 0 -> now causes immediate GC; which is OK */
50245 
50246 	/* Prevent mark-and-sweep and finalizer execution until heap is completely
50247 	 * initialized.
50248 	 */
50249 	DUK_ASSERT(res->ms_prevent_count == 0);
50250 	DUK_ASSERT(res->pf_prevent_count == 0);
50251 	res->ms_prevent_count = 1;
50252 	res->pf_prevent_count = 1;
50253 	DUK_ASSERT(res->ms_running == 0);
50254 
50255 	res->call_recursion_depth = 0;
50256 	res->call_recursion_limit = DUK_USE_NATIVE_CALL_RECLIMIT;
50257 
50258 	/* XXX: use the pointer as a seed for now: mix in time at least */
50259 
50260 	/* The casts through duk_uintptr_t is to avoid the following GCC warning:
50261 	 *
50262 	 *   warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
50263 	 *
50264 	 * This still generates a /Wp64 warning on VS2010 when compiling for x86.
50265 	 */
50266 #if defined(DUK_USE_ROM_STRINGS)
50267 	/* XXX: make a common DUK_USE_ option, and allow custom fixed seed? */
50268 	DUK_D(DUK_DPRINT("using rom strings, force heap hash_seed to fixed value 0x%08lx", (long) DUK__FIXED_HASH_SEED));
50269 	res->hash_seed = (duk_uint32_t) DUK__FIXED_HASH_SEED;
50270 #else  /* DUK_USE_ROM_STRINGS */
50271 	res->hash_seed = (duk_uint32_t) (duk_uintptr_t) res;
50272 #if !defined(DUK_USE_STRHASH_DENSE)
50273 	res->hash_seed ^= 5381;  /* Bernstein hash init value is normally 5381; XOR it in in case pointer low bits are 0 */
50274 #endif
50275 #endif  /* DUK_USE_ROM_STRINGS */
50276 
50277 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
50278 	res->lj.jmpbuf_ptr = NULL;
50279 #endif
50280 	DUK_ASSERT(res->lj.type == DUK_LJ_TYPE_UNKNOWN);  /* zero */
50281 	DUK_ASSERT(res->lj.iserror == 0);
50282 	DUK_TVAL_SET_UNDEFINED(&res->lj.value1);
50283 	DUK_TVAL_SET_UNDEFINED(&res->lj.value2);
50284 
50285 	DUK_ASSERT_LJSTATE_UNSET(res);
50286 
50287 	/*
50288 	 *  Init stringtable: fixed variant
50289 	 */
50290 
50291 	st_initsize = DUK_USE_STRTAB_MINSIZE;
50292 #if defined(DUK_USE_STRTAB_PTRCOMP)
50293 	res->strtable16 = (duk_uint16_t *) alloc_func(heap_udata, sizeof(duk_uint16_t) * st_initsize);
50294 	if (res->strtable16 == NULL) {
50295 		goto failed;
50296 	}
50297 #else
50298 	res->strtable = (duk_hstring **) alloc_func(heap_udata, sizeof(duk_hstring *) * st_initsize);
50299 	if (res->strtable == NULL) {
50300 		goto failed;
50301 	}
50302 #endif
50303 	res->st_size = st_initsize;
50304 	res->st_mask = st_initsize - 1;
50305 #if (DUK_USE_STRTAB_MINSIZE != DUK_USE_STRTAB_MAXSIZE)
50306 	DUK_ASSERT(res->st_count == 0);
50307 #endif
50308 
50309 #if defined(DUK_USE_STRTAB_PTRCOMP)
50310 	/* zero assumption */
50311 	duk_memzero(res->strtable16, sizeof(duk_uint16_t) * st_initsize);
50312 #else
50313 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
50314 	{
50315 		duk_uint32_t i;
50316 	        for (i = 0; i < st_initsize; i++) {
50317 			res->strtable[i] = NULL;
50318 	        }
50319 	}
50320 #else
50321 	duk_memzero(res->strtable, sizeof(duk_hstring *) * st_initsize);
50322 #endif  /* DUK_USE_EXPLICIT_NULL_INIT */
50323 #endif  /* DUK_USE_STRTAB_PTRCOMP */
50324 
50325 	/*
50326 	 *  Init stringcache
50327 	 */
50328 
50329 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
50330 	{
50331 		duk_uint_t i;
50332 		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
50333 			res->strcache[i].h = NULL;
50334 		}
50335 	}
50336 #endif
50337 
50338 	/*
50339 	 *  Init litcache
50340 	 */
50341 #if defined(DUK_USE_LITCACHE_SIZE)
50342 	DUK_ASSERT(DUK_USE_LITCACHE_SIZE > 0);
50343 	DUK_ASSERT(DUK_IS_POWER_OF_TWO((duk_uint_t) DUK_USE_LITCACHE_SIZE));
50344 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
50345 	{
50346 		duk_uint_t i;
50347 		for (i = 0; i < DUK_USE_LITCACHE_SIZE; i++) {
50348 			res->litcache[i].addr = NULL;
50349 			res->litcache[i].h = NULL;
50350 		}
50351 	}
50352 #endif
50353 #endif  /* DUK_USE_LITCACHE_SIZE */
50354 
50355 	/* XXX: error handling is incomplete.  It would be cleanest if
50356 	 * there was a setjmp catchpoint, so that all init code could
50357 	 * freely throw errors.  If that were the case, the return code
50358 	 * passing here could be removed.
50359 	 */
50360 
50361 	/*
50362 	 *  Init built-in strings
50363 	 */
50364 
50365 #if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 2)
50366 	goto failed;
50367 #endif
50368 	DUK_D(DUK_DPRINT("heap init: initialize heap strings"));
50369 	if (!duk__init_heap_strings(res)) {
50370 		goto failed;
50371 	}
50372 
50373 	/*
50374 	 *  Init the heap thread
50375 	 */
50376 
50377 #if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 3)
50378 	goto failed;
50379 #endif
50380 	DUK_D(DUK_DPRINT("heap init: initialize heap thread"));
50381 	if (!duk__init_heap_thread(res)) {
50382 		goto failed;
50383 	}
50384 
50385 	/*
50386 	 *  Init the heap object
50387 	 */
50388 
50389 #if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 4)
50390 	goto failed;
50391 #endif
50392 	DUK_D(DUK_DPRINT("heap init: initialize heap object"));
50393 	DUK_ASSERT(res->heap_thread != NULL);
50394 	res->heap_object = duk_hobject_alloc_unchecked(res, DUK_HOBJECT_FLAG_EXTENSIBLE |
50395 	                                                    DUK_HOBJECT_FLAG_FASTREFS |
50396 	                                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT));
50397 	if (res->heap_object == NULL) {
50398 		goto failed;
50399 	}
50400 	DUK_HOBJECT_INCREF(res->heap_thread, res->heap_object);
50401 
50402 	/*
50403 	 *  Odds and ends depending on the heap thread
50404 	 */
50405 
50406 #if !defined(DUK_USE_GET_RANDOM_DOUBLE)
50407 #if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)
50408 	res->rnd_state = (duk_uint32_t) duk_time_get_ecmascript_time(res->heap_thread);
50409 	duk_util_tinyrandom_prepare_seed(res->heap_thread);
50410 #else
50411 	res->rnd_state[0] = (duk_uint64_t) duk_time_get_ecmascript_time(res->heap_thread);
50412 	DUK_ASSERT(res->rnd_state[1] == 0);  /* Not filled here, filled in by seed preparation. */
50413 #if 0  /* Manual test values matching misc/xoroshiro128plus_test.c. */
50414 	res->rnd_state[0] = DUK_U64_CONSTANT(0xdeadbeef12345678);
50415 	res->rnd_state[1] = DUK_U64_CONSTANT(0xcafed00d12345678);
50416 #endif
50417 	duk_util_tinyrandom_prepare_seed(res->heap_thread);
50418 	/* Mix in heap pointer: this ensures that if two Duktape heaps are
50419 	 * created on the same millisecond, they get a different PRNG
50420 	 * sequence (unless e.g. virtual memory addresses cause also the
50421 	 * heap object pointer to be the same).
50422 	 */
50423 	{
50424 		duk_uint64_t tmp_u64;
50425 		tmp_u64 = 0;
50426 		duk_memcpy((void *) &tmp_u64,
50427 		           (const void *) &res,
50428 		           (size_t) (sizeof(void *) >= sizeof(duk_uint64_t) ? sizeof(duk_uint64_t) : sizeof(void *)));
50429 		res->rnd_state[1] ^= tmp_u64;
50430 	}
50431 	do {
50432 		duk_small_uint_t i;
50433 		for (i = 0; i < 10; i++) {
50434 			/* Throw away a few initial random numbers just in
50435 			 * case.  Probably unnecessary due to SplitMix64
50436 			 * preparation.
50437 			 */
50438 			(void) duk_util_tinyrandom_get_double(res->heap_thread);
50439 		}
50440 	} while (0);
50441 #endif
50442 #endif
50443 
50444 	/*
50445 	 *  Allow finalizer and mark-and-sweep processing.
50446 	 */
50447 
50448 	DUK_D(DUK_DPRINT("heap init: allow finalizer/mark-and-sweep processing"));
50449 	DUK_ASSERT(res->ms_prevent_count == 1);
50450 	DUK_ASSERT(res->pf_prevent_count == 1);
50451 	res->ms_prevent_count = 0;
50452 	res->pf_prevent_count = 0;
50453 	DUK_ASSERT(res->ms_running == 0);
50454 #if defined(DUK_USE_ASSERTIONS)
50455 	res->heap_initializing = 0;
50456 #endif
50457 
50458 	/*
50459 	 *  All done.
50460 	 */
50461 
50462 	DUK_D(DUK_DPRINT("allocated heap: %p", (void *) res));
50463 	return res;
50464 
50465  failed:
50466 	DUK_D(DUK_DPRINT("heap allocation failed"));
50467 
50468 	if (res != NULL) {
50469 		/* Assumes that allocated pointers and alloc funcs are valid
50470 		 * if res exists.
50471 		 */
50472 		DUK_ASSERT(res->ms_prevent_count == 1);
50473 		DUK_ASSERT(res->pf_prevent_count == 1);
50474 		DUK_ASSERT(res->ms_running == 0);
50475 		if (res->heap_thread != NULL) {
50476 			res->ms_prevent_count = 0;
50477 			res->pf_prevent_count = 0;
50478 		}
50479 #if defined(DUK_USE_ASSERTIONS)
50480 		res->heap_initializing = 0;
50481 #endif
50482 
50483 		DUK_ASSERT(res->alloc_func != NULL);
50484 		DUK_ASSERT(res->realloc_func != NULL);
50485 		DUK_ASSERT(res->free_func != NULL);
50486 		duk_heap_free(res);
50487 	}
50488 
50489 	return NULL;
50490 }
50491 
50492 /* automatic undefs */
50493 #undef DUK__DUMPLM_SIGNED
50494 #undef DUK__DUMPLM_SIGNED_RAW
50495 #undef DUK__DUMPLM_UNSIGNED
50496 #undef DUK__DUMPLM_UNSIGNED_RAW
50497 #undef DUK__DUMPSZ
50498 #undef DUK__FIXED_HASH_SEED
50499 /*
50500  *  Finalizer handling.
50501  */
50502 
50503 /* #include duk_internal.h -> already included */
50504 
50505 #if defined(DUK_USE_FINALIZER_SUPPORT)
50506 
50507 /*
50508  *  Fake torture finalizer.
50509  */
50510 
50511 #if defined(DUK_USE_FINALIZER_TORTURE)
50512 DUK_LOCAL duk_ret_t duk__fake_global_finalizer(duk_hthread *thr) {
50513 	DUK_DD(DUK_DDPRINT("fake global torture finalizer executed"));
50514 
50515 	/* Require a lot of stack to force a value stack grow/shrink. */
50516 	duk_require_stack(thr, 100000);
50517 
50518 	/* Force a reallocation with pointer change for value stack
50519 	 * to maximize side effects.
50520 	 */
50521 	duk_hthread_valstack_torture_realloc(thr);
50522 
50523 	/* Inner function call, error throw. */
50524 	duk_eval_string_noresult(thr,
50525 		"(function dummy() {\n"
50526 		"    dummy.prototype = null;  /* break reference loop */\n"
50527 		"    try {\n"
50528 		"        throw 'fake-finalizer-dummy-error';\n"
50529 		"    } catch (e) {\n"
50530 		"        void e;\n"
50531 		"    }\n"
50532 		"})()");
50533 
50534 	/* The above creates garbage (e.g. a function instance).  Because
50535 	 * the function/prototype reference loop is broken, it gets collected
50536 	 * immediately by DECREF.  If Function.prototype has a _Finalizer
50537 	 * property (happens in some test cases), the garbage gets queued to
50538 	 * finalize_list.  This still won't cause an infinite loop because
50539 	 * the torture finalizer is called once per finalize_list run and
50540 	 * the garbage gets handled in the same run.  (If the garbage needs
50541 	 * mark-and-sweep collection, an infinite loop might ensue.)
50542 	 */
50543 	return 0;
50544 }
50545 
50546 DUK_LOCAL void duk__run_global_torture_finalizer(duk_hthread *thr) {
50547 	DUK_ASSERT(thr != NULL);
50548 
50549 	/* Avoid fake finalization when callstack limit is near.  Otherwise
50550 	 * a callstack limit error will be created, then refzero'ed.  The
50551 	 * +5 headroom is conservative.
50552 	 */
50553 	if (thr->heap->call_recursion_depth + 5 >= thr->heap->call_recursion_limit ||
50554 	    thr->callstack_top + 5 >= DUK_USE_CALLSTACK_LIMIT) {
50555 		DUK_D(DUK_DPRINT("skip global torture finalizer, too little headroom for call recursion or call stack size"));
50556 		return;
50557 	}
50558 
50559 	/* Run fake finalizer.  Avoid creating unnecessary garbage. */
50560 	duk_push_c_function(thr, duk__fake_global_finalizer, 0 /*nargs*/);
50561 	(void) duk_pcall(thr, 0 /*nargs*/);
50562 	duk_pop(thr);
50563 }
50564 #endif  /* DUK_USE_FINALIZER_TORTURE */
50565 
50566 /*
50567  *  Process the finalize_list to completion.
50568  *
50569  *  An object may be placed on finalize_list by either refcounting or
50570  *  mark-and-sweep.  The refcount of objects placed by refcounting will be
50571  *  zero; the refcount of objects placed by mark-and-sweep is > 0.  In both
50572  *  cases the refcount is bumped by 1 artificially so that a REFZERO event
50573  *  can never happen while an object is waiting for finalization.  Without
50574  *  this bump a REFZERO could now happen because user code may call
50575  *  duk_push_heapptr() and then pop a value even when it's on finalize_list.
50576  *
50577  *  List processing assumes refcounts are kept up-to-date at all times, so
50578  *  that once the finalizer returns, a zero refcount is a reliable reason to
50579  *  free the object immediately rather than place it back to the heap.  This
50580  *  is the case because we run outside of refzero_list processing so that
50581  *  DECREF cascades are handled fully inline.
50582  *
50583  *  For mark-and-sweep queued objects (had_zero_refcount false) the object
50584  *  may be freed immediately if its refcount is zero after the finalizer call
50585  *  (i.e. finalizer removed the reference loop for the object).  If not, the
50586  *  next mark-and-sweep will collect the object unless it has become reachable
50587  *  (i.e. rescued) by that time and its refcount hasn't fallen to zero before
50588  *  that.  Mark-and-sweep detects these objects because their FINALIZED flag
50589  *  is set.
50590  *
50591  *  There's an inherent limitation for mark-and-sweep finalizer rescuing: an
50592  *  object won't get refinalized if (1) it's rescued, but (2) becomes
50593  *  unreachable before mark-and-sweep has had time to notice it.  The next
50594  *  mark-and-sweep round simply doesn't have any information of whether the
50595  *  object has been unreachable the whole time or not (the only way to get
50596  *  that information would be a mark-and-sweep pass for *every finalized
50597  *  object*).  This is awkward for the application because the mark-and-sweep
50598  *  round is not generally visible or under full application control.
50599  *
50600  *  For refcount queued objects (had_zero_refcount true) the object is either
50601  *  immediately freed or rescued, and waiting for a mark-and-sweep round is not
50602  *  necessary (or desirable); FINALIZED is cleared when a rescued object is
50603  *  queued back to heap_allocated.  The object is eligible for finalization
50604  *  again (either via refcounting or mark-and-sweep) immediately after being
50605  *  rescued.  If a refcount finalized object is placed into an unreachable
50606  *  reference loop by its finalizer, it will get collected by mark-and-sweep
50607  *  and currently the finalizer will execute again.
50608  *
50609  *  There's a special case where:
50610  *
50611  *    - Mark-and-sweep queues an object to finalize_list for finalization.
50612  *    - The finalizer is executed, FINALIZED is set, and object is queued
50613  *      back to heap_allocated, waiting for a new mark-and-sweep round.
50614  *    - The object's refcount drops to zero before mark-and-sweep has a
50615  *      chance to run another round and make a rescue/free decision.
50616  *
50617  *  This is now handled by refzero code: if an object has a finalizer but
50618  *  FINALIZED is already set, the object is freed without finalizer processing.
50619  *  The outcome is the same as if mark-and-sweep was executed at that point;
50620  *  mark-and-sweep would also free the object without another finalizer run.
50621  *  This could also be changed so that the refzero-triggered finalizer *IS*
50622  *  executed: being refzero collected implies someone has operated on the
50623  *  object so it hasn't been totally unreachable the whole time.  This would
50624  *  risk a finalizer loop however.
50625  */
50626 
50627 DUK_INTERNAL void duk_heap_process_finalize_list(duk_heap *heap) {
50628 	duk_heaphdr *curr;
50629 #if defined(DUK_USE_DEBUG)
50630 	duk_size_t count = 0;
50631 #endif
50632 
50633 	DUK_DDD(DUK_DDDPRINT("duk_heap_process_finalize_list: %p", (void *) heap));
50634 
50635 	if (heap->pf_prevent_count != 0) {
50636 		DUK_DDD(DUK_DDDPRINT("skip finalize_list processing: pf_prevent_count != 0"));
50637 		return;
50638 	}
50639 
50640 	/* Heap alloc prevents mark-and-sweep before heap_thread is ready. */
50641 	DUK_ASSERT(heap != NULL);
50642 	DUK_ASSERT(heap->heap_thread != NULL);
50643 	DUK_ASSERT(heap->heap_thread->valstack != NULL);
50644 #if defined(DUK_USE_REFERENCE_COUNTING)
50645 	DUK_ASSERT(heap->refzero_list == NULL);
50646 #endif
50647 
50648 	DUK_ASSERT(heap->pf_prevent_count == 0);
50649 	heap->pf_prevent_count = 1;
50650 
50651 	/* Mark-and-sweep no longer needs to be prevented when running
50652 	 * finalizers: mark-and-sweep skips any rescue decisions if there
50653 	 * are any objects in finalize_list when mark-and-sweep is entered.
50654 	 * This protects finalized objects from incorrect rescue decisions
50655 	 * caused by finalize_list being a reachability root and only
50656 	 * partially processed.  Freeing decisions are not postponed.
50657 	 */
50658 
50659 	/* When finalizer torture is enabled, make a fake finalizer call with
50660 	 * maximum side effects regardless of whether finalize_list is empty.
50661 	 */
50662 #if defined(DUK_USE_FINALIZER_TORTURE)
50663 	duk__run_global_torture_finalizer(heap->heap_thread);
50664 #endif
50665 
50666 	/* Process finalize_list until it becomes empty.  There's currently no
50667 	 * protection against a finalizer always creating more garbage.
50668 	 */
50669 	while ((curr = heap->finalize_list) != NULL) {
50670 #if defined(DUK_USE_REFERENCE_COUNTING)
50671 		duk_bool_t queue_back;
50672 #endif
50673 
50674 		DUK_DD(DUK_DDPRINT("processing finalize_list entry: %p -> %!iO", (void *) curr, curr));
50675 
50676 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);  /* Only objects have finalizers. */
50677 		DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(curr));
50678 		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(curr));
50679 		DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZABLE(curr));  /* All objects on finalize_list will have this flag (except object being finalized right now). */
50680 		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));   /* Queueing code ensures. */
50681 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(curr));  /* ROM objects never get freed (or finalized). */
50682 
50683 #if defined(DUK_USE_ASSERTIONS)
50684 		DUK_ASSERT(heap->currently_finalizing == NULL);
50685 		heap->currently_finalizing = curr;
50686 #endif
50687 
50688 		/* Clear FINALIZABLE for object being finalized, so that
50689 		 * duk_push_heapptr() can properly ignore the object.
50690 		 */
50691 		DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);
50692 
50693 		if (DUK_LIKELY(!heap->pf_skip_finalizers)) {
50694 			/* Run the finalizer, duk_heap_run_finalizer() sets
50695 			 * and checks for FINALIZED to prevent the finalizer
50696 			 * from executing multiple times per finalization cycle.
50697 			 * (This safeguard shouldn't be actually needed anymore).
50698 			 */
50699 
50700 #if defined(DUK_USE_REFERENCE_COUNTING)
50701 			duk_bool_t had_zero_refcount;
50702 #endif
50703 
50704 			/* The object's refcount is >0 throughout so it won't be
50705 			 * refzero processed prematurely.
50706 			 */
50707 #if defined(DUK_USE_REFERENCE_COUNTING)
50708 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) >= 1);
50709 			had_zero_refcount = (DUK_HEAPHDR_GET_REFCOUNT(curr) == 1);  /* Preincremented on finalize_list insert. */
50710 #endif
50711 
50712 			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
50713 			duk_heap_run_finalizer(heap, (duk_hobject *) curr);  /* must never longjmp */
50714 			DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZED(curr));
50715 			/* XXX: assert that object is still in finalize_list
50716 			 * when duk_push_heapptr() allows automatic rescue.
50717 			 */
50718 
50719 #if defined(DUK_USE_REFERENCE_COUNTING)
50720 			DUK_DD(DUK_DDPRINT("refcount after finalizer (includes bump): %ld", (long) DUK_HEAPHDR_GET_REFCOUNT(curr)));
50721 			if (DUK_HEAPHDR_GET_REFCOUNT(curr) == 1) {  /* Only artificial bump in refcount? */
50722 #if defined(DUK_USE_DEBUG)
50723 				if (had_zero_refcount) {
50724 					DUK_DD(DUK_DDPRINT("finalized object's refcount is zero -> free immediately (refcount queued)"));
50725 				} else {
50726 					DUK_DD(DUK_DDPRINT("finalized object's refcount is zero -> free immediately (mark-and-sweep queued)"));
50727 				}
50728 #endif
50729 				queue_back = 0;
50730 			} else
50731 #endif
50732 			{
50733 #if defined(DUK_USE_REFERENCE_COUNTING)
50734 				queue_back = 1;
50735 				if (had_zero_refcount) {
50736 					/* When finalization is triggered
50737 					 * by refzero and we queue the object
50738 					 * back, clear FINALIZED right away
50739 					 * so that the object can be refinalized
50740 					 * immediately if necessary.
50741 					 */
50742 					DUK_HEAPHDR_CLEAR_FINALIZED(curr);
50743 				}
50744 #endif
50745 			}
50746 		} else {
50747 			/* Used during heap destruction: don't actually run finalizers
50748 			 * because we're heading into forced finalization.  Instead,
50749 			 * queue finalizable objects back to the heap_allocated list.
50750 			 */
50751 			DUK_D(DUK_DPRINT("skip finalizers flag set, queue object to heap_allocated without finalizing"));
50752 			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
50753 #if defined(DUK_USE_REFERENCE_COUNTING)
50754 			queue_back = 1;
50755 #endif
50756 		}
50757 
50758 		/* Dequeue object from finalize_list.  Note that 'curr' may no
50759 		 * longer be finalize_list head because new objects may have
50760 		 * been queued to the list.  As a result we can't optimize for
50761 		 * the single-linked heap case and must scan the list for
50762 		 * removal, typically the scan is very short however.
50763 		 */
50764 		DUK_HEAP_REMOVE_FROM_FINALIZE_LIST(heap, curr);
50765 
50766 		/* Queue back to heap_allocated or free immediately. */
50767 #if defined(DUK_USE_REFERENCE_COUNTING)
50768 		if (queue_back) {
50769 			/* FINALIZED is only cleared if object originally
50770 			 * queued for finalization by refcounting.  For
50771 			 * mark-and-sweep FINALIZED is left set, so that
50772 			 * next mark-and-sweep round can make a rescue/free
50773 			 * decision.
50774 			 */
50775 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) >= 1);
50776 			DUK_HEAPHDR_PREDEC_REFCOUNT(curr);  /* Remove artificial refcount bump. */
50777 			DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);
50778 			DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, curr);
50779 		} else {
50780 			/* No need to remove the refcount bump here. */
50781 			DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);  /* currently, always the case */
50782 			DUK_DD(DUK_DDPRINT("refcount finalize after finalizer call: %!O", curr));
50783 			duk_hobject_refcount_finalize_norz(heap, (duk_hobject *) curr);
50784 			duk_free_hobject(heap, (duk_hobject *) curr);
50785 			DUK_DD(DUK_DDPRINT("freed hobject after finalization: %p", (void *) curr));
50786 		}
50787 #else  /* DUK_USE_REFERENCE_COUNTING */
50788 		DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);
50789 		DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, curr);
50790 #endif  /* DUK_USE_REFERENCE_COUNTING */
50791 
50792 #if defined(DUK_USE_DEBUG)
50793 		count++;
50794 #endif
50795 
50796 #if defined(DUK_USE_ASSERTIONS)
50797 		DUK_ASSERT(heap->currently_finalizing != NULL);
50798 		heap->currently_finalizing = NULL;
50799 #endif
50800 	}
50801 
50802 	/* finalize_list will always be processed completely. */
50803 	DUK_ASSERT(heap->finalize_list == NULL);
50804 
50805 #if 0
50806 	/* While NORZ macros are used above, this is unnecessary because the
50807 	 * only pending side effects are now finalizers, and finalize_list is
50808 	 * empty.
50809 	 */
50810 	DUK_REFZERO_CHECK_SLOW(heap->heap_thread);
50811 #endif
50812 
50813 	/* Prevent count may be bumped while finalizers run, but should always
50814 	 * be reliably unbumped by the time we get here.
50815 	 */
50816 	DUK_ASSERT(heap->pf_prevent_count == 1);
50817 	heap->pf_prevent_count = 0;
50818 
50819 #if defined(DUK_USE_DEBUG)
50820 	DUK_DD(DUK_DDPRINT("duk_heap_process_finalize_list: %ld finalizers called", (long) count));
50821 #endif
50822 }
50823 
50824 /*
50825  *  Run an duk_hobject finalizer.  Must never throw an uncaught error
50826  *  (but may throw caught errors).
50827  *
50828  *  There is no return value.  Any return value or error thrown by
50829  *  the finalizer is ignored (although errors are debug logged).
50830  *
50831  *  Notes:
50832  *
50833  *    - The finalizer thread 'top' assertions are there because it is
50834  *      critical that strict stack policy is observed (i.e. no cruft
50835  *      left on the finalizer stack).
50836  */
50837 
50838 DUK_LOCAL duk_ret_t duk__finalize_helper(duk_hthread *thr, void *udata) {
50839 	DUK_ASSERT(thr != NULL);
50840 	DUK_UNREF(udata);
50841 
50842 	DUK_DDD(DUK_DDDPRINT("protected finalization helper running"));
50843 
50844 	/* [... obj] */
50845 
50846 	/* _Finalizer property is read without checking if the value is
50847 	 * callable or even exists.  This is intentional, and handled
50848 	 * by throwing an error which is caught by the safe call wrapper.
50849 	 *
50850 	 * XXX: Finalizer lookup should traverse the prototype chain (to allow
50851 	 * inherited finalizers) but should not invoke accessors or proxy object
50852 	 * behavior.  At the moment this lookup will invoke proxy behavior, so
50853 	 * caller must ensure that this function is not called if the target is
50854 	 * a Proxy.
50855 	 */
50856 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_FINALIZER);  /* -> [... obj finalizer] */
50857 	duk_dup_m2(thr);
50858 	duk_push_boolean(thr, DUK_HEAP_HAS_FINALIZER_NORESCUE(thr->heap));
50859 	DUK_DDD(DUK_DDDPRINT("calling finalizer"));
50860 	duk_call(thr, 2);  /* [ ... obj finalizer obj heapDestruct ]  -> [ ... obj retval ] */
50861 	DUK_DDD(DUK_DDDPRINT("finalizer returned successfully"));
50862 	return 0;
50863 
50864 	/* Note: we rely on duk_safe_call() to fix up the stack for the caller,
50865 	 * so we don't need to pop stuff here.  There is no return value;
50866 	 * caller determines rescued status based on object refcount.
50867 	 */
50868 }
50869 
50870 DUK_INTERNAL void duk_heap_run_finalizer(duk_heap *heap, duk_hobject *obj) {
50871 	duk_hthread *thr;
50872 	duk_ret_t rc;
50873 #if defined(DUK_USE_ASSERTIONS)
50874 	duk_idx_t entry_top;
50875 #endif
50876 
50877 	DUK_DD(DUK_DDPRINT("running duk_hobject finalizer for object: %p", (void *) obj));
50878 
50879 	DUK_ASSERT(heap != NULL);
50880 	DUK_ASSERT(heap->heap_thread != NULL);
50881 	thr = heap->heap_thread;
50882 	DUK_ASSERT(obj != NULL);
50883 	DUK_ASSERT_VALSTACK_SPACE(heap->heap_thread, 1);
50884 
50885 #if defined(DUK_USE_ASSERTIONS)
50886 	entry_top = duk_get_top(thr);
50887 #endif
50888 	/*
50889 	 *  Get and call the finalizer.  All of this must be wrapped
50890 	 *  in a protected call, because even getting the finalizer
50891 	 *  may trigger an error (getter may throw one, for instance).
50892 	 */
50893 
50894 	/* ROM objects could inherit a finalizer, but they are never deemed
50895 	 * unreachable by mark-and-sweep, and their refcount never falls to 0.
50896 	 */
50897 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
50898 
50899 	/* Duktape 2.1: finalize_list never contains objects with FINALIZED
50900 	 * set, so no need to check here.
50901 	 */
50902 	DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) obj));
50903 #if 0
50904 	if (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) obj)) {
50905 		DUK_D(DUK_DPRINT("object already finalized, avoid running finalizer twice: %!O", obj));
50906 		return;
50907 	}
50908 #endif
50909 	DUK_HEAPHDR_SET_FINALIZED((duk_heaphdr *) obj);  /* ensure never re-entered until rescue cycle complete */
50910 
50911 #if defined(DUK_USE_ES6_PROXY)
50912 	if (DUK_HOBJECT_IS_PROXY(obj)) {
50913 		/* This may happen if duk_set_finalizer() or Duktape.fin() is
50914 		 * called for a Proxy object.  In such cases the fast finalizer
50915 		 * flag will be set on the Proxy, not the target, and neither
50916 		 * will be finalized.
50917 		 */
50918 		DUK_D(DUK_DPRINT("object is a Proxy, skip finalizer call"));
50919 		return;
50920 	}
50921 #endif  /* DUK_USE_ES6_PROXY */
50922 
50923 	duk_push_hobject(thr, obj);  /* this also increases refcount by one */
50924 	rc = duk_safe_call(thr, duk__finalize_helper, NULL /*udata*/, 0 /*nargs*/, 1 /*nrets*/);  /* -> [... obj retval/error] */
50925 	DUK_ASSERT_TOP(thr, entry_top + 2);  /* duk_safe_call discipline */
50926 
50927 	if (rc != DUK_EXEC_SUCCESS) {
50928 		/* Note: we ask for one return value from duk_safe_call to get this
50929 		 * error debugging here.
50930 		 */
50931 		DUK_D(DUK_DPRINT("wrapped finalizer call failed for object %p (ignored); error: %!T",
50932 		                 (void *) obj, (duk_tval *) duk_get_tval(thr, -1)));
50933 	}
50934 	duk_pop_2(thr);  /* -> [...] */
50935 
50936 	DUK_ASSERT_TOP(thr, entry_top);
50937 }
50938 
50939 #else  /* DUK_USE_FINALIZER_SUPPORT */
50940 
50941 /* nothing */
50942 
50943 #endif  /* DUK_USE_FINALIZER_SUPPORT */
50944 /*
50945  *  String hash computation (interning).
50946  *
50947  *  String hashing is performance critical because a string hash is computed
50948  *  for all new strings which are candidates to be added to the string table.
50949  *  However, strings actually added to the string table go through a codepoint
50950  *  length calculation which dominates performance because it goes through
50951  *  every byte of the input string (but only for strings added).
50952  *
50953  *  The string hash algorithm should be fast, but on the other hand provide
50954  *  good enough hashes to ensure both string table and object property table
50955  *  hash tables work reasonably well (i.e., there aren't too many collisions
50956  *  with real world inputs).  Unless the hash is cryptographic, it's always
50957  *  possible to craft inputs with maximal hash collisions.
50958  *
50959  *  NOTE: The hash algorithms must match tools/dukutil.py:duk_heap_hashstring()
50960  *  for ROM string support!
50961  */
50962 
50963 /* #include duk_internal.h -> already included */
50964 
50965 #if defined(DUK_USE_STRHASH_DENSE)
50966 /* Constants for duk_hashstring(). */
50967 #define DUK__STRHASH_SHORTSTRING   4096L
50968 #define DUK__STRHASH_MEDIUMSTRING  (256L * 1024L)
50969 #define DUK__STRHASH_BLOCKSIZE     256L
50970 
50971 DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
50972 	duk_uint32_t hash;
50973 
50974 	/* Use Murmurhash2 directly for short strings, and use "block skipping"
50975 	 * for long strings: hash an initial part and then sample the rest of
50976 	 * the string with reasonably sized chunks.  An initial offset for the
50977 	 * sampling is computed based on a hash of the initial part of the string;
50978 	 * this is done to (usually) avoid the case where all long strings have
50979 	 * certain offset ranges which are never sampled.
50980 	 *
50981 	 * Skip should depend on length and bound the total time to roughly
50982 	 * logarithmic.  With current values:
50983 	 *
50984 	 *   1M string => 256 * 241 = 61696 bytes (0.06M) of hashing
50985 	 *   1G string => 256 * 16321 = 4178176 bytes (3.98M) of hashing
50986 	 *
50987 	 * XXX: It would be better to compute the skip offset more "smoothly"
50988 	 * instead of having a few boundary values.
50989 	 */
50990 
50991 	/* note: mixing len into seed improves hashing when skipping */
50992 	duk_uint32_t str_seed = heap->hash_seed ^ ((duk_uint32_t) len);
50993 
50994 	if (len <= DUK__STRHASH_SHORTSTRING) {
50995 		hash = duk_util_hashbytes(str, len, str_seed);
50996 	} else {
50997 		duk_size_t off;
50998 		duk_size_t skip;
50999 
51000 		if (len <= DUK__STRHASH_MEDIUMSTRING) {
51001 			skip = (duk_size_t) (16 * DUK__STRHASH_BLOCKSIZE + DUK__STRHASH_BLOCKSIZE);
51002 		} else {
51003 			skip = (duk_size_t) (256 * DUK__STRHASH_BLOCKSIZE + DUK__STRHASH_BLOCKSIZE);
51004 		}
51005 
51006 		hash = duk_util_hashbytes(str, (duk_size_t) DUK__STRHASH_SHORTSTRING, str_seed);
51007 		off = DUK__STRHASH_SHORTSTRING + (skip * (hash % 256)) / 256;
51008 
51009 		/* XXX: inefficient loop */
51010 		while (off < len) {
51011 			duk_size_t left = len - off;
51012 			duk_size_t now = (duk_size_t) (left > DUK__STRHASH_BLOCKSIZE ? DUK__STRHASH_BLOCKSIZE : left);
51013 			hash ^= duk_util_hashbytes(str + off, now, str_seed);
51014 			off += skip;
51015 		}
51016 	}
51017 
51018 #if defined(DUK_USE_STRHASH16)
51019 	/* Truncate to 16 bits here, so that a computed hash can be compared
51020 	 * against a hash stored in a 16-bit field.
51021 	 */
51022 	hash &= 0x0000ffffUL;
51023 #endif
51024 	return hash;
51025 }
51026 #else  /* DUK_USE_STRHASH_DENSE */
51027 DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
51028 	duk_uint32_t hash;
51029 	duk_size_t step;
51030 	duk_size_t off;
51031 
51032 	/* Slightly modified "Bernstein hash" from:
51033 	 *
51034 	 *     http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
51035 	 *
51036 	 * Modifications: string skipping and reverse direction similar to
51037 	 * Lua 5.1.5, and different hash initializer.
51038 	 *
51039 	 * The reverse direction ensures last byte it always included in the
51040 	 * hash which is a good default as changing parts of the string are
51041 	 * more often in the suffix than in the prefix.
51042 	 */
51043 
51044 	hash = heap->hash_seed ^ ((duk_uint32_t) len);  /* Bernstein hash init value is normally 5381 */
51045 	step = (len >> DUK_USE_STRHASH_SKIP_SHIFT) + 1;
51046 	for (off = len; off >= step; off -= step) {
51047 		DUK_ASSERT(off >= 1);  /* off >= step, and step >= 1 */
51048 		hash = (hash * 33) + str[off - 1];
51049 	}
51050 
51051 #if defined(DUK_USE_STRHASH16)
51052 	/* Truncate to 16 bits here, so that a computed hash can be compared
51053 	 * against a hash stored in a 16-bit field.
51054 	 */
51055 	hash &= 0x0000ffffUL;
51056 #endif
51057 	return hash;
51058 }
51059 #endif  /* DUK_USE_STRHASH_DENSE */
51060 
51061 /* automatic undefs */
51062 #undef DUK__STRHASH_BLOCKSIZE
51063 #undef DUK__STRHASH_MEDIUMSTRING
51064 #undef DUK__STRHASH_SHORTSTRING
51065 /*
51066  *  Mark-and-sweep garbage collection.
51067  */
51068 
51069 /* #include duk_internal.h -> already included */
51070 
51071 DUK_LOCAL_DECL void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h);
51072 DUK_LOCAL_DECL void duk__mark_heaphdr_nonnull(duk_heap *heap, duk_heaphdr *h);
51073 DUK_LOCAL_DECL void duk__mark_tval(duk_heap *heap, duk_tval *tv);
51074 DUK_LOCAL_DECL void duk__mark_tvals(duk_heap *heap, duk_tval *tv, duk_idx_t count);
51075 
51076 /*
51077  *  Marking functions for heap types: mark children recursively.
51078  */
51079 
51080 DUK_LOCAL void duk__mark_hstring(duk_heap *heap, duk_hstring *h) {
51081 	DUK_UNREF(heap);
51082 	DUK_UNREF(h);
51083 
51084 	DUK_DDD(DUK_DDDPRINT("duk__mark_hstring: %p", (void *) h));
51085 	DUK_ASSERT(h);
51086 	DUK_HSTRING_ASSERT_VALID(h);
51087 
51088 	/* nothing to process */
51089 }
51090 
51091 DUK_LOCAL void duk__mark_hobject(duk_heap *heap, duk_hobject *h) {
51092 	duk_uint_fast32_t i;
51093 
51094 	DUK_DDD(DUK_DDDPRINT("duk__mark_hobject: %p", (void *) h));
51095 
51096 	DUK_ASSERT(h);
51097 	DUK_HOBJECT_ASSERT_VALID(h);
51098 
51099 	/* XXX: use advancing pointers instead of index macros -> faster and smaller? */
51100 
51101 	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
51102 		duk_hstring *key = DUK_HOBJECT_E_GET_KEY(heap, h, i);
51103 		if (key == NULL) {
51104 			continue;
51105 		}
51106 		duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) key);
51107 		if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {
51108 			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);
51109 			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);
51110 		} else {
51111 			duk__mark_tval(heap, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);
51112 		}
51113 	}
51114 
51115 	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
51116 		duk__mark_tval(heap, DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i));
51117 	}
51118 
51119 	/* Hash part is a 'weak reference' and does not contribute. */
51120 
51121 	duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(heap, h));
51122 
51123 	/* Fast path for objects which don't have a subclass struct, or have a
51124 	 * subclass struct but nothing that needs marking in the subclass struct.
51125 	 */
51126 	if (DUK_HOBJECT_HAS_FASTREFS(h)) {
51127 		DUK_ASSERT(DUK_HOBJECT_ALLOWS_FASTREFS(h));
51128 		return;
51129 	}
51130 	DUK_ASSERT(DUK_HOBJECT_PROHIBITS_FASTREFS(h));
51131 
51132 	/* XXX: reorg, more common first */
51133 	if (DUK_HOBJECT_IS_COMPFUNC(h)) {
51134 		duk_hcompfunc *f = (duk_hcompfunc *) h;
51135 		duk_tval *tv, *tv_end;
51136 		duk_hobject **fn, **fn_end;
51137 
51138 		DUK_HCOMPFUNC_ASSERT_VALID(f);
51139 
51140 		/* 'data' is reachable through every compiled function which
51141 		 * contains a reference.
51142 		 */
51143 
51144 		duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPFUNC_GET_DATA(heap, f));
51145 		duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPFUNC_GET_LEXENV(heap, f));
51146 		duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPFUNC_GET_VARENV(heap, f));
51147 
51148 		if (DUK_HCOMPFUNC_GET_DATA(heap, f) != NULL) {
51149 			tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, f);
51150 			tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(heap, f);
51151 			while (tv < tv_end) {
51152 				duk__mark_tval(heap, tv);
51153 				tv++;
51154 			}
51155 
51156 			fn = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, f);
51157 			fn_end = DUK_HCOMPFUNC_GET_FUNCS_END(heap, f);
51158 			while (fn < fn_end) {
51159 				duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) *fn);
51160 				fn++;
51161 			}
51162 		} else {
51163 			/* May happen in some out-of-memory corner cases. */
51164 			DUK_D(DUK_DPRINT("duk_hcompfunc 'data' is NULL, skipping marking"));
51165 		}
51166 	} else if (DUK_HOBJECT_IS_DECENV(h)) {
51167 		duk_hdecenv *e = (duk_hdecenv *) h;
51168 		DUK_HDECENV_ASSERT_VALID(e);
51169 		duk__mark_heaphdr(heap, (duk_heaphdr *) e->thread);
51170 		duk__mark_heaphdr(heap, (duk_heaphdr *) e->varmap);
51171 	} else if (DUK_HOBJECT_IS_OBJENV(h)) {
51172 		duk_hobjenv *e = (duk_hobjenv *) h;
51173 		DUK_HOBJENV_ASSERT_VALID(e);
51174 		duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) e->target);
51175 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
51176 	} else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
51177 		duk_hbufobj *b = (duk_hbufobj *) h;
51178 		DUK_HBUFOBJ_ASSERT_VALID(b);
51179 		duk__mark_heaphdr(heap, (duk_heaphdr *) b->buf);
51180 		duk__mark_heaphdr(heap, (duk_heaphdr *) b->buf_prop);
51181 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
51182 	} else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {
51183 		duk_hboundfunc *f = (duk_hboundfunc *) (void *) h;
51184 		DUK_HBOUNDFUNC_ASSERT_VALID(f);
51185 		duk__mark_tval(heap, &f->target);
51186 		duk__mark_tval(heap, &f->this_binding);
51187 		duk__mark_tvals(heap, f->args, f->nargs);
51188 #if defined(DUK_USE_ES6_PROXY)
51189 	} else if (DUK_HOBJECT_IS_PROXY(h)) {
51190 		duk_hproxy *p = (duk_hproxy *) h;
51191 		DUK_HPROXY_ASSERT_VALID(p);
51192 		duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) p->target);
51193 		duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) p->handler);
51194 #endif  /* DUK_USE_ES6_PROXY */
51195 	} else if (DUK_HOBJECT_IS_THREAD(h)) {
51196 		duk_hthread *t = (duk_hthread *) h;
51197 		duk_activation *act;
51198 		duk_tval *tv;
51199 
51200 		DUK_HTHREAD_ASSERT_VALID(t);
51201 
51202 		tv = t->valstack;
51203 		while (tv < t->valstack_top) {
51204 			duk__mark_tval(heap, tv);
51205 			tv++;
51206 		}
51207 
51208 		for (act = t->callstack_curr; act != NULL; act = act->parent) {
51209 			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_ACT_GET_FUNC(act));
51210 			duk__mark_heaphdr(heap, (duk_heaphdr *) act->var_env);
51211 			duk__mark_heaphdr(heap, (duk_heaphdr *) act->lex_env);
51212 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
51213 			duk__mark_heaphdr(heap, (duk_heaphdr *) act->prev_caller);
51214 #endif
51215 #if 0  /* nothing now */
51216 			for (cat = act->cat; cat != NULL; cat = cat->parent) {
51217 			}
51218 #endif
51219 		}
51220 
51221 		duk__mark_heaphdr(heap, (duk_heaphdr *) t->resumer);
51222 
51223 		for (i = 0; i < DUK_NUM_BUILTINS; i++) {
51224 			duk__mark_heaphdr(heap, (duk_heaphdr *) t->builtins[i]);
51225 		}
51226 	} else {
51227 		/* We may come here if the object should have a FASTREFS flag
51228 		 * but it's missing for some reason.  Assert for never getting
51229 		 * here; however, other than performance, this is harmless.
51230 		 */
51231 		DUK_D(DUK_DPRINT("missing FASTREFS flag for: %!iO", h));
51232 		DUK_ASSERT(0);
51233 	}
51234 }
51235 
51236 /* Mark any duk_heaphdr type.  Recursion tracking happens only here. */
51237 DUK_LOCAL void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h) {
51238 	DUK_DDD(DUK_DDDPRINT("duk__mark_heaphdr %p, type %ld",
51239 	                     (void *) h,
51240 	                     (h != NULL ? (long) DUK_HEAPHDR_GET_TYPE(h) : (long) -1)));
51241 
51242 	/* XXX: add non-null variant? */
51243 	if (h == NULL) {
51244 		return;
51245 	}
51246 
51247 	DUK_HEAPHDR_ASSERT_VALID(h);
51248 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(h) || DUK_HEAPHDR_HAS_REACHABLE(h));
51249 
51250 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
51251 	if (!DUK_HEAPHDR_HAS_READONLY(h)) {
51252 		h->h_assert_refcount++;  /* Comparison refcount: bump even if already reachable. */
51253 	}
51254 #endif
51255 	if (DUK_HEAPHDR_HAS_REACHABLE(h)) {
51256 		DUK_DDD(DUK_DDDPRINT("already marked reachable, skip"));
51257 		return;
51258 	}
51259 #if defined(DUK_USE_ROM_OBJECTS)
51260 	/* READONLY objects always have REACHABLE set, so the check above
51261 	 * will prevent READONLY objects from being marked here.
51262 	 */
51263 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(h));
51264 #endif
51265 
51266 	DUK_HEAPHDR_SET_REACHABLE(h);
51267 
51268 	if (heap->ms_recursion_depth >= DUK_USE_MARK_AND_SWEEP_RECLIMIT) {
51269 		DUK_D(DUK_DPRINT("mark-and-sweep recursion limit reached, marking as temproot: %p", (void *) h));
51270 		DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap);
51271 		DUK_HEAPHDR_SET_TEMPROOT(h);
51272 		return;
51273 	}
51274 
51275 	heap->ms_recursion_depth++;
51276 	DUK_ASSERT(heap->ms_recursion_depth != 0);  /* Wrap. */
51277 
51278 	switch (DUK_HEAPHDR_GET_TYPE(h)) {
51279 	case DUK_HTYPE_STRING:
51280 		duk__mark_hstring(heap, (duk_hstring *) h);
51281 		break;
51282 	case DUK_HTYPE_OBJECT:
51283 		duk__mark_hobject(heap, (duk_hobject *) h);
51284 		break;
51285 	case DUK_HTYPE_BUFFER:
51286 		/* nothing to mark */
51287 		break;
51288 	default:
51289 		DUK_D(DUK_DPRINT("attempt to mark heaphdr %p with invalid htype %ld", (void *) h, (long) DUK_HEAPHDR_GET_TYPE(h)));
51290 		DUK_UNREACHABLE();
51291 	}
51292 
51293 	DUK_ASSERT(heap->ms_recursion_depth > 0);
51294 	heap->ms_recursion_depth--;
51295 }
51296 
51297 DUK_LOCAL void duk__mark_tval(duk_heap *heap, duk_tval *tv) {
51298 	DUK_DDD(DUK_DDDPRINT("duk__mark_tval %p", (void *) tv));
51299 	if (tv == NULL) {
51300 		return;
51301 	}
51302 	DUK_TVAL_ASSERT_VALID(tv);
51303 	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
51304 		duk_heaphdr *h;
51305 		h = DUK_TVAL_GET_HEAPHDR(tv);
51306 		DUK_ASSERT(h != NULL);
51307 		duk__mark_heaphdr_nonnull(heap, h);
51308 	}
51309 }
51310 
51311 DUK_LOCAL void duk__mark_tvals(duk_heap *heap, duk_tval *tv, duk_idx_t count) {
51312 	DUK_ASSERT(count == 0 || tv != NULL);
51313 
51314 	while (count-- > 0) {
51315 		DUK_TVAL_ASSERT_VALID(tv);
51316 		if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
51317 			duk_heaphdr *h;
51318 			h = DUK_TVAL_GET_HEAPHDR(tv);
51319 			DUK_ASSERT(h != NULL);
51320 			duk__mark_heaphdr_nonnull(heap, h);
51321 		}
51322 		tv++;
51323 	}
51324 }
51325 
51326 /* Mark any duk_heaphdr type, caller guarantees a non-NULL pointer. */
51327 DUK_LOCAL void duk__mark_heaphdr_nonnull(duk_heap *heap, duk_heaphdr *h) {
51328 	/* For now, just call the generic handler.  Change when call sites
51329 	 * are changed too.
51330 	 */
51331 	duk__mark_heaphdr(heap, h);
51332 }
51333 
51334 /*
51335  *  Mark the heap.
51336  */
51337 
51338 DUK_LOCAL void duk__mark_roots_heap(duk_heap *heap) {
51339 	duk_small_uint_t i;
51340 
51341 	DUK_DD(DUK_DDPRINT("duk__mark_roots_heap: %p", (void *) heap));
51342 
51343 	duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_thread);
51344 	duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_object);
51345 
51346 	for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
51347 		duk_hstring *h = DUK_HEAP_GET_STRING(heap, i);
51348 		duk__mark_heaphdr(heap, (duk_heaphdr *) h);
51349 	}
51350 
51351 	duk__mark_tval(heap, &heap->lj.value1);
51352 	duk__mark_tval(heap, &heap->lj.value2);
51353 
51354 #if defined(DUK_USE_DEBUGGER_SUPPORT)
51355 	for (i = 0; i < heap->dbg_breakpoint_count; i++) {
51356 		duk__mark_heaphdr(heap, (duk_heaphdr *) heap->dbg_breakpoints[i].filename);
51357 	}
51358 #endif
51359 }
51360 
51361 /*
51362  *  Mark unreachable, finalizable objects.
51363  *
51364  *  Such objects will be moved aside and their finalizers run later.  They
51365  *  have to be treated as reachability roots for their properties etc to
51366  *  remain allocated.  This marking is only done for unreachable values which
51367  *  would be swept later.
51368  *
51369  *  Objects are first marked FINALIZABLE and only then marked as reachability
51370  *  roots; otherwise circular references might be handled inconsistently.
51371  */
51372 
51373 #if defined(DUK_USE_FINALIZER_SUPPORT)
51374 DUK_LOCAL void duk__mark_finalizable(duk_heap *heap) {
51375 	duk_heaphdr *hdr;
51376 	duk_size_t count_finalizable = 0;
51377 
51378 	DUK_DD(DUK_DDPRINT("duk__mark_finalizable: %p", (void *) heap));
51379 
51380 	DUK_ASSERT(heap->heap_thread != NULL);
51381 
51382 	hdr = heap->heap_allocated;
51383 	while (hdr != NULL) {
51384 		/* A finalizer is looked up from the object and up its
51385 		 * prototype chain (which allows inherited finalizers).
51386 		 * The finalizer is checked for using a duk_hobject flag
51387 		 * which is kept in sync with the presence and callability
51388 		 * of a _Finalizer hidden symbol.
51389 		 */
51390 
51391 		if (!DUK_HEAPHDR_HAS_REACHABLE(hdr) &&
51392 		    DUK_HEAPHDR_IS_OBJECT(hdr) &&
51393 		    !DUK_HEAPHDR_HAS_FINALIZED(hdr) &&
51394 		    DUK_HOBJECT_HAS_FINALIZER_FAST(heap, (duk_hobject *) hdr)) {
51395 			/* heaphdr:
51396 			 *  - is not reachable
51397 			 *  - is an object
51398 			 *  - is not a finalized object waiting for rescue/keep decision
51399 			 *  - has a finalizer
51400 			 */
51401 
51402 			DUK_DD(DUK_DDPRINT("unreachable heap object will be "
51403 			                   "finalized -> mark as finalizable "
51404 			                   "and treat as a reachability root: %p",
51405 			                   (void *) hdr));
51406 			DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(hdr));
51407 			DUK_HEAPHDR_SET_FINALIZABLE(hdr);
51408 			count_finalizable++;
51409 		}
51410 
51411 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
51412 	}
51413 
51414 	if (count_finalizable == 0) {
51415 		return;
51416 	}
51417 
51418 	DUK_DD(DUK_DDPRINT("marked %ld heap objects as finalizable, now mark them reachable",
51419 	                   (long) count_finalizable));
51420 
51421 	hdr = heap->heap_allocated;
51422 	while (hdr != NULL) {
51423 		if (DUK_HEAPHDR_HAS_FINALIZABLE(hdr)) {
51424 			duk__mark_heaphdr_nonnull(heap, hdr);
51425 		}
51426 
51427 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
51428 	}
51429 
51430 	/* Caller will finish the marking process if we hit a recursion limit. */
51431 }
51432 #endif  /* DUK_USE_FINALIZER_SUPPORT */
51433 
51434 /*
51435  *  Mark objects on finalize_list.
51436  */
51437 
51438 #if defined(DUK_USE_FINALIZER_SUPPORT)
51439 DUK_LOCAL void duk__mark_finalize_list(duk_heap *heap) {
51440 	duk_heaphdr *hdr;
51441 #if defined(DUK_USE_DEBUG)
51442 	duk_size_t count_finalize_list = 0;
51443 #endif
51444 
51445 	DUK_DD(DUK_DDPRINT("duk__mark_finalize_list: %p", (void *) heap));
51446 
51447 	hdr = heap->finalize_list;
51448 	while (hdr != NULL) {
51449 		duk__mark_heaphdr_nonnull(heap, hdr);
51450 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
51451 #if defined(DUK_USE_DEBUG)
51452 		count_finalize_list++;
51453 #endif
51454 	}
51455 
51456 #if defined(DUK_USE_DEBUG)
51457 	if (count_finalize_list > 0) {
51458 		DUK_D(DUK_DPRINT("marked %ld objects on the finalize_list as reachable (previous finalizer run skipped)",
51459 		                 (long) count_finalize_list));
51460 	}
51461 #endif
51462 }
51463 #endif  /* DUK_USE_FINALIZER_SUPPORT */
51464 
51465 /*
51466  *  Fallback marking handler if recursion limit is reached.
51467  *
51468  *  Iterates 'temproots' until recursion limit is no longer hit.  Temproots
51469  *  can be in heap_allocated or finalize_list; refzero_list is now always
51470  *  empty for mark-and-sweep.  A temproot may occur in finalize_list now if
51471  *  there are objects on the finalize_list and user code creates a reference
51472  *  from an object in heap_allocated to the object in finalize_list (which is
51473  *  now allowed), and it happened to coincide with the recursion depth limit.
51474  *
51475  *  This is a slow scan, but guarantees that we finish with a bounded C stack.
51476  *
51477  *  Note that nodes may have been marked as temproots before this scan begun,
51478  *  OR they may have been marked during the scan (as we process nodes
51479  *  recursively also during the scan).  This is intended behavior.
51480  */
51481 
51482 #if defined(DUK_USE_DEBUG)
51483 DUK_LOCAL void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr, duk_size_t *count) {
51484 #else
51485 DUK_LOCAL void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr) {
51486 #endif
51487 	DUK_ASSERT(hdr != NULL);
51488 
51489 	if (!DUK_HEAPHDR_HAS_TEMPROOT(hdr)) {
51490 		DUK_DDD(DUK_DDDPRINT("not a temp root: %p", (void *) hdr));
51491 		return;
51492 	}
51493 
51494 	DUK_DDD(DUK_DDDPRINT("found a temp root: %p", (void *) hdr));
51495 	DUK_HEAPHDR_CLEAR_TEMPROOT(hdr);
51496 	DUK_HEAPHDR_CLEAR_REACHABLE(hdr);  /* Done so that duk__mark_heaphdr() works correctly. */
51497 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
51498 	hdr->h_assert_refcount--;  /* Same node visited twice. */
51499 #endif
51500 	duk__mark_heaphdr_nonnull(heap, hdr);
51501 
51502 #if defined(DUK_USE_DEBUG)
51503 	(*count)++;
51504 #endif
51505 }
51506 
51507 DUK_LOCAL void duk__mark_temproots_by_heap_scan(duk_heap *heap) {
51508 	duk_heaphdr *hdr;
51509 #if defined(DUK_USE_DEBUG)
51510 	duk_size_t count;
51511 #endif
51512 
51513 	DUK_DD(DUK_DDPRINT("duk__mark_temproots_by_heap_scan: %p", (void *) heap));
51514 
51515 	while (DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap)) {
51516 		DUK_DD(DUK_DDPRINT("recursion limit reached, doing heap scan to continue from temproots"));
51517 
51518 #if defined(DUK_USE_DEBUG)
51519 		count = 0;
51520 #endif
51521 		DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap);
51522 
51523 		hdr = heap->heap_allocated;
51524 		while (hdr) {
51525 #if defined(DUK_USE_DEBUG)
51526 			duk__handle_temproot(heap, hdr, &count);
51527 #else
51528 			duk__handle_temproot(heap, hdr);
51529 #endif
51530 			hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
51531 		}
51532 
51533 #if defined(DUK_USE_FINALIZER_SUPPORT)
51534 		hdr = heap->finalize_list;
51535 		while (hdr) {
51536 #if defined(DUK_USE_DEBUG)
51537 			duk__handle_temproot(heap, hdr, &count);
51538 #else
51539 			duk__handle_temproot(heap, hdr);
51540 #endif
51541 			hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
51542 		}
51543 #endif
51544 
51545 #if defined(DUK_USE_DEBUG)
51546 		DUK_DD(DUK_DDPRINT("temproot mark heap scan processed %ld temp roots", (long) count));
51547 #endif
51548 	}
51549 }
51550 
51551 /*
51552  *  Finalize refcounts for heap elements just about to be freed.
51553  *  This must be done for all objects before freeing to avoid any
51554  *  stale pointer dereferences.
51555  *
51556  *  Note that this must deduce the set of objects to be freed
51557  *  identically to duk__sweep_heap().
51558  */
51559 
51560 #if defined(DUK_USE_REFERENCE_COUNTING)
51561 DUK_LOCAL void duk__finalize_refcounts(duk_heap *heap) {
51562 	duk_heaphdr *hdr;
51563 
51564 	DUK_ASSERT(heap->heap_thread != NULL);
51565 
51566 	DUK_DD(DUK_DDPRINT("duk__finalize_refcounts: heap=%p", (void *) heap));
51567 
51568 	hdr = heap->heap_allocated;
51569 	while (hdr) {
51570 		if (!DUK_HEAPHDR_HAS_REACHABLE(hdr)) {
51571 			/*
51572 			 *  Unreachable object about to be swept.  Finalize target refcounts
51573 			 *  (objects which the unreachable object points to) without doing
51574 			 *  refzero processing.  Recursive decrefs are also prevented when
51575 			 *  refzero processing is disabled.
51576 			 *
51577 			 *  Value cannot be a finalizable object, as they have been made
51578 			 *  temporarily reachable for this round.
51579 			 */
51580 
51581 			DUK_DDD(DUK_DDDPRINT("unreachable object, refcount finalize before sweeping: %p", (void *) hdr));
51582 
51583 			/* Finalize using heap->heap_thread; DECREF has a
51584 			 * suppress check for mark-and-sweep which is based
51585 			 * on heap->ms_running.
51586 			 */
51587 			duk_heaphdr_refcount_finalize_norz(heap, hdr);
51588 		}
51589 
51590 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
51591 	}
51592 }
51593 #endif  /* DUK_USE_REFERENCE_COUNTING */
51594 
51595 /*
51596  *  Clear (reachable) flags of finalize_list.
51597  *
51598  *  We could mostly do in the sweep phase when we move objects from the
51599  *  heap into the finalize_list.  However, if a finalizer run is skipped
51600  *  during a mark-and-sweep, the objects on the finalize_list will be marked
51601  *  reachable during the next mark-and-sweep.  Since they're already on the
51602  *  finalize_list, no-one will be clearing their REACHABLE flag so we do it
51603  *  here.  (This now overlaps with the sweep handling in a harmless way.)
51604  */
51605 
51606 #if defined(DUK_USE_FINALIZER_SUPPORT)
51607 DUK_LOCAL void duk__clear_finalize_list_flags(duk_heap *heap) {
51608 	duk_heaphdr *hdr;
51609 
51610 	DUK_DD(DUK_DDPRINT("duk__clear_finalize_list_flags: %p", (void *) heap));
51611 
51612 	hdr = heap->finalize_list;
51613 	while (hdr) {
51614 		DUK_HEAPHDR_CLEAR_REACHABLE(hdr);
51615 #if defined(DUK_USE_ASSERTIONS)
51616 		DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZABLE(hdr) || \
51617 		           (heap->currently_finalizing == hdr));
51618 #endif
51619 		/* DUK_HEAPHDR_FLAG_FINALIZED may be set. */
51620 		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
51621 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
51622 	}
51623 }
51624 #endif  /* DUK_USE_FINALIZER_SUPPORT */
51625 
51626 /*
51627  *  Sweep stringtable.
51628  */
51629 
51630 DUK_LOCAL void duk__sweep_stringtable(duk_heap *heap, duk_size_t *out_count_keep) {
51631 	duk_hstring *h;
51632 	duk_hstring *prev;
51633 	duk_uint32_t i;
51634 #if defined(DUK_USE_DEBUG)
51635 	duk_size_t count_free = 0;
51636 #endif
51637 	duk_size_t count_keep = 0;
51638 
51639 	DUK_DD(DUK_DDPRINT("duk__sweep_stringtable: %p", (void *) heap));
51640 
51641 #if defined(DUK_USE_STRTAB_PTRCOMP)
51642 	if (heap->strtable16 == NULL) {
51643 #else
51644 	if (heap->strtable == NULL) {
51645 #endif
51646 		goto done;
51647 	}
51648 
51649 	for (i = 0; i < heap->st_size; i++) {
51650 #if defined(DUK_USE_STRTAB_PTRCOMP)
51651 		h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
51652 #else
51653 		h = heap->strtable[i];
51654 #endif
51655 		prev = NULL;
51656 		while (h != NULL) {
51657 			duk_hstring *next;
51658 			next = h->hdr.h_next;
51659 
51660 			if (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h))
51661 			{
51662 				DUK_HEAPHDR_CLEAR_REACHABLE((duk_heaphdr *) h);
51663 				count_keep++;
51664 				prev = h;
51665 			} else {
51666 #if defined(DUK_USE_DEBUG)
51667 				count_free++;
51668 #endif
51669 
51670 				/* For pinned strings the refcount has been
51671 				 * bumped.  We could unbump it here before
51672 				 * freeing, but that's actually not necessary
51673 				 * except for assertions.
51674 				 */
51675 #if 0
51676 				if (DUK_HSTRING_HAS_PINNED_LITERAL(h)) {
51677 					DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) > 0U);
51678 					DUK_HSTRING_DECREF_NORZ(heap->heap_thread, h);
51679 					DUK_HSTRING_CLEAR_PINNED_LITERAL(h);
51680 				}
51681 #endif
51682 #if defined(DUK_USE_REFERENCE_COUNTING)
51683 				/* Non-zero refcounts should not happen for unreachable strings,
51684 				 * because we refcount finalize all unreachable objects which
51685 				 * should have decreased unreachable string refcounts to zero
51686 				 * (even for cycles).  However, pinned strings have a +1 bump.
51687 				 */
51688 				DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) ==
51689 				           DUK_HSTRING_HAS_PINNED_LITERAL(h) ? 1U : 0U);
51690 #endif
51691 
51692 				/* Deal with weak references first. */
51693 				duk_heap_strcache_string_remove(heap, (duk_hstring *) h);
51694 
51695 				/* Remove the string from the string table. */
51696 				duk_heap_strtable_unlink_prev(heap, (duk_hstring *) h, (duk_hstring *) prev);
51697 
51698 				/* Free inner references (these exist e.g. when external
51699 				 * strings are enabled) and the struct itself.
51700 				 */
51701 				duk_free_hstring(heap, (duk_hstring *) h);
51702 
51703 				/* Don't update 'prev'; it should be last string kept. */
51704 			}
51705 
51706 			h = next;
51707 		}
51708 	}
51709 
51710  done:
51711 #if defined(DUK_USE_DEBUG)
51712 	DUK_D(DUK_DPRINT("mark-and-sweep sweep stringtable: %ld freed, %ld kept",
51713 	                 (long) count_free, (long) count_keep));
51714 #endif
51715 	*out_count_keep = count_keep;
51716 }
51717 
51718 /*
51719  *  Sweep heap.
51720  */
51721 
51722 DUK_LOCAL void duk__sweep_heap(duk_heap *heap, duk_small_uint_t flags, duk_size_t *out_count_keep) {
51723 	duk_heaphdr *prev;  /* last element that was left in the heap */
51724 	duk_heaphdr *curr;
51725 	duk_heaphdr *next;
51726 #if defined(DUK_USE_DEBUG)
51727 	duk_size_t count_free = 0;
51728 	duk_size_t count_finalize = 0;
51729 	duk_size_t count_rescue = 0;
51730 #endif
51731 	duk_size_t count_keep = 0;
51732 
51733 	DUK_DD(DUK_DDPRINT("duk__sweep_heap: %p", (void *) heap));
51734 
51735 	prev = NULL;
51736 	curr = heap->heap_allocated;
51737 	heap->heap_allocated = NULL;
51738 	while (curr) {
51739 		/* Strings and ROM objects are never placed on the heap allocated list. */
51740 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) != DUK_HTYPE_STRING);
51741 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(curr));
51742 
51743 		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
51744 
51745 		if (DUK_HEAPHDR_HAS_REACHABLE(curr)) {
51746 			/*
51747 			 *  Reachable object:
51748 			 *    - If FINALIZABLE -> actually unreachable (but marked
51749 			 *      artificially reachable), queue to finalize_list.
51750 			 *    - If !FINALIZABLE but FINALIZED -> rescued after
51751 			 *      finalizer execution.
51752 			 *    - Otherwise just a normal, reachable object.
51753 			 *
51754 			 *  Objects which are kept are queued to heap_allocated
51755 			 *  tail (we're essentially filtering heap_allocated in
51756 			 *  practice).
51757 			 */
51758 
51759 #if defined(DUK_USE_FINALIZER_SUPPORT)
51760 			if (DUK_UNLIKELY(DUK_HEAPHDR_HAS_FINALIZABLE(curr))) {
51761 				DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
51762 				DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);
51763 				DUK_DD(DUK_DDPRINT("sweep; reachable, finalizable --> move to finalize_list: %p", (void *) curr));
51764 
51765 #if defined(DUK_USE_REFERENCE_COUNTING)
51766 				DUK_HEAPHDR_PREINC_REFCOUNT(curr);  /* Bump refcount so that refzero never occurs when pending a finalizer call. */
51767 #endif
51768 				DUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap, curr);
51769 #if defined(DUK_USE_DEBUG)
51770 				count_finalize++;
51771 #endif
51772 			}
51773 			else
51774 #endif  /* DUK_USE_FINALIZER_SUPPORT */
51775 			{
51776 				if (DUK_UNLIKELY(DUK_HEAPHDR_HAS_FINALIZED(curr))) {
51777 					DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));
51778 					DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);
51779 
51780 					if (flags & DUK_MS_FLAG_POSTPONE_RESCUE) {
51781 						DUK_DD(DUK_DDPRINT("sweep; reachable, finalized, but postponing rescue decisions --> keep object (with FINALIZED set): %!iO", curr));
51782 						count_keep++;
51783 					} else {
51784 						DUK_DD(DUK_DDPRINT("sweep; reachable, finalized --> rescued after finalization: %p", (void *) curr));
51785 #if defined(DUK_USE_FINALIZER_SUPPORT)
51786 						DUK_HEAPHDR_CLEAR_FINALIZED(curr);
51787 #endif
51788 #if defined(DUK_USE_DEBUG)
51789 						count_rescue++;
51790 #endif
51791 					}
51792 				} else {
51793 					DUK_DD(DUK_DDPRINT("sweep; reachable --> keep: %!iO", curr));
51794 					count_keep++;
51795 				}
51796 
51797 				if (prev != NULL) {
51798 					DUK_ASSERT(heap->heap_allocated != NULL);
51799 					DUK_HEAPHDR_SET_NEXT(heap, prev, curr);
51800 				} else {
51801 					DUK_ASSERT(heap->heap_allocated == NULL);
51802 					heap->heap_allocated = curr;
51803 				}
51804 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
51805 				DUK_HEAPHDR_SET_PREV(heap, curr, prev);
51806 #endif
51807 				DUK_HEAPHDR_ASSERT_LINKS(heap, prev);
51808 				DUK_HEAPHDR_ASSERT_LINKS(heap, curr);
51809 				prev = curr;
51810 			}
51811 
51812 			/*
51813 			 *  Shrink check for value stacks here.  We're inside
51814 			 *  ms_prevent_count protection which prevents recursive
51815 			 *  mark-and-sweep and refzero finalizers, so there are
51816 			 *  no side effects that would affect the heap lists.
51817 			 */
51818 			if (DUK_HEAPHDR_IS_OBJECT(curr) && DUK_HOBJECT_IS_THREAD((duk_hobject *) curr)) {
51819 				duk_hthread *thr_curr = (duk_hthread *) curr;
51820 				DUK_DD(DUK_DDPRINT("value stack shrink check for thread: %!O", curr));
51821 				duk_valstack_shrink_check_nothrow(thr_curr, flags & DUK_MS_FLAG_EMERGENCY /*snug*/);
51822 			}
51823 
51824 			DUK_HEAPHDR_CLEAR_REACHABLE(curr);
51825 			/* Keep FINALIZED if set, used if rescue decisions are postponed. */
51826 			/* Keep FINALIZABLE for objects on finalize_list. */
51827 			DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(curr));
51828 		} else {
51829 			/*
51830 			 *  Unreachable object:
51831 			 *    - If FINALIZED, object was finalized but not
51832 			 *      rescued.  This doesn't affect freeing.
51833 			 *    - Otherwise normal unreachable object.
51834 			 *
51835 			 *  There's no guard preventing a FINALIZED object
51836 			 *  from being freed while finalizers execute: the
51837 			 *  artificial finalize_list reachability roots can't
51838 			 *  cause an incorrect free decision (but can cause
51839 			 *  an incorrect rescue decision).
51840 			 */
51841 
51842 #if defined(DUK_USE_REFERENCE_COUNTING)
51843 			/* Non-zero refcounts should not happen because we refcount
51844 			 * finalize all unreachable objects which should cancel out
51845 			 * refcounts (even for cycles).
51846 			 */
51847 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) == 0);
51848 #endif
51849 			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));
51850 
51851 #if defined(DUK_USE_DEBUG)
51852 			if (DUK_HEAPHDR_HAS_FINALIZED(curr)) {
51853 				DUK_DD(DUK_DDPRINT("sweep; unreachable, finalized --> finalized object not rescued: %p", (void *) curr));
51854 			} else {
51855 				DUK_DD(DUK_DDPRINT("sweep; not reachable --> free: %p", (void *) curr));
51856 			}
51857 
51858 #endif
51859 
51860 			/* Note: object cannot be a finalizable unreachable object, as
51861 			 * they have been marked temporarily reachable for this round,
51862 			 * and are handled above.
51863 			 */
51864 
51865 #if defined(DUK_USE_DEBUG)
51866 			count_free++;
51867 #endif
51868 
51869 			/* Weak refs should be handled here, but no weak refs for
51870 			 * any non-string objects exist right now.
51871 			 */
51872 
51873 			/* Free object and all auxiliary (non-heap) allocs. */
51874 			duk_heap_free_heaphdr_raw(heap, curr);
51875 		}
51876 
51877 		curr = next;
51878 	}
51879 
51880 	if (prev != NULL) {
51881 		DUK_HEAPHDR_SET_NEXT(heap, prev, NULL);
51882 	}
51883 	DUK_HEAPHDR_ASSERT_LINKS(heap, prev);
51884 
51885 #if defined(DUK_USE_DEBUG)
51886 	DUK_D(DUK_DPRINT("mark-and-sweep sweep objects (non-string): %ld freed, %ld kept, %ld rescued, %ld queued for finalization",
51887 	                 (long) count_free, (long) count_keep, (long) count_rescue, (long) count_finalize));
51888 #endif
51889 	*out_count_keep = count_keep;
51890 }
51891 
51892 /*
51893  *  Litcache helpers.
51894  */
51895 
51896 #if defined(DUK_USE_LITCACHE_SIZE)
51897 DUK_LOCAL void duk__wipe_litcache(duk_heap *heap) {
51898 	duk_uint_t i;
51899 	duk_litcache_entry *e;
51900 
51901 	e = heap->litcache;
51902 	for (i = 0; i < DUK_USE_LITCACHE_SIZE; i++) {
51903 		e->addr = NULL;
51904 		/* e->h does not need to be invalidated: when e->addr is
51905 		 * NULL, e->h is considered garbage.
51906 		 */
51907 		e++;
51908 	}
51909 }
51910 #endif  /* DUK_USE_LITCACHE_SIZE */
51911 
51912 /*
51913  *  Object compaction.
51914  *
51915  *  Compaction is assumed to never throw an error.
51916  */
51917 
51918 DUK_LOCAL int duk__protected_compact_object(duk_hthread *thr, void *udata) {
51919 	duk_hobject *obj;
51920 	/* XXX: for threads, compact stacks? */
51921 
51922 	DUK_UNREF(udata);
51923 	obj = duk_known_hobject(thr, -1);
51924 	duk_hobject_compact_props(thr, obj);
51925 	return 0;
51926 }
51927 
51928 #if defined(DUK_USE_DEBUG)
51929 DUK_LOCAL void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_heaphdr *start, duk_size_t *p_count_check, duk_size_t *p_count_compact, duk_size_t *p_count_bytes_saved) {
51930 #else
51931 DUK_LOCAL void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_heaphdr *start) {
51932 #endif
51933 	duk_heaphdr *curr;
51934 #if defined(DUK_USE_DEBUG)
51935 	duk_size_t old_size, new_size;
51936 #endif
51937 	duk_hobject *obj;
51938 
51939 	DUK_UNREF(heap);
51940 
51941 	curr = start;
51942 	while (curr) {
51943 		DUK_DDD(DUK_DDDPRINT("mark-and-sweep compact: %p", (void *) curr));
51944 
51945 		if (DUK_HEAPHDR_GET_TYPE(curr) != DUK_HTYPE_OBJECT) {
51946 			goto next;
51947 		}
51948 		obj = (duk_hobject *) curr;
51949 
51950 #if defined(DUK_USE_DEBUG)
51951 		old_size = DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
51952 		                                      DUK_HOBJECT_GET_ASIZE(obj),
51953 		                                      DUK_HOBJECT_GET_HSIZE(obj));
51954 #endif
51955 
51956 		DUK_DD(DUK_DDPRINT("compact object: %p", (void *) obj));
51957 		duk_push_hobject(thr, obj);
51958 		/* XXX: disable error handlers for duration of compaction? */
51959 		duk_safe_call(thr, duk__protected_compact_object, NULL, 1, 0);
51960 
51961 #if defined(DUK_USE_DEBUG)
51962 		new_size = DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
51963 		                                      DUK_HOBJECT_GET_ASIZE(obj),
51964 		                                      DUK_HOBJECT_GET_HSIZE(obj));
51965 #endif
51966 
51967 #if defined(DUK_USE_DEBUG)
51968 		(*p_count_compact)++;
51969 		(*p_count_bytes_saved) += (duk_size_t) (old_size - new_size);
51970 #endif
51971 
51972 	 next:
51973 		curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
51974 #if defined(DUK_USE_DEBUG)
51975 		(*p_count_check)++;
51976 #endif
51977 	}
51978 }
51979 
51980 DUK_LOCAL void duk__compact_objects(duk_heap *heap) {
51981 	/* XXX: which lists should participate?  to be finalized? */
51982 #if defined(DUK_USE_DEBUG)
51983 	duk_size_t count_check = 0;
51984 	duk_size_t count_compact = 0;
51985 	duk_size_t count_bytes_saved = 0;
51986 #endif
51987 
51988 	DUK_DD(DUK_DDPRINT("duk__compact_objects: %p", (void *) heap));
51989 
51990 	DUK_ASSERT(heap->heap_thread != NULL);
51991 
51992 #if defined(DUK_USE_DEBUG)
51993 	duk__compact_object_list(heap, heap->heap_thread, heap->heap_allocated, &count_check, &count_compact, &count_bytes_saved);
51994 #if defined(DUK_USE_FINALIZER_SUPPORT)
51995 	duk__compact_object_list(heap, heap->heap_thread, heap->finalize_list, &count_check, &count_compact, &count_bytes_saved);
51996 #endif
51997 #else
51998 	duk__compact_object_list(heap, heap->heap_thread, heap->heap_allocated);
51999 #if defined(DUK_USE_FINALIZER_SUPPORT)
52000 	duk__compact_object_list(heap, heap->heap_thread, heap->finalize_list);
52001 #endif
52002 #endif
52003 #if defined(DUK_USE_REFERENCE_COUNTING)
52004 	DUK_ASSERT(heap->refzero_list == NULL);  /* Always handled to completion inline in DECREF. */
52005 #endif
52006 
52007 #if defined(DUK_USE_DEBUG)
52008 	DUK_D(DUK_DPRINT("mark-and-sweep compact objects: %ld checked, %ld compaction attempts, %ld bytes saved by compaction",
52009 	                 (long) count_check, (long) count_compact, (long) count_bytes_saved));
52010 #endif
52011 }
52012 
52013 /*
52014  *  Assertion helpers.
52015  */
52016 
52017 #if defined(DUK_USE_ASSERTIONS)
52018 typedef void (*duk__gc_heaphdr_assert)(duk_heap *heap, duk_heaphdr *h);
52019 typedef void (*duk__gc_hstring_assert)(duk_heap *heap, duk_hstring *h);
52020 
52021 DUK_LOCAL void duk__assert_walk_list(duk_heap *heap, duk_heaphdr *start, duk__gc_heaphdr_assert func) {
52022 	duk_heaphdr *curr;
52023 	for (curr = start; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
52024 		func(heap, curr);
52025 	}
52026 }
52027 
52028 DUK_LOCAL void duk__assert_walk_strtable(duk_heap *heap, duk__gc_hstring_assert func) {
52029 	duk_uint32_t i;
52030 
52031 	for (i = 0; i < heap->st_size; i++) {
52032 		duk_hstring *h;
52033 
52034 #if defined(DUK_USE_STRTAB_PTRCOMP)
52035 		h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
52036 #else
52037 		h = heap->strtable[i];
52038 #endif
52039 		while (h != NULL) {
52040 			func(heap, h);
52041 			h = h->hdr.h_next;
52042 		}
52043 	}
52044 }
52045 
52046 DUK_LOCAL void duk__assert_heaphdr_flags_cb(duk_heap *heap, duk_heaphdr *h) {
52047 	DUK_UNREF(heap);
52048 	DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(h));
52049 	DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(h));
52050 	DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(h));
52051 	/* may have FINALIZED */
52052 }
52053 DUK_LOCAL void duk__assert_heaphdr_flags(duk_heap *heap) {
52054 	duk__assert_walk_list(heap, heap->heap_allocated, duk__assert_heaphdr_flags_cb);
52055 #if defined(DUK_USE_REFERENCE_COUNTING)
52056 	DUK_ASSERT(heap->refzero_list == NULL);  /* Always handled to completion inline in DECREF. */
52057 #endif
52058 	/* XXX: Assertions for finalize_list? */
52059 }
52060 
52061 DUK_LOCAL void duk__assert_validity_cb1(duk_heap *heap, duk_heaphdr *h) {
52062 	DUK_UNREF(heap);
52063 	DUK_ASSERT(DUK_HEAPHDR_IS_OBJECT(h) || DUK_HEAPHDR_IS_BUFFER(h));
52064 	duk_heaphdr_assert_valid_subclassed(h);
52065 }
52066 DUK_LOCAL void duk__assert_validity_cb2(duk_heap *heap, duk_hstring *h) {
52067 	DUK_UNREF(heap);
52068 	DUK_ASSERT(DUK_HEAPHDR_IS_STRING((duk_heaphdr *) h));
52069 	duk_heaphdr_assert_valid_subclassed((duk_heaphdr *) h);
52070 }
52071 DUK_LOCAL void duk__assert_validity(duk_heap *heap) {
52072 	duk__assert_walk_list(heap, heap->heap_allocated, duk__assert_validity_cb1);
52073 #if defined(DUK_USE_FINALIZER_SUPPORT)
52074 	duk__assert_walk_list(heap, heap->finalize_list, duk__assert_validity_cb1);
52075 #endif
52076 #if defined(DUK_USE_REFERENCE_COUNTING)
52077 	duk__assert_walk_list(heap, heap->refzero_list, duk__assert_validity_cb1);
52078 #endif
52079 	duk__assert_walk_strtable(heap, duk__assert_validity_cb2);
52080 }
52081 
52082 #if defined(DUK_USE_REFERENCE_COUNTING)
52083 DUK_LOCAL void duk__assert_valid_refcounts_cb(duk_heap *heap, duk_heaphdr *h) {
52084 	/* Cannot really assert much w.r.t. refcounts now. */
52085 
52086 	DUK_UNREF(heap);
52087 	if (DUK_HEAPHDR_GET_REFCOUNT(h) == 0 &&
52088 	    DUK_HEAPHDR_HAS_FINALIZED(h)) {
52089 		/* An object may be in heap_allocated list with a zero
52090 		 * refcount if it has just been finalized and is waiting
52091 		 * to be collected by the next cycle.
52092 		 * (This doesn't currently happen however.)
52093 		 */
52094 	} else if (DUK_HEAPHDR_GET_REFCOUNT(h) == 0) {
52095 		/* An object may be in heap_allocated list with a zero
52096 		 * refcount also if it is a temporary object created
52097 		 * during debugger paused state.  It will get collected
52098 		 * by mark-and-sweep based on its reachability status
52099 		 * (presumably not reachable because refcount is 0).
52100 		 */
52101 	}
52102 	DUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(h) >= 0);  /* Unsigned. */
52103 }
52104 DUK_LOCAL void duk__assert_valid_refcounts(duk_heap *heap) {
52105 	duk__assert_walk_list(heap, heap->heap_allocated, duk__assert_valid_refcounts_cb);
52106 }
52107 
52108 DUK_LOCAL void duk__clear_assert_refcounts_cb1(duk_heap *heap, duk_heaphdr *h) {
52109 	DUK_UNREF(heap);
52110 	h->h_assert_refcount = 0;
52111 }
52112 DUK_LOCAL void duk__clear_assert_refcounts_cb2(duk_heap *heap, duk_hstring *h) {
52113 	DUK_UNREF(heap);
52114 	((duk_heaphdr *) h)->h_assert_refcount = 0;
52115 }
52116 DUK_LOCAL void duk__clear_assert_refcounts(duk_heap *heap) {
52117 	duk__assert_walk_list(heap, heap->heap_allocated, duk__clear_assert_refcounts_cb1);
52118 #if defined(DUK_USE_FINALIZER_SUPPORT)
52119 	duk__assert_walk_list(heap, heap->finalize_list, duk__clear_assert_refcounts_cb1);
52120 #endif
52121 #if defined(DUK_USE_REFERENCE_COUNTING)
52122 	duk__assert_walk_list(heap, heap->refzero_list, duk__clear_assert_refcounts_cb1);
52123 #endif
52124 	duk__assert_walk_strtable(heap, duk__clear_assert_refcounts_cb2);
52125 }
52126 
52127 DUK_LOCAL void duk__check_refcount_heaphdr(duk_heaphdr *hdr) {
52128 	duk_bool_t count_ok;
52129 	duk_size_t expect_refc;
52130 
52131 	/* The refcount check only makes sense for reachable objects on
52132 	 * heap_allocated or string table, after the sweep phase.  Prior to
52133 	 * sweep phase refcounts will include references that are not visible
52134 	 * via reachability roots.
52135 	 *
52136 	 * Because we're called after the sweep phase, all heap objects on
52137 	 * heap_allocated are reachable.  REACHABLE flags have already been
52138 	 * cleared so we can't check them.
52139 	 */
52140 
52141 	/* ROM objects have intentionally incorrect refcount (1), but we won't
52142 	 * check them.
52143 	 */
52144 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(hdr));
52145 
52146 	expect_refc = hdr->h_assert_refcount;
52147 	if (DUK_HEAPHDR_IS_STRING(hdr) && DUK_HSTRING_HAS_PINNED_LITERAL((duk_hstring *) hdr)) {
52148 		expect_refc++;
52149 	}
52150 	count_ok = ((duk_size_t) DUK_HEAPHDR_GET_REFCOUNT(hdr) == expect_refc);
52151 	if (!count_ok) {
52152 		DUK_D(DUK_DPRINT("refcount mismatch for: %p: header=%ld counted=%ld --> %!iO",
52153 		                 (void *) hdr, (long) DUK_HEAPHDR_GET_REFCOUNT(hdr),
52154 		                 (long) hdr->h_assert_refcount, hdr));
52155 		DUK_ASSERT(0);
52156 	}
52157 }
52158 
52159 DUK_LOCAL void duk__check_assert_refcounts_cb1(duk_heap *heap, duk_heaphdr *h) {
52160 	DUK_UNREF(heap);
52161 	duk__check_refcount_heaphdr(h);
52162 }
52163 DUK_LOCAL void duk__check_assert_refcounts_cb2(duk_heap *heap, duk_hstring *h) {
52164 	DUK_UNREF(heap);
52165 	duk__check_refcount_heaphdr((duk_heaphdr *) h);
52166 }
52167 DUK_LOCAL void duk__check_assert_refcounts(duk_heap *heap) {
52168 	duk__assert_walk_list(heap, heap->heap_allocated, duk__check_assert_refcounts_cb1);
52169 #if defined(DUK_USE_FINALIZER_SUPPORT)
52170 	duk__assert_walk_list(heap, heap->finalize_list, duk__check_assert_refcounts_cb1);
52171 #endif
52172 	/* XXX: Assert anything for refzero_list? */
52173 	duk__assert_walk_strtable(heap, duk__check_assert_refcounts_cb2);
52174 }
52175 #endif  /* DUK_USE_REFERENCE_COUNTING */
52176 
52177 #if defined(DUK_USE_LITCACHE_SIZE)
52178 DUK_LOCAL void duk__assert_litcache_nulls(duk_heap *heap) {
52179 	duk_uint_t i;
52180 	duk_litcache_entry *e;
52181 
52182 	e = heap->litcache;
52183 	for (i = 0; i < DUK_USE_LITCACHE_SIZE; i++) {
52184 		/* Entry addresses were NULLed before mark-and-sweep, check
52185 		 * that they're still NULL afterwards to ensure no pointers
52186 		 * were recorded through any side effects.
52187 		 */
52188 		DUK_ASSERT(e->addr == NULL);
52189 	}
52190 }
52191 #endif  /* DUK_USE_LITCACHE_SIZE */
52192 #endif  /* DUK_USE_ASSERTIONS */
52193 
52194 /*
52195  *  Stats dump.
52196  */
52197 
52198 #if defined(DUK_USE_DEBUG)
52199 DUK_LOCAL void duk__dump_stats(duk_heap *heap) {
52200 	DUK_D(DUK_DPRINT("stats executor: opcodes=%ld, interrupt=%ld, throw=%ld",
52201 	                 (long) heap->stats_exec_opcodes, (long) heap->stats_exec_interrupt,
52202 	                 (long) heap->stats_exec_throw));
52203 	DUK_D(DUK_DPRINT("stats call: all=%ld, tailcall=%ld, ecmatoecma=%ld",
52204 	                 (long) heap->stats_call_all, (long) heap->stats_call_tailcall,
52205 	                 (long) heap->stats_call_ecmatoecma));
52206 	DUK_D(DUK_DPRINT("stats safecall: all=%ld, nothrow=%ld, throw=%ld",
52207 	                 (long) heap->stats_safecall_all, (long) heap->stats_safecall_nothrow,
52208 	                 (long) heap->stats_safecall_throw));
52209 	DUK_D(DUK_DPRINT("stats mark-and-sweep: try_count=%ld, skip_count=%ld, emergency_count=%ld",
52210 	                 (long) heap->stats_ms_try_count, (long) heap->stats_ms_skip_count,
52211 	                 (long) heap->stats_ms_emergency_count));
52212 	DUK_D(DUK_DPRINT("stats stringtable: intern_hit=%ld, intern_miss=%ld, "
52213 	                 "resize_check=%ld, resize_grow=%ld, resize_shrink=%ld, "
52214 	                 "litcache_hit=%ld, litcache_miss=%ld, litcache_pin=%ld",
52215 	                 (long) heap->stats_strtab_intern_hit, (long) heap->stats_strtab_intern_miss,
52216 	                 (long) heap->stats_strtab_resize_check, (long) heap->stats_strtab_resize_grow,
52217 	                 (long) heap->stats_strtab_resize_shrink, (long) heap->stats_strtab_litcache_hit,
52218 	                 (long) heap->stats_strtab_litcache_miss, (long) heap->stats_strtab_litcache_pin));
52219 	DUK_D(DUK_DPRINT("stats object: realloc_props=%ld, abandon_array=%ld",
52220 	                 (long) heap->stats_object_realloc_props, (long) heap->stats_object_abandon_array));
52221 	DUK_D(DUK_DPRINT("stats getownpropdesc: count=%ld, hit=%ld, miss=%ld",
52222 	                 (long) heap->stats_getownpropdesc_count, (long) heap->stats_getownpropdesc_hit,
52223 	                 (long) heap->stats_getownpropdesc_miss));
52224 	DUK_D(DUK_DPRINT("stats getpropdesc: count=%ld, hit=%ld, miss=%ld",
52225 	                 (long) heap->stats_getpropdesc_count, (long) heap->stats_getpropdesc_hit,
52226 	                 (long) heap->stats_getpropdesc_miss));
52227 	DUK_D(DUK_DPRINT("stats getprop: all=%ld, arrayidx=%ld, bufobjidx=%ld, "
52228 	                 "bufferidx=%ld, bufferlen=%ld, stringidx=%ld, stringlen=%ld, "
52229 	                 "proxy=%ld, arguments=%ld",
52230 	                 (long) heap->stats_getprop_all, (long) heap->stats_getprop_arrayidx,
52231 	                 (long) heap->stats_getprop_bufobjidx, (long) heap->stats_getprop_bufferidx,
52232 	                 (long) heap->stats_getprop_bufferlen, (long) heap->stats_getprop_stringidx,
52233 	                 (long) heap->stats_getprop_stringlen, (long) heap->stats_getprop_proxy,
52234 	                 (long) heap->stats_getprop_arguments));
52235 	DUK_D(DUK_DPRINT("stats putprop: all=%ld, arrayidx=%ld, bufobjidx=%ld, "
52236 	                 "bufferidx=%ld, proxy=%ld",
52237 	                 (long) heap->stats_putprop_all, (long) heap->stats_putprop_arrayidx,
52238 	                 (long) heap->stats_putprop_bufobjidx, (long) heap->stats_putprop_bufferidx,
52239 	                 (long) heap->stats_putprop_proxy));
52240 	DUK_D(DUK_DPRINT("stats getvar: all=%ld",
52241 	                 (long) heap->stats_getvar_all));
52242 	DUK_D(DUK_DPRINT("stats putvar: all=%ld",
52243 	                 (long) heap->stats_putvar_all));
52244 	DUK_D(DUK_DPRINT("stats envrec: delayedcreate=%ld, create=%ld, newenv=%ld, oldenv=%ld, pushclosure=%ld",
52245 	                 (long) heap->stats_envrec_delayedcreate,
52246 	                 (long) heap->stats_envrec_create,
52247 	                 (long) heap->stats_envrec_newenv,
52248 	                 (long) heap->stats_envrec_oldenv,
52249 	                 (long) heap->stats_envrec_pushclosure));
52250 }
52251 #endif  /* DUK_USE_DEBUG */
52252 
52253 /*
52254  *  Main mark-and-sweep function.
52255  *
52256  *  'flags' represents the features requested by the caller.  The current
52257  *  heap->ms_base_flags is ORed automatically into the flags; the base flags
52258  *  mask typically prevents certain mark-and-sweep operation to avoid trouble.
52259  */
52260 
52261 DUK_INTERNAL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags) {
52262 	duk_size_t count_keep_obj;
52263 	duk_size_t count_keep_str;
52264 #if defined(DUK_USE_VOLUNTARY_GC)
52265 	duk_size_t tmp;
52266 #endif
52267 	duk_bool_t entry_creating_error;
52268 
52269 	DUK_STATS_INC(heap, stats_ms_try_count);
52270 #if defined(DUK_USE_DEBUG)
52271 	if (flags & DUK_MS_FLAG_EMERGENCY) {
52272 		DUK_STATS_INC(heap, stats_ms_emergency_count);
52273 	}
52274 #endif
52275 
52276 	/* If debugger is paused, garbage collection is disabled by default.
52277 	 * This is achieved by bumping ms_prevent_count when becoming paused.
52278 	 */
52279 	DUK_ASSERT(!DUK_HEAP_HAS_DEBUGGER_PAUSED(heap) || heap->ms_prevent_count > 0);
52280 
52281 	/* Prevention/recursion check as soon as possible because we may
52282 	 * be called a number of times when voluntary mark-and-sweep is
52283 	 * pending.
52284 	 */
52285 	if (heap->ms_prevent_count != 0) {
52286 		DUK_DD(DUK_DDPRINT("reject recursive mark-and-sweep"));
52287 		DUK_STATS_INC(heap, stats_ms_skip_count);
52288 		return;
52289 	}
52290 	DUK_ASSERT(heap->ms_running == 0);  /* ms_prevent_count is bumped when ms_running is set */
52291 
52292 	/* Heap_thread is used during mark-and-sweep for refcount finalization
52293 	 * (it's also used for finalizer execution once mark-and-sweep is
52294 	 * complete).  Heap allocation code ensures heap_thread is set and
52295 	 * properly initialized before setting ms_prevent_count to 0.
52296 	 */
52297 	DUK_ASSERT(heap->heap_thread != NULL);
52298 	DUK_ASSERT(heap->heap_thread->valstack != NULL);
52299 
52300 	DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) starting, requested flags: 0x%08lx, effective flags: 0x%08lx",
52301 	                 (unsigned long) flags, (unsigned long) (flags | heap->ms_base_flags)));
52302 
52303 	flags |= heap->ms_base_flags;
52304 #if defined(DUK_USE_FINALIZER_SUPPORT)
52305 	if (heap->finalize_list != NULL) {
52306 		flags |= DUK_MS_FLAG_POSTPONE_RESCUE;
52307 	}
52308 #endif
52309 
52310 	/*
52311 	 *  Assertions before
52312 	 */
52313 
52314 #if defined(DUK_USE_ASSERTIONS)
52315 	DUK_ASSERT(heap->ms_prevent_count == 0);
52316 	DUK_ASSERT(heap->ms_running == 0);
52317 	DUK_ASSERT(!DUK_HEAP_HAS_DEBUGGER_PAUSED(heap));
52318 	DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap));
52319 	DUK_ASSERT(heap->ms_recursion_depth == 0);
52320 	duk__assert_heaphdr_flags(heap);
52321 	duk__assert_validity(heap);
52322 #if defined(DUK_USE_REFERENCE_COUNTING)
52323 	/* Note: heap->refzero_free_running may be true; a refcount
52324 	 * finalizer may trigger a mark-and-sweep.
52325 	 */
52326 	duk__assert_valid_refcounts(heap);
52327 #endif  /* DUK_USE_REFERENCE_COUNTING */
52328 #endif  /* DUK_USE_ASSERTIONS */
52329 
52330 	/*
52331 	 *  Begin
52332 	 */
52333 
52334 	DUK_ASSERT(heap->ms_prevent_count == 0);
52335 	DUK_ASSERT(heap->ms_running == 0);
52336 	heap->ms_prevent_count = 1;
52337 	heap->ms_running = 1;
52338 	entry_creating_error = heap->creating_error;
52339 	heap->creating_error = 0;
52340 
52341 	/*
52342 	 *  Free activation/catcher freelists on every mark-and-sweep for now.
52343 	 *  This is an initial rough draft; ideally we'd keep count of the
52344 	 *  freelist size and free only excess entries.
52345 	 */
52346 
52347 	DUK_D(DUK_DPRINT("freeing temporary freelists"));
52348 	duk_heap_free_freelists(heap);
52349 
52350 	/*
52351 	 *  Mark roots, hoping that recursion limit is not normally hit.
52352 	 *  If recursion limit is hit, run additional reachability rounds
52353 	 *  starting from "temproots" until marking is complete.
52354 	 *
52355 	 *  Marking happens in two phases: first we mark actual reachability
52356 	 *  roots (and run "temproots" to complete the process).  Then we
52357 	 *  check which objects are unreachable and are finalizable; such
52358 	 *  objects are marked as FINALIZABLE and marked as reachability
52359 	 *  (and "temproots" is run again to complete the process).
52360 	 *
52361 	 *  The heap finalize_list must also be marked as a reachability root.
52362 	 *  There may be objects on the list from a previous round if the
52363 	 *  previous run had finalizer skip flag.
52364 	 */
52365 
52366 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
52367 	duk__clear_assert_refcounts(heap);
52368 #endif
52369 #if defined(DUK_USE_LITCACHE_SIZE)
52370 	duk__wipe_litcache(heap);
52371 #endif
52372 	duk__mark_roots_heap(heap);               /* Mark main reachability roots. */
52373 #if defined(DUK_USE_REFERENCE_COUNTING)
52374 	DUK_ASSERT(heap->refzero_list == NULL);   /* Always handled to completion inline in DECREF. */
52375 #endif
52376 	duk__mark_temproots_by_heap_scan(heap);   /* Temproots. */
52377 
52378 #if defined(DUK_USE_FINALIZER_SUPPORT)
52379 	duk__mark_finalizable(heap);              /* Mark finalizable as reachability roots. */
52380 	duk__mark_finalize_list(heap);            /* Mark finalizer work list as reachability roots. */
52381 #endif
52382 	duk__mark_temproots_by_heap_scan(heap);   /* Temproots. */
52383 
52384 	/*
52385 	 *  Sweep garbage and remove marking flags, and move objects with
52386 	 *  finalizers to the finalizer work list.
52387 	 *
52388 	 *  Objects to be swept need to get their refcounts finalized before
52389 	 *  they are swept.  In other words, their target object refcounts
52390 	 *  need to be decreased.  This has to be done before freeing any
52391 	 *  objects to avoid decref'ing dangling pointers (which may happen
52392 	 *  even without bugs, e.g. with reference loops)
52393 	 *
52394 	 *  Because strings don't point to other heap objects, similar
52395 	 *  finalization is not necessary for strings.
52396 	 */
52397 
52398 	/* XXX: more emergency behavior, e.g. find smaller hash sizes etc */
52399 
52400 #if defined(DUK_USE_REFERENCE_COUNTING)
52401 	duk__finalize_refcounts(heap);
52402 #endif
52403 	duk__sweep_heap(heap, flags, &count_keep_obj);
52404 	duk__sweep_stringtable(heap, &count_keep_str);
52405 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
52406 	duk__check_assert_refcounts(heap);
52407 #endif
52408 #if defined(DUK_USE_REFERENCE_COUNTING)
52409 	DUK_ASSERT(heap->refzero_list == NULL);   /* Always handled to completion inline in DECREF. */
52410 #endif
52411 #if defined(DUK_USE_FINALIZER_SUPPORT)
52412 	duk__clear_finalize_list_flags(heap);
52413 #endif
52414 
52415 	/*
52416 	 *  Object compaction (emergency only).
52417 	 *
52418 	 *  Object compaction is a separate step after sweeping, as there is
52419 	 *  more free memory for it to work with.  Also, currently compaction
52420 	 *  may insert new objects into the heap allocated list and the string
52421 	 *  table which we don't want to do during a sweep (the reachability
52422 	 *  flags of such objects would be incorrect).  The objects inserted
52423 	 *  are currently:
52424 	 *
52425 	 *    - a temporary duk_hbuffer for a new properties allocation
52426 	 *    - if array part is abandoned, string keys are interned
52427 	 *
52428 	 *  The object insertions go to the front of the list, so they do not
52429 	 *  cause an infinite loop (they are not compacted).
52430 	 *
52431 	 *  At present compaction is not allowed when mark-and-sweep runs
52432 	 *  during error handling because it involves a duk_safe_call()
52433 	 *  interfering with error state.
52434 	 */
52435 
52436 	if ((flags & DUK_MS_FLAG_EMERGENCY) &&
52437 	    !(flags & DUK_MS_FLAG_NO_OBJECT_COMPACTION)) {
52438 		if (heap->lj.type != DUK_LJ_TYPE_UNKNOWN) {
52439 			DUK_D(DUK_DPRINT("lj.type (%ld) not DUK_LJ_TYPE_UNKNOWN, skip object compaction", (long) heap->lj.type));
52440 		} else {
52441 			DUK_D(DUK_DPRINT("object compaction"));
52442 			duk__compact_objects(heap);
52443 		}
52444 	}
52445 
52446 	/*
52447 	 *  String table resize check.
52448 	 *
52449 	 *  This is mainly useful in emergency GC: if the string table load
52450 	 *  factor is really low for some reason, we can shrink the string
52451 	 *  table to a smaller size and free some memory in the process.
52452 	 *  Only execute in emergency GC.  String table has internal flags
52453 	 *  to protect against recursive resizing if this mark-and-sweep pass
52454 	 *  was triggered by a string table resize.
52455 	 */
52456 
52457 	if (flags & DUK_MS_FLAG_EMERGENCY) {
52458 		DUK_D(DUK_DPRINT("stringtable resize check in emergency gc"));
52459 		duk_heap_strtable_force_resize(heap);
52460 	}
52461 
52462 	/*
52463 	 *  Finish
52464 	 */
52465 
52466 	DUK_ASSERT(heap->ms_prevent_count == 1);
52467 	DUK_ASSERT(heap->ms_running == 1);
52468 	heap->ms_prevent_count = 0;
52469 	heap->ms_running = 0;
52470 	heap->creating_error = entry_creating_error;  /* for nested error handling, see GH-2278 */
52471 
52472 	/*
52473 	 *  Assertions after
52474 	 */
52475 
52476 #if defined(DUK_USE_ASSERTIONS)
52477 	DUK_ASSERT(heap->ms_prevent_count == 0);
52478 	DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap));
52479 	DUK_ASSERT(heap->ms_recursion_depth == 0);
52480 	duk__assert_heaphdr_flags(heap);
52481 	duk__assert_validity(heap);
52482 #if defined(DUK_USE_REFERENCE_COUNTING)
52483 	/* Note: heap->refzero_free_running may be true; a refcount
52484 	 * finalizer may trigger a mark-and-sweep.
52485 	 */
52486 	duk__assert_valid_refcounts(heap);
52487 #endif  /* DUK_USE_REFERENCE_COUNTING */
52488 #if defined(DUK_USE_LITCACHE_SIZE)
52489 	duk__assert_litcache_nulls(heap);
52490 #endif  /* DUK_USE_LITCACHE_SIZE */
52491 #endif  /* DUK_USE_ASSERTIONS */
52492 
52493 	/*
52494 	 *  Reset trigger counter
52495 	 */
52496 
52497 #if defined(DUK_USE_VOLUNTARY_GC)
52498 	tmp = (count_keep_obj + count_keep_str) / 256;
52499 	heap->ms_trigger_counter = (duk_int_t) (
52500 	    (tmp * DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT) +
52501 	    DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD);
52502 	DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, trigger reset to %ld",
52503 	                 (long) count_keep_obj, (long) count_keep_str, (long) heap->ms_trigger_counter));
52504 #else
52505 	DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, no voluntary trigger",
52506 	                 (long) count_keep_obj, (long) count_keep_str));
52507 #endif
52508 
52509 	/*
52510 	 *  Stats dump
52511 	 */
52512 
52513 #if defined(DUK_USE_DEBUG)
52514 	duk__dump_stats(heap);
52515 #endif
52516 
52517 	/*
52518 	 *  Finalize objects in the finalization work list.  Finalized
52519 	 *  objects are queued back to heap_allocated with FINALIZED set.
52520 	 *
52521 	 *  Since finalizers may cause arbitrary side effects, they are
52522 	 *  prevented e.g. during string table and object property allocation
52523 	 *  resizing using heap->pf_prevent_count.  In this case the objects
52524 	 *  remain in the finalization work list after mark-and-sweep exits
52525 	 *  and they may be finalized on the next pass or any DECREF checking
52526 	 *  for finalize_list.
52527 	 *
52528 	 *  As of Duktape 2.1 finalization happens outside mark-and-sweep
52529 	 *  protection.  Mark-and-sweep is allowed while the finalize_list
52530 	 *  is being processed, but no rescue decisions are done while the
52531 	 *  process is on-going.  This avoids incorrect rescue decisions
52532 	 *  if an object is considered reachable (and thus rescued) because
52533 	 *  of a reference via finalize_list (which is considered a reachability
52534 	 *  root).  When finalize_list is being processed, reachable objects
52535 	 *  with FINALIZED set will just keep their FINALIZED flag for later
52536 	 *  mark-and-sweep processing.
52537 	 *
52538 	 *  This could also be handled (a bit better) by having a more refined
52539 	 *  notion of reachability for rescue/free decisions.
52540 	 *
52541 	 *  XXX: avoid finalizer execution when doing emergency GC?
52542 	 */
52543 
52544 #if defined(DUK_USE_FINALIZER_SUPPORT)
52545 	/* Attempt to process finalize_list, pf_prevent_count check
52546 	 * is inside the target.
52547 	 */
52548 	duk_heap_process_finalize_list(heap);
52549 #endif  /* DUK_USE_FINALIZER_SUPPORT */
52550 }
52551 /*
52552  *  Memory allocation handling.
52553  */
52554 
52555 /* #include duk_internal.h -> already included */
52556 
52557 /*
52558  *  Allocate memory with garbage collection.
52559  */
52560 
52561 /* Slow path: voluntary GC triggered, first alloc attempt failed, or zero size. */
52562 DUK_LOCAL DUK_NOINLINE_PERF DUK_COLD void *duk__heap_mem_alloc_slowpath(duk_heap *heap, duk_size_t size) {
52563 	void *res;
52564 	duk_small_int_t i;
52565 
52566 	DUK_ASSERT(heap != NULL);
52567 	DUK_ASSERT(heap->alloc_func != NULL);
52568 	DUK_ASSERT_DISABLE(size >= 0);
52569 
52570 	if (size == 0) {
52571 		DUK_D(DUK_DPRINT("zero size alloc in slow path, return NULL"));
52572 		return NULL;
52573 	}
52574 
52575 	DUK_D(DUK_DPRINT("first alloc attempt failed or voluntary GC limit reached, attempt to gc and retry"));
52576 
52577 #if 0
52578 	/*
52579 	 *  If GC is already running there is no point in attempting a GC
52580 	 *  because it will be skipped.  This could be checked for explicitly,
52581 	 *  but it isn't actually needed: the loop below will eventually
52582 	 *  fail resulting in a NULL.
52583 	 */
52584 
52585 	if (heap->ms_prevent_count != 0) {
52586 		DUK_D(DUK_DPRINT("duk_heap_mem_alloc() failed, gc in progress (gc skipped), alloc size %ld", (long) size));
52587 		return NULL;
52588 	}
52589 #endif
52590 
52591 	/*
52592 	 *  Retry with several GC attempts.  Initial attempts are made without
52593 	 *  emergency mode; later attempts use emergency mode which minimizes
52594 	 *  memory allocations forcibly.
52595 	 */
52596 
52597 	for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
52598 		duk_small_uint_t flags;
52599 
52600 		flags = 0;
52601 		if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
52602 			flags |= DUK_MS_FLAG_EMERGENCY;
52603 		}
52604 
52605 		duk_heap_mark_and_sweep(heap, flags);
52606 
52607 		DUK_ASSERT(size > 0);
52608 		res = heap->alloc_func(heap->heap_udata, size);
52609 		if (res != NULL) {
52610 			DUK_D(DUK_DPRINT("duk_heap_mem_alloc() succeeded after gc (pass %ld), alloc size %ld",
52611 			                 (long) (i + 1), (long) size));
52612 			return res;
52613 		}
52614 	}
52615 
52616 	DUK_D(DUK_DPRINT("duk_heap_mem_alloc() failed even after gc, alloc size %ld", (long) size));
52617 	return NULL;
52618 }
52619 
52620 DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size) {
52621 	void *res;
52622 
52623 	DUK_ASSERT(heap != NULL);
52624 	DUK_ASSERT(heap->alloc_func != NULL);
52625 	DUK_ASSERT_DISABLE(size >= 0);
52626 
52627 #if defined(DUK_USE_VOLUNTARY_GC)
52628 	/* Voluntary periodic GC (if enabled). */
52629 	if (DUK_UNLIKELY(--(heap)->ms_trigger_counter < 0)) {
52630 		goto slowpath;
52631 	}
52632 #endif
52633 
52634 #if defined(DUK_USE_GC_TORTURE)
52635 	/* Simulate alloc failure on every alloc, except when mark-and-sweep
52636 	 * is running.
52637 	 */
52638 	if (heap->ms_prevent_count == 0) {
52639 		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first alloc attempt fails"));
52640 		res = NULL;
52641 		DUK_UNREF(res);
52642 		goto slowpath;
52643 	}
52644 #endif
52645 
52646 	/* Zero-size allocation should happen very rarely (if at all), so
52647 	 * don't check zero size on NULL; handle it in the slow path
52648 	 * instead.  This reduces size of inlined code.
52649 	 */
52650 	res = heap->alloc_func(heap->heap_udata, size);
52651 	if (DUK_LIKELY(res != NULL)) {
52652 		return res;
52653 	}
52654 
52655  slowpath:
52656 
52657 	if (size == 0) {
52658 		DUK_D(DUK_DPRINT("first alloc attempt returned NULL for zero size alloc, use slow path to deal with it"));
52659 	} else {
52660 		DUK_D(DUK_DPRINT("first alloc attempt failed, attempt to gc and retry"));
52661 	}
52662 	return duk__heap_mem_alloc_slowpath(heap, size);
52663 }
52664 
52665 DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size) {
52666 	void *res;
52667 
52668 	DUK_ASSERT(heap != NULL);
52669 	DUK_ASSERT(heap->alloc_func != NULL);
52670 	DUK_ASSERT_DISABLE(size >= 0);
52671 
52672 	res = DUK_ALLOC(heap, size);
52673 	if (DUK_LIKELY(res != NULL)) {
52674 		duk_memzero(res, size);
52675 	}
52676 	return res;
52677 }
52678 
52679 DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_alloc_checked(duk_hthread *thr, duk_size_t size) {
52680 	void *res;
52681 
52682 	DUK_ASSERT(thr != NULL);
52683 	DUK_ASSERT(thr->heap != NULL);
52684 	DUK_ASSERT(thr->heap->alloc_func != NULL);
52685 
52686 	res = duk_heap_mem_alloc(thr->heap, size);
52687 	if (DUK_LIKELY(res != NULL)) {
52688 		return res;
52689 	} else if (size == 0) {
52690 		DUK_ASSERT(res == NULL);
52691 		return res;
52692 	}
52693 	DUK_ERROR_ALLOC_FAILED(thr);
52694 	DUK_WO_NORETURN(return NULL;);
52695 }
52696 
52697 DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_alloc_checked_zeroed(duk_hthread *thr, duk_size_t size) {
52698 	void *res;
52699 
52700 	DUK_ASSERT(thr != NULL);
52701 	DUK_ASSERT(thr->heap != NULL);
52702 	DUK_ASSERT(thr->heap->alloc_func != NULL);
52703 
52704 	res = duk_heap_mem_alloc(thr->heap, size);
52705 	if (DUK_LIKELY(res != NULL)) {
52706 		duk_memzero(res, size);
52707 		return res;
52708 	} else if (size == 0) {
52709 		DUK_ASSERT(res == NULL);
52710 		return res;
52711 	}
52712 	DUK_ERROR_ALLOC_FAILED(thr);
52713 	DUK_WO_NORETURN(return NULL;);
52714 }
52715 
52716 /*
52717  *  Reallocate memory with garbage collection.
52718  */
52719 
52720 /* Slow path: voluntary GC triggered, first realloc attempt failed, or zero size. */
52721 DUK_LOCAL DUK_NOINLINE_PERF DUK_COLD void *duk__heap_mem_realloc_slowpath(duk_heap *heap, void *ptr, duk_size_t newsize) {
52722 	void *res;
52723 	duk_small_int_t i;
52724 
52725 	DUK_ASSERT(heap != NULL);
52726 	DUK_ASSERT(heap->realloc_func != NULL);
52727 	/* ptr may be NULL */
52728 	DUK_ASSERT_DISABLE(newsize >= 0);
52729 
52730 	/* Newsize was 0 and realloc() returned NULL, this has the semantics
52731 	 * of free(oldptr), i.e. memory was successfully freed.
52732 	 */
52733 	if (newsize == 0) {
52734 		DUK_D(DUK_DPRINT("zero size realloc in slow path, return NULL"));
52735 		return NULL;
52736 	}
52737 
52738 	DUK_D(DUK_DPRINT("first realloc attempt failed, attempt to gc and retry"));
52739 
52740 #if 0
52741 	/*
52742 	 *  Avoid a GC if GC is already running.  See duk_heap_mem_alloc().
52743 	 */
52744 
52745 	if (heap->ms_prevent_count != 0) {
52746 		DUK_D(DUK_DPRINT("duk_heap_mem_realloc() failed, gc in progress (gc skipped), alloc size %ld", (long) newsize));
52747 		return NULL;
52748 	}
52749 #endif
52750 
52751 	/*
52752 	 *  Retry with several GC attempts.  Initial attempts are made without
52753 	 *  emergency mode; later attempts use emergency mode which minimizes
52754 	 *  memory allocations forcibly.
52755 	 */
52756 
52757 	for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
52758 		duk_small_uint_t flags;
52759 
52760 		flags = 0;
52761 		if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
52762 			flags |= DUK_MS_FLAG_EMERGENCY;
52763 		}
52764 
52765 		duk_heap_mark_and_sweep(heap, flags);
52766 
52767 		DUK_ASSERT(newsize > 0);
52768 		res = heap->realloc_func(heap->heap_udata, ptr, newsize);
52769 		if (res || newsize == 0) {
52770 			DUK_D(DUK_DPRINT("duk_heap_mem_realloc() succeeded after gc (pass %ld), alloc size %ld",
52771 			                 (long) (i + 1), (long) newsize));
52772 			return res;
52773 		}
52774 	}
52775 
52776 	DUK_D(DUK_DPRINT("duk_heap_mem_realloc() failed even after gc, alloc size %ld", (long) newsize));
52777 	return NULL;
52778 }
52779 
52780 DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize) {
52781 	void *res;
52782 
52783 	DUK_ASSERT(heap != NULL);
52784 	DUK_ASSERT(heap->realloc_func != NULL);
52785 	/* ptr may be NULL */
52786 	DUK_ASSERT_DISABLE(newsize >= 0);
52787 
52788 #if defined(DUK_USE_VOLUNTARY_GC)
52789 	/* Voluntary periodic GC (if enabled). */
52790 	if (DUK_UNLIKELY(--(heap)->ms_trigger_counter < 0)) {
52791 		goto slowpath;
52792 	}
52793 #endif
52794 
52795 #if defined(DUK_USE_GC_TORTURE)
52796 	/* Simulate alloc failure on every realloc, except when mark-and-sweep
52797 	 * is running.
52798 	 */
52799 	if (heap->ms_prevent_count == 0) {
52800 		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first realloc attempt fails"));
52801 		res = NULL;
52802 		DUK_UNREF(res);
52803 		goto slowpath;
52804 	}
52805 #endif
52806 
52807 	res = heap->realloc_func(heap->heap_udata, ptr, newsize);
52808 	if (DUK_LIKELY(res != NULL)) {
52809 		return res;
52810 	}
52811 
52812  slowpath:
52813 
52814 	if (newsize == 0) {
52815 		DUK_D(DUK_DPRINT("first realloc attempt returned NULL for zero size realloc, use slow path to deal with it"));
52816 	} else {
52817 		DUK_D(DUK_DPRINT("first realloc attempt failed, attempt to gc and retry"));
52818 	}
52819 	return duk__heap_mem_realloc_slowpath(heap, ptr, newsize);
52820 }
52821 
52822 /*
52823  *  Reallocate memory with garbage collection, using a callback to provide
52824  *  the current allocated pointer.  This variant is used when a mark-and-sweep
52825  *  (e.g. finalizers) might change the original pointer.
52826  */
52827 
52828 /* Slow path: voluntary GC triggered, first realloc attempt failed, or zero size. */
52829 DUK_LOCAL DUK_NOINLINE_PERF DUK_COLD void *duk__heap_mem_realloc_indirect_slowpath(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize) {
52830 	void *res;
52831 	duk_small_int_t i;
52832 
52833 	DUK_ASSERT(heap != NULL);
52834 	DUK_ASSERT(heap->realloc_func != NULL);
52835 	DUK_ASSERT_DISABLE(newsize >= 0);
52836 
52837 	if (newsize == 0) {
52838 		DUK_D(DUK_DPRINT("zero size indirect realloc in slow path, return NULL"));
52839 		return NULL;
52840 	}
52841 
52842 	DUK_D(DUK_DPRINT("first indirect realloc attempt failed, attempt to gc and retry"));
52843 
52844 #if 0
52845 	/*
52846 	 *  Avoid a GC if GC is already running.  See duk_heap_mem_alloc().
52847 	 */
52848 
52849 	if (heap->ms_prevent_count != 0) {
52850 		DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() failed, gc in progress (gc skipped), alloc size %ld", (long) newsize));
52851 		return NULL;
52852 	}
52853 #endif
52854 
52855 	/*
52856 	 *  Retry with several GC attempts.  Initial attempts are made without
52857 	 *  emergency mode; later attempts use emergency mode which minimizes
52858 	 *  memory allocations forcibly.
52859 	 */
52860 
52861 	for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
52862 		duk_small_uint_t flags;
52863 
52864 #if defined(DUK_USE_DEBUG)
52865 		void *ptr_pre;
52866 		void *ptr_post;
52867 #endif
52868 
52869 #if defined(DUK_USE_DEBUG)
52870 		ptr_pre = cb(heap, ud);
52871 #endif
52872 		flags = 0;
52873 		if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
52874 			flags |= DUK_MS_FLAG_EMERGENCY;
52875 		}
52876 
52877 		duk_heap_mark_and_sweep(heap, flags);
52878 #if defined(DUK_USE_DEBUG)
52879 		ptr_post = cb(heap, ud);
52880 		if (ptr_pre != ptr_post) {
52881 			DUK_DD(DUK_DDPRINT("realloc base pointer changed by mark-and-sweep: %p -> %p",
52882 			                   (void *) ptr_pre, (void *) ptr_post));
52883 		}
52884 #endif
52885 
52886 		/* Note: key issue here is to re-lookup the base pointer on every attempt.
52887 		 * The pointer being reallocated may change after every mark-and-sweep.
52888 		 */
52889 
52890 		DUK_ASSERT(newsize > 0);
52891 		res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
52892 		if (res || newsize == 0) {
52893 			DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() succeeded after gc (pass %ld), alloc size %ld",
52894 			                 (long) (i + 1), (long) newsize));
52895 			return res;
52896 		}
52897 	}
52898 
52899 	DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() failed even after gc, alloc size %ld", (long) newsize));
52900 	return NULL;
52901 }
52902 
52903 DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize) {
52904 	void *res;
52905 
52906 	DUK_ASSERT(heap != NULL);
52907 	DUK_ASSERT(heap->realloc_func != NULL);
52908 	DUK_ASSERT_DISABLE(newsize >= 0);
52909 
52910 #if defined(DUK_USE_VOLUNTARY_GC)
52911 	/* Voluntary periodic GC (if enabled). */
52912 	if (DUK_UNLIKELY(--(heap)->ms_trigger_counter < 0)) {
52913 		goto slowpath;
52914 	}
52915 #endif
52916 
52917 #if defined(DUK_USE_GC_TORTURE)
52918 	/* Simulate alloc failure on every realloc, except when mark-and-sweep
52919 	 * is running.
52920 	 */
52921 	if (heap->ms_prevent_count == 0) {
52922 		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first indirect realloc attempt fails"));
52923 		res = NULL;
52924 		DUK_UNREF(res);
52925 		goto slowpath;
52926 	}
52927 #endif
52928 
52929 	res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
52930 	if (DUK_LIKELY(res != NULL)) {
52931 		return res;
52932 	}
52933 
52934  slowpath:
52935 
52936 	if (newsize == 0) {
52937 		DUK_D(DUK_DPRINT("first indirect realloc attempt returned NULL for zero size realloc, use slow path to deal with it"));
52938 	} else {
52939 		DUK_D(DUK_DPRINT("first indirect realloc attempt failed, attempt to gc and retry"));
52940 	}
52941 	return duk__heap_mem_realloc_indirect_slowpath(heap, cb, ud, newsize);
52942 }
52943 
52944 /*
52945  *  Free memory
52946  */
52947 
52948 DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void duk_heap_mem_free(duk_heap *heap, void *ptr) {
52949 	DUK_ASSERT(heap != NULL);
52950 	DUK_ASSERT(heap->free_func != NULL);
52951 	/* ptr may be NULL */
52952 
52953 	/* Must behave like a no-op with NULL and any pointer returned from
52954 	 * malloc/realloc with zero size.
52955 	 */
52956 	heap->free_func(heap->heap_udata, ptr);
52957 
52958 	/* Never perform a GC (even voluntary) in a memory free, otherwise
52959 	 * all call sites doing frees would need to deal with the side effects.
52960 	 * No need to update voluntary GC counter either.
52961 	 */
52962 }
52963 /*
52964  *  Support functions for duk_heap.
52965  */
52966 
52967 /* #include duk_internal.h -> already included */
52968 
52969 DUK_INTERNAL void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphdr *hdr) {
52970 	duk_heaphdr *root;
52971 
52972 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) != DUK_HTYPE_STRING);
52973 
52974 	root = heap->heap_allocated;
52975 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
52976 	if (root != NULL) {
52977 		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, root) == NULL);
52978 		DUK_HEAPHDR_SET_PREV(heap, root, hdr);
52979 	}
52980 	DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
52981 #endif
52982 	DUK_HEAPHDR_SET_NEXT(heap, hdr, root);
52983 	DUK_HEAPHDR_ASSERT_LINKS(heap, hdr);
52984 	DUK_HEAPHDR_ASSERT_LINKS(heap, root);
52985 	heap->heap_allocated = hdr;
52986 }
52987 
52988 #if defined(DUK_USE_REFERENCE_COUNTING)
52989 DUK_INTERNAL void duk_heap_remove_from_heap_allocated(duk_heap *heap, duk_heaphdr *hdr) {
52990 	duk_heaphdr *prev;
52991 	duk_heaphdr *next;
52992 
52993 	/* Strings are in string table. */
52994 	DUK_ASSERT(hdr != NULL);
52995 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) != DUK_HTYPE_STRING);
52996 
52997 	/* Target 'hdr' must be in heap_allocated (not e.g. finalize_list).
52998 	 * If not, heap lists will become corrupted so assert early for it.
52999 	 */
53000 #if defined(DUK_USE_ASSERTIONS)
53001 	{
53002 		duk_heaphdr *tmp;
53003 		for (tmp = heap->heap_allocated; tmp != NULL; tmp = DUK_HEAPHDR_GET_NEXT(heap, tmp)) {
53004 			if (tmp == hdr) {
53005 				break;
53006 			}
53007 		}
53008 		DUK_ASSERT(tmp == hdr);
53009 	}
53010 #endif
53011 
53012 	/* Read/write only once to minimize pointer compression calls. */
53013 	prev = DUK_HEAPHDR_GET_PREV(heap, hdr);
53014 	next = DUK_HEAPHDR_GET_NEXT(heap, hdr);
53015 
53016 	if (prev != NULL) {
53017 		DUK_ASSERT(heap->heap_allocated != hdr);
53018 		DUK_HEAPHDR_SET_NEXT(heap, prev, next);
53019 	} else {
53020 		DUK_ASSERT(heap->heap_allocated == hdr);
53021 		heap->heap_allocated = next;
53022 	}
53023 	if (next != NULL) {
53024 		DUK_HEAPHDR_SET_PREV(heap, next, prev);
53025 	} else {
53026 		;
53027 	}
53028 }
53029 #endif  /* DUK_USE_REFERENCE_COUNTING */
53030 
53031 #if defined(DUK_USE_FINALIZER_SUPPORT)
53032 DUK_INTERNAL void duk_heap_insert_into_finalize_list(duk_heap *heap, duk_heaphdr *hdr) {
53033 	duk_heaphdr *root;
53034 
53035 	root = heap->finalize_list;
53036 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
53037 	DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
53038 	if (root != NULL) {
53039 		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, root) == NULL);
53040 		DUK_HEAPHDR_SET_PREV(heap, root, hdr);
53041 	}
53042 #endif
53043 	DUK_HEAPHDR_SET_NEXT(heap, hdr, root);
53044 	DUK_HEAPHDR_ASSERT_LINKS(heap, hdr);
53045 	DUK_HEAPHDR_ASSERT_LINKS(heap, root);
53046 	heap->finalize_list = hdr;
53047 }
53048 #endif  /* DUK_USE_FINALIZER_SUPPORT */
53049 
53050 #if defined(DUK_USE_FINALIZER_SUPPORT)
53051 DUK_INTERNAL void duk_heap_remove_from_finalize_list(duk_heap *heap, duk_heaphdr *hdr) {
53052 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
53053 	duk_heaphdr *next;
53054 	duk_heaphdr *prev;
53055 
53056 	next = DUK_HEAPHDR_GET_NEXT(heap, hdr);
53057 	prev = DUK_HEAPHDR_GET_PREV(heap, hdr);
53058 	if (next != NULL) {
53059 		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, next) == hdr);
53060 		DUK_HEAPHDR_SET_PREV(heap, next, prev);
53061 	}
53062 	if (prev == NULL) {
53063 		DUK_ASSERT(hdr == heap->finalize_list);
53064 		heap->finalize_list = next;
53065 	} else {
53066 		DUK_ASSERT(hdr != heap->finalize_list);
53067 		DUK_HEAPHDR_SET_NEXT(heap, prev, next);
53068 	}
53069 #else
53070 	duk_heaphdr *next;
53071 	duk_heaphdr *curr;
53072 
53073 	/* Random removal is expensive: we need to locate the previous element
53074 	 * because we don't have a 'prev' pointer.
53075 	 */
53076 	curr = heap->finalize_list;
53077 	if (curr == hdr) {
53078 		heap->finalize_list = DUK_HEAPHDR_GET_NEXT(heap, curr);
53079 	} else {
53080 		DUK_ASSERT(hdr != heap->finalize_list);
53081 		for (;;) {
53082 			DUK_ASSERT(curr != NULL);  /* Caller responsibility. */
53083 
53084 			next = DUK_HEAPHDR_GET_NEXT(heap, curr);
53085 			if (next == hdr) {
53086 				next = DUK_HEAPHDR_GET_NEXT(heap, hdr);
53087 				DUK_HEAPHDR_SET_NEXT(heap, curr, next);
53088 				break;
53089 			}
53090 		}
53091 	}
53092 #endif
53093 }
53094 #endif  /* DUK_USE_FINALIZER_SUPPORT */
53095 
53096 #if defined(DUK_USE_ASSERTIONS)
53097 DUK_INTERNAL duk_bool_t duk_heap_in_heap_allocated(duk_heap *heap, duk_heaphdr *ptr) {
53098 	duk_heaphdr *curr;
53099 	DUK_ASSERT(heap != NULL);
53100 
53101 	for (curr = heap->heap_allocated; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
53102 		if (curr == ptr) {
53103 			return 1;
53104 		}
53105 	}
53106 	return 0;
53107 }
53108 #endif  /* DUK_USE_ASSERTIONS */
53109 
53110 #if defined(DUK_USE_INTERRUPT_COUNTER)
53111 DUK_INTERNAL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr) {
53112 	duk_hthread *curr_thr;
53113 
53114 	DUK_ASSERT(heap != NULL);
53115 
53116 	if (new_thr != NULL) {
53117 		curr_thr = heap->curr_thread;
53118 		if (curr_thr == NULL) {
53119 			/* For initial entry use default value; zero forces an
53120 			 * interrupt before executing the first insturction.
53121 			 */
53122 			DUK_DD(DUK_DDPRINT("switch thread, initial entry, init default interrupt counter"));
53123 			new_thr->interrupt_counter = 0;
53124 			new_thr->interrupt_init = 0;
53125 		} else {
53126 			/* Copy interrupt counter/init value state to new thread (if any).
53127 			 * It's OK for new_thr to be the same as curr_thr.
53128 			 */
53129 #if defined(DUK_USE_DEBUG)
53130 			if (new_thr != curr_thr) {
53131 				DUK_DD(DUK_DDPRINT("switch thread, not initial entry, copy interrupt counter"));
53132 			}
53133 #endif
53134 			new_thr->interrupt_counter = curr_thr->interrupt_counter;
53135 			new_thr->interrupt_init = curr_thr->interrupt_init;
53136 		}
53137 	} else {
53138 		DUK_DD(DUK_DDPRINT("switch thread, new thread is NULL, no interrupt counter changes"));
53139 	}
53140 
53141 	heap->curr_thread = new_thr;  /* may be NULL */
53142 }
53143 #endif  /* DUK_USE_INTERRUPT_COUNTER */
53144 
53145 #if defined(DUK_USE_ASSERTIONS)
53146 DUK_INTERNAL void duk_heap_assert_valid(duk_heap *heap) {
53147 	DUK_ASSERT(heap != NULL);
53148 }
53149 #endif
53150 /*
53151  *  Reference counting implementation.
53152  *
53153  *  INCREF/DECREF, finalization and freeing of objects whose refcount reaches
53154  *  zero (refzero).  These operations are very performance sensitive, so
53155  *  various small tricks are used in an attempt to maximize speed.
53156  */
53157 
53158 /* #include duk_internal.h -> already included */
53159 
53160 #if defined(DUK_USE_REFERENCE_COUNTING)
53161 
53162 #if !defined(DUK_USE_DOUBLE_LINKED_HEAP)
53163 #error internal error, reference counting requires a double linked heap
53164 #endif
53165 
53166 /*
53167  *  Heap object refcount finalization.
53168  *
53169  *  When an object is about to be freed, all other objects it refers to must
53170  *  be decref'd.  Refcount finalization does NOT free the object or its inner
53171  *  allocations (mark-and-sweep shares these helpers), it just manipulates
53172  *  the refcounts.
53173  *
53174  *  Note that any of the DECREFs may cause a refcount to drop to zero.  If so,
53175  *  the object won't be refzero processed inline, but will just be queued to
53176  *  refzero_list and processed by an earlier caller working on refzero_list,
53177  *  eliminating C recursion from even long refzero cascades.  If refzero
53178  *  finalization is triggered by mark-and-sweep, refzero conditions are ignored
53179  *  (objects are not even queued to refzero_list) because mark-and-sweep deals
53180  *  with them; refcounts are still updated so that they remain in sync with
53181  *  actual references.
53182  */
53183 
53184 DUK_LOCAL void duk__decref_tvals_norz(duk_hthread *thr, duk_tval *tv, duk_idx_t count) {
53185 	DUK_ASSERT(count == 0 || tv != NULL);
53186 
53187 	while (count-- > 0) {
53188 		DUK_TVAL_DECREF_NORZ(thr, tv);
53189 		tv++;
53190 	}
53191 }
53192 
53193 DUK_INTERNAL void duk_hobject_refcount_finalize_norz(duk_heap *heap, duk_hobject *h) {
53194 	duk_hthread *thr;
53195 	duk_uint_fast32_t i;
53196 	duk_uint_fast32_t n;
53197 	duk_propvalue *p_val;
53198 	duk_tval *p_tv;
53199 	duk_hstring **p_key;
53200 	duk_uint8_t *p_flag;
53201 	duk_hobject *h_proto;
53202 
53203 	DUK_ASSERT(heap != NULL);
53204 	DUK_ASSERT(heap->heap_thread != NULL);
53205 	DUK_ASSERT(h);
53206 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h) == DUK_HTYPE_OBJECT);
53207 
53208 	thr = heap->heap_thread;
53209 	DUK_ASSERT(thr != NULL);
53210 
53211 	p_key = DUK_HOBJECT_E_GET_KEY_BASE(heap, h);
53212 	p_val = DUK_HOBJECT_E_GET_VALUE_BASE(heap, h);
53213 	p_flag = DUK_HOBJECT_E_GET_FLAGS_BASE(heap, h);
53214 	n = DUK_HOBJECT_GET_ENEXT(h);
53215 	while (n-- > 0) {
53216 		duk_hstring *key;
53217 
53218 		key = p_key[n];
53219 		if (DUK_UNLIKELY(key == NULL)) {
53220 			continue;
53221 		}
53222 		DUK_HSTRING_DECREF_NORZ(thr, key);
53223 		if (DUK_UNLIKELY(p_flag[n] & DUK_PROPDESC_FLAG_ACCESSOR)) {
53224 			duk_hobject *h_getset;
53225 			h_getset = p_val[n].a.get;
53226 			DUK_ASSERT(h_getset == NULL || DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_getset));
53227 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h_getset);
53228 			h_getset = p_val[n].a.set;
53229 			DUK_ASSERT(h_getset == NULL || DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_getset));
53230 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h_getset);
53231 		} else {
53232 			duk_tval *tv_val;
53233 			tv_val = &p_val[n].v;
53234 			DUK_TVAL_DECREF_NORZ(thr, tv_val);
53235 		}
53236 	}
53237 
53238 	p_tv = DUK_HOBJECT_A_GET_BASE(heap, h);
53239 	n = DUK_HOBJECT_GET_ASIZE(h);
53240 	while (n-- > 0) {
53241 		duk_tval *tv_val;
53242 		tv_val = p_tv + n;
53243 		DUK_TVAL_DECREF_NORZ(thr, tv_val);
53244 	}
53245 
53246 	/* Hash part is a 'weak reference' and doesn't contribute to refcounts. */
53247 
53248 	h_proto = (duk_hobject *) DUK_HOBJECT_GET_PROTOTYPE(heap, h);
53249 	DUK_ASSERT(h_proto == NULL || DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_proto));
53250 	DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h_proto);
53251 
53252 	/* XXX: Object subclass tests are quite awkward at present, ideally
53253 	 * we should be able to switch-case here with a dense index (subtype
53254 	 * number or something).  For now, fast path plain objects and arrays
53255 	 * and bit test the rest individually.
53256 	 */
53257 
53258 	if (DUK_HOBJECT_HAS_FASTREFS(h)) {
53259 		/* Plain object or array, nothing more to do.  While a
53260 		 * duk_harray has additional fields, none of them need
53261 		 * DECREF updates.
53262 		 */
53263 		DUK_ASSERT(DUK_HOBJECT_ALLOWS_FASTREFS(h));
53264 		return;
53265 	}
53266 	DUK_ASSERT(DUK_HOBJECT_PROHIBITS_FASTREFS(h));
53267 
53268 	/* Slow path: special object, start bit checks from most likely. */
53269 
53270 	/* XXX: reorg, more common first */
53271 	if (DUK_HOBJECT_IS_COMPFUNC(h)) {
53272 		duk_hcompfunc *f = (duk_hcompfunc *) h;
53273 		duk_tval *tv, *tv_end;
53274 		duk_hobject **funcs, **funcs_end;
53275 
53276 		DUK_HCOMPFUNC_ASSERT_VALID(f);
53277 
53278 		if (DUK_LIKELY(DUK_HCOMPFUNC_GET_DATA(heap, f) != NULL)) {
53279 			tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, f);
53280 			tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(heap, f);
53281 			while (tv < tv_end) {
53282 				DUK_TVAL_DECREF_NORZ(thr, tv);
53283 				tv++;
53284 			}
53285 
53286 			funcs = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, f);
53287 			funcs_end = DUK_HCOMPFUNC_GET_FUNCS_END(heap, f);
53288 			while (funcs < funcs_end) {
53289 				duk_hobject *h_func;
53290 				h_func = *funcs;
53291 				DUK_ASSERT(h_func != NULL);
53292 				DUK_ASSERT(DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_func));
53293 				DUK_HCOMPFUNC_DECREF_NORZ(thr, (duk_hcompfunc *) h_func);
53294 				funcs++;
53295 			}
53296 		} else {
53297 			/* May happen in some out-of-memory corner cases. */
53298 			DUK_D(DUK_DPRINT("duk_hcompfunc 'data' is NULL, skipping decref"));
53299 		}
53300 
53301 		DUK_HEAPHDR_DECREF_ALLOWNULL(thr, (duk_heaphdr *) DUK_HCOMPFUNC_GET_LEXENV(heap, f));
53302 		DUK_HEAPHDR_DECREF_ALLOWNULL(thr, (duk_heaphdr *) DUK_HCOMPFUNC_GET_VARENV(heap, f));
53303 		DUK_HEAPHDR_DECREF_ALLOWNULL(thr, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(heap, f));
53304 	} else if (DUK_HOBJECT_IS_DECENV(h)) {
53305 		duk_hdecenv *e = (duk_hdecenv *) h;
53306 		DUK_HDECENV_ASSERT_VALID(e);
53307 		DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr, e->thread);
53308 		DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, e->varmap);
53309 	} else if (DUK_HOBJECT_IS_OBJENV(h)) {
53310 		duk_hobjenv *e = (duk_hobjenv *) h;
53311 		DUK_HOBJENV_ASSERT_VALID(e);
53312 		DUK_ASSERT(e->target != NULL);  /* Required for object environments. */
53313 		DUK_HOBJECT_DECREF_NORZ(thr, e->target);
53314 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
53315 	} else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
53316 		duk_hbufobj *b = (duk_hbufobj *) h;
53317 		DUK_HBUFOBJ_ASSERT_VALID(b);
53318 		DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr, (duk_hbuffer *) b->buf);
53319 		DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) b->buf_prop);
53320 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
53321 	} else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {
53322 		duk_hboundfunc *f = (duk_hboundfunc *) (void *) h;
53323 		DUK_HBOUNDFUNC_ASSERT_VALID(f);
53324 		DUK_TVAL_DECREF_NORZ(thr, &f->target);
53325 		DUK_TVAL_DECREF_NORZ(thr, &f->this_binding);
53326 		duk__decref_tvals_norz(thr, f->args, f->nargs);
53327 #if defined(DUK_USE_ES6_PROXY)
53328 	} else if (DUK_HOBJECT_IS_PROXY(h)) {
53329 		duk_hproxy *p = (duk_hproxy *) h;
53330 		DUK_HPROXY_ASSERT_VALID(p);
53331 		DUK_HOBJECT_DECREF_NORZ(thr, p->target);
53332 		DUK_HOBJECT_DECREF_NORZ(thr, p->handler);
53333 #endif  /* DUK_USE_ES6_PROXY */
53334 	} else if (DUK_HOBJECT_IS_THREAD(h)) {
53335 		duk_hthread *t = (duk_hthread *) h;
53336 		duk_activation *act;
53337 		duk_tval *tv;
53338 
53339 		DUK_HTHREAD_ASSERT_VALID(t);
53340 
53341 		tv = t->valstack;
53342 		while (tv < t->valstack_top) {
53343 			DUK_TVAL_DECREF_NORZ(thr, tv);
53344 			tv++;
53345 		}
53346 
53347 		for (act = t->callstack_curr; act != NULL; act = act->parent) {
53348 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) DUK_ACT_GET_FUNC(act));
53349 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) act->var_env);
53350 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) act->lex_env);
53351 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
53352 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) act->prev_caller);
53353 #endif
53354 #if 0  /* nothing now */
53355 			for (cat = act->cat; cat != NULL; cat = cat->parent) {
53356 			}
53357 #endif
53358 		}
53359 
53360 
53361 		for (i = 0; i < DUK_NUM_BUILTINS; i++) {
53362 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) t->builtins[i]);
53363 		}
53364 
53365 		DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr, (duk_hthread *) t->resumer);
53366 	} else {
53367 		/* We may come here if the object should have a FASTREFS flag
53368 		 * but it's missing for some reason.  Assert for never getting
53369 		 * here; however, other than performance, this is harmless.
53370 		 */
53371 		DUK_D(DUK_DPRINT("missing FASTREFS flag for: %!iO", h));
53372 		DUK_ASSERT(0);
53373 	}
53374 }
53375 
53376 DUK_INTERNAL void duk_heaphdr_refcount_finalize_norz(duk_heap *heap, duk_heaphdr *hdr) {
53377 	DUK_ASSERT(heap != NULL);
53378 	DUK_ASSERT(heap->heap_thread != NULL);
53379 	DUK_ASSERT(hdr != NULL);
53380 
53381 	if (DUK_HEAPHDR_IS_OBJECT(hdr)) {
53382 		duk_hobject_refcount_finalize_norz(heap, (duk_hobject *) hdr);
53383 	}
53384 	/* DUK_HTYPE_BUFFER: nothing to finalize */
53385 	/* DUK_HTYPE_STRING: nothing to finalize */
53386 }
53387 
53388 /*
53389  *  Refzero processing for duk_hobject: queue a refzero'ed object to either
53390  *  finalize_list or refzero_list and process the relevent list(s) if
53391  *  necessary.
53392  *
53393  *  Refzero_list is single linked, with only 'prev' pointers set and valid.
53394  *  All 'next' pointers are intentionally left as garbage.  This doesn't
53395  *  matter because refzero_list is processed to completion before any other
53396  *  code (like mark-and-sweep) might walk the list.
53397  *
53398  *  In more detail:
53399  *
53400  *  - On first insert refzero_list is NULL and the new object becomes the
53401  *    first and only element on the list; duk__refcount_free_pending() is
53402  *    called and it starts processing the list from the initial element,
53403  *    i.e. the list tail.
53404  *
53405  *  - As each object is refcount finalized, new objects may be queued to
53406  *    refzero_list head.  Their 'next' pointers are left as garbage, but
53407  *    'prev' points are set correctly, with the element at refzero_list
53408  *    having a NULL 'prev' pointer.  The fact that refzero_list is non-NULL
53409  *    is used to reject (1) recursive duk__refcount_free_pending() and
53410  *    (2) finalize_list processing calls.
53411  *
53412  *  - When we're done with the current object, read its 'prev' pointer and
53413  *    free the object.  If 'prev' is NULL, we've reached head of list and are
53414  *    done: set refzero_list to NULL and process pending finalizers.  Otherwise
53415  *    continue processing the list.
53416  *
53417  *  A refzero cascade is free of side effects because it only involves
53418  *  queueing more objects and freeing memory; finalizer execution is blocked
53419  *  in the code path queueing objects to finalize_list.  As a result the
53420  *  initial refzero call (which triggers duk__refcount_free_pending()) must
53421  *  check finalize_list so that finalizers are executed snappily.
53422  *
53423  *  If finalize_list processing starts first, refzero may occur while we're
53424  *  processing finalizers.  That's fine: that particular refzero cascade is
53425  *  handled to completion without side effects.  Once the cascade is complete,
53426  *  we'll run pending finalizers but notice that we're already doing that and
53427  *  return.
53428  *
53429  *  This could be expanded to allow incremental freeing: just bail out
53430  *  early and resume at a future alloc/decref/refzero.  However, if that
53431  *  were done, the list structure would need to be kept consistent at all
53432  *  times, mark-and-sweep would need to handle refzero_list, etc.
53433  */
53434 
53435 DUK_LOCAL void duk__refcount_free_pending(duk_heap *heap) {
53436 	duk_heaphdr *curr;
53437 #if defined(DUK_USE_DEBUG)
53438 	duk_int_t count = 0;
53439 #endif
53440 
53441 	DUK_ASSERT(heap != NULL);
53442 
53443 	curr = heap->refzero_list;
53444 	DUK_ASSERT(curr != NULL);
53445 	DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, curr) == NULL);  /* We're called on initial insert only. */
53446 	/* curr->next is GARBAGE. */
53447 
53448 	do {
53449 		duk_heaphdr *prev;
53450 
53451 		DUK_DDD(DUK_DDDPRINT("refzero processing %p: %!O", (void *) curr, (duk_heaphdr *) curr));
53452 
53453 #if defined(DUK_USE_DEBUG)
53454 		count++;
53455 #endif
53456 
53457 		DUK_ASSERT(curr != NULL);
53458 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);  /* currently, always the case */
53459 		/* FINALIZED may be set; don't care about flags here. */
53460 
53461 		/* Refcount finalize 'curr'.  Refzero_list must be non-NULL
53462 		 * here to prevent recursive entry to duk__refcount_free_pending().
53463 		 */
53464 		DUK_ASSERT(heap->refzero_list != NULL);
53465 		duk_hobject_refcount_finalize_norz(heap, (duk_hobject *) curr);
53466 
53467 		prev = DUK_HEAPHDR_GET_PREV(heap, curr);
53468 		DUK_ASSERT((prev == NULL && heap->refzero_list == curr) || \
53469 		           (prev != NULL && heap->refzero_list != curr));
53470 		/* prev->next is intentionally not updated and is garbage. */
53471 
53472 		duk_free_hobject(heap, (duk_hobject *) curr);  /* Invalidates 'curr'. */
53473 
53474 		curr = prev;
53475 	} while (curr != NULL);
53476 
53477 	heap->refzero_list = NULL;
53478 
53479 	DUK_DD(DUK_DDPRINT("refzero processed %ld objects", (long) count));
53480 }
53481 
53482 DUK_LOCAL DUK_INLINE void duk__refcount_refzero_hobject(duk_heap *heap, duk_hobject *obj, duk_bool_t skip_free_pending) {
53483 	duk_heaphdr *hdr;
53484 	duk_heaphdr *root;
53485 
53486 	DUK_ASSERT(heap != NULL);
53487 	DUK_ASSERT(heap->heap_thread != NULL);
53488 	DUK_ASSERT(obj != NULL);
53489 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) obj) == DUK_HTYPE_OBJECT);
53490 
53491 	hdr = (duk_heaphdr *) obj;
53492 
53493 	/* Refzero'd objects must be in heap_allocated.  They can't be in
53494 	 * finalize_list because all objects on finalize_list have an
53495 	 * artificial +1 refcount bump.
53496 	 */
53497 #if defined(DUK_USE_ASSERTIONS)
53498 	DUK_ASSERT(duk_heap_in_heap_allocated(heap, (duk_heaphdr *) obj));
53499 #endif
53500 
53501 	DUK_HEAP_REMOVE_FROM_HEAP_ALLOCATED(heap, hdr);
53502 
53503 #if defined(DUK_USE_FINALIZER_SUPPORT)
53504 	/* This finalizer check MUST BE side effect free.  It should also be
53505 	 * as fast as possible because it's applied to every object freed.
53506 	 */
53507 	if (DUK_UNLIKELY(DUK_HOBJECT_HAS_FINALIZER_FAST(heap, (duk_hobject *) hdr) != 0U)) {
53508 		/* Special case: FINALIZED may be set if mark-and-sweep queued
53509 		 * object for finalization, the finalizer was executed (and
53510 		 * FINALIZED set), mark-and-sweep hasn't yet processed the
53511 		 * object again, but its refcount drops to zero.  Free without
53512 		 * running the finalizer again.
53513 		 */
53514 		if (DUK_HEAPHDR_HAS_FINALIZED(hdr)) {
53515 			DUK_D(DUK_DPRINT("refzero'd object has finalizer and FINALIZED is set -> free"));
53516 		} else {
53517 			/* Set FINALIZABLE flag so that all objects on finalize_list
53518 			 * will have it set and are thus detectable based on the
53519 			 * flag alone.
53520 			 */
53521 			DUK_HEAPHDR_SET_FINALIZABLE(hdr);
53522 			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(hdr));
53523 
53524 #if defined(DUK_USE_REFERENCE_COUNTING)
53525 			/* Bump refcount on finalize_list insert so that a
53526 			 * refzero can never occur when an object is waiting
53527 			 * for its finalizer call.  Refzero might otherwise
53528 			 * now happen because we allow duk_push_heapptr() for
53529 			 * objects pending finalization.
53530 			 */
53531 			DUK_HEAPHDR_PREINC_REFCOUNT(hdr);
53532 #endif
53533 			DUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap, hdr);
53534 
53535 			/* Process finalizers unless skipping is explicitly
53536 			 * requested (NORZ) or refzero_list is being processed
53537 			 * (avoids side effects during a refzero cascade).
53538 			 * If refzero_list is processed, the initial refzero
53539 			 * call will run pending finalizers when refzero_list
53540 			 * is done.
53541 			 */
53542 			if (!skip_free_pending && heap->refzero_list == NULL) {
53543 				duk_heap_process_finalize_list(heap);
53544 			}
53545 			return;
53546 		}
53547 	}
53548 #endif  /* DUK_USE_FINALIZER_SUPPORT */
53549 
53550 	/* No need to finalize, free object via refzero_list. */
53551 
53552 	root = heap->refzero_list;
53553 
53554 	DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
53555 	/* 'next' is left as GARBAGE. */
53556 	heap->refzero_list = hdr;
53557 
53558 	if (root == NULL) {
53559 		/* Object is now queued.  Refzero_list was NULL so
53560 		 * no-one is currently processing it; do it here.
53561 		 * With refzero processing just doing a cascade of
53562 		 * free calls, we can process it directly even when
53563 		 * NORZ macros are used: there are no side effects.
53564 		 */
53565 		duk__refcount_free_pending(heap);
53566 		DUK_ASSERT(heap->refzero_list == NULL);
53567 
53568 		/* Process finalizers only after the entire cascade
53569 		 * is finished.  In most cases there's nothing to
53570 		 * finalize, so fast path check to avoid a call.
53571 		 */
53572 #if defined(DUK_USE_FINALIZER_SUPPORT)
53573 		if (!skip_free_pending && DUK_UNLIKELY(heap->finalize_list != NULL)) {
53574 			duk_heap_process_finalize_list(heap);
53575 		}
53576 #endif
53577 	} else {
53578 		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, root) == NULL);
53579 		DUK_HEAPHDR_SET_PREV(heap, root, hdr);
53580 
53581 		/* Object is now queued.  Because refzero_list was
53582 		 * non-NULL, it's already being processed by someone
53583 		 * in the C call stack, so we're done.
53584 		 */
53585 	}
53586 }
53587 
53588 #if defined(DUK_USE_FINALIZER_SUPPORT)
53589 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_refzero_check_fast(duk_hthread *thr) {
53590 	DUK_ASSERT(thr != NULL);
53591 	DUK_ASSERT(thr->heap != NULL);
53592 	DUK_ASSERT(thr->heap->refzero_list == NULL);  /* Processed to completion inline. */
53593 
53594 	if (DUK_UNLIKELY(thr->heap->finalize_list != NULL)) {
53595 		duk_heap_process_finalize_list(thr->heap);
53596 	}
53597 }
53598 
53599 DUK_INTERNAL void duk_refzero_check_slow(duk_hthread *thr) {
53600 	DUK_ASSERT(thr != NULL);
53601 	DUK_ASSERT(thr->heap != NULL);
53602 	DUK_ASSERT(thr->heap->refzero_list == NULL);  /* Processed to completion inline. */
53603 
53604 	if (DUK_UNLIKELY(thr->heap->finalize_list != NULL)) {
53605 		duk_heap_process_finalize_list(thr->heap);
53606 	}
53607 }
53608 #endif  /* DUK_USE_FINALIZER_SUPPORT */
53609 
53610 /*
53611  *  Refzero processing for duk_hstring.
53612  */
53613 
53614 DUK_LOCAL DUK_INLINE void duk__refcount_refzero_hstring(duk_heap *heap, duk_hstring *str) {
53615 	DUK_ASSERT(heap != NULL);
53616 	DUK_ASSERT(heap->heap_thread != NULL);
53617 	DUK_ASSERT(str != NULL);
53618 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) str) == DUK_HTYPE_STRING);
53619 
53620 	duk_heap_strcache_string_remove(heap, str);
53621 	duk_heap_strtable_unlink(heap, str);
53622 	duk_free_hstring(heap, str);
53623 }
53624 
53625 /*
53626  *  Refzero processing for duk_hbuffer.
53627  */
53628 
53629 DUK_LOCAL DUK_INLINE void duk__refcount_refzero_hbuffer(duk_heap *heap, duk_hbuffer *buf) {
53630 	DUK_ASSERT(heap != NULL);
53631 	DUK_ASSERT(heap->heap_thread != NULL);
53632 	DUK_ASSERT(buf != NULL);
53633 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) buf) == DUK_HTYPE_BUFFER);
53634 
53635 	DUK_HEAP_REMOVE_FROM_HEAP_ALLOCATED(heap, (duk_heaphdr *) buf);
53636 	duk_free_hbuffer(heap, buf);
53637 }
53638 
53639 /*
53640  *  Incref and decref functions.
53641  *
53642  *  Decref may trigger immediate refzero handling, which may free and finalize
53643  *  an arbitrary number of objects (a "DECREF cascade").
53644  *
53645  *  Refzero handling is skipped entirely if (1) mark-and-sweep is running or
53646  *  (2) execution is paused in the debugger.  The objects are left in the heap,
53647  *  and will be freed by mark-and-sweep or eventual heap destruction.
53648  *
53649  *  This is necessary during mark-and-sweep because refcounts are also updated
53650  *  during the sweep phase (otherwise objects referenced by a swept object
53651  *  would have incorrect refcounts) which then calls here.  This could be
53652  *  avoided by using separate decref macros in mark-and-sweep; however,
53653  *  mark-and-sweep also calls finalizers which would use the ordinary decref
53654  *  macros anyway.
53655  *
53656  *  We can't process refzeros (= free objects) when the debugger is running
53657  *  as the debugger might make an object unreachable but still continue
53658  *  inspecting it (or even cause it to be pushed back).  So we must rely on
53659  *  mark-and-sweep to collect them.
53660  *
53661  *  The DUK__RZ_SUPPRESS_CHECK() condition is also used in heap destruction
53662  *  when running finalizers for remaining objects: the flag prevents objects
53663  *  from being moved around in heap linked lists while that's being done.
53664  *
53665  *  The suppress condition is important to performance.
53666  */
53667 
53668 #define DUK__RZ_SUPPRESS_ASSERT1() do { \
53669 		DUK_ASSERT(thr != NULL); \
53670 		DUK_ASSERT(thr->heap != NULL); \
53671 		/* When mark-and-sweep runs, heap_thread must exist. */ \
53672 		DUK_ASSERT(thr->heap->ms_running == 0 || thr->heap->heap_thread != NULL); \
53673 		/* In normal operation finalizers are executed with ms_running == 0 \
53674 		 * so we should never see ms_running == 1 and thr != heap_thread. \
53675 		 * In heap destruction finalizers are executed with ms_running != 0 \
53676 		 * to e.g. prevent refzero; a special value ms_running == 2 is used \
53677 		 * in that case so it can be distinguished from the normal runtime \
53678 		 * case, and allows a stronger assertion here (GH-2030). \
53679 		 */ \
53680 		DUK_ASSERT(!(thr->heap->ms_running == 1 && thr != thr->heap->heap_thread)); \
53681 		/* We may be called when the heap is initializing and we process \
53682 		 * refzeros normally, but mark-and-sweep and finalizers are prevented \
53683 		 * if that's the case. \
53684 		 */ \
53685 		DUK_ASSERT(thr->heap->heap_initializing == 0 || thr->heap->ms_prevent_count > 0); \
53686 		DUK_ASSERT(thr->heap->heap_initializing == 0 || thr->heap->pf_prevent_count > 0); \
53687 	} while (0)
53688 
53689 #if defined(DUK_USE_DEBUGGER_SUPPORT)
53690 #define DUK__RZ_SUPPRESS_ASSERT2() do { \
53691 		/* When debugger is paused, ms_running is set. */ \
53692 		DUK_ASSERT(!DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) || thr->heap->ms_running != 0); \
53693 	} while (0)
53694 #define DUK__RZ_SUPPRESS_COND()  (heap->ms_running != 0)
53695 #else
53696 #define DUK__RZ_SUPPRESS_ASSERT2() do { } while (0)
53697 #define DUK__RZ_SUPPRESS_COND()  (heap->ms_running != 0)
53698 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
53699 
53700 #define DUK__RZ_SUPPRESS_CHECK() do { \
53701 		DUK__RZ_SUPPRESS_ASSERT1(); \
53702 		DUK__RZ_SUPPRESS_ASSERT2(); \
53703 		if (DUK_UNLIKELY(DUK__RZ_SUPPRESS_COND())) { \
53704 			DUK_DDD(DUK_DDDPRINT("refzero handling suppressed (not even queued) when mark-and-sweep running, object: %p", (void *) h)); \
53705 			return; \
53706 		} \
53707 	} while (0)
53708 
53709 #define DUK__RZ_STRING() do { \
53710 		duk__refcount_refzero_hstring(heap, (duk_hstring *) h); \
53711 	} while (0)
53712 #define DUK__RZ_BUFFER() do { \
53713 		duk__refcount_refzero_hbuffer(heap, (duk_hbuffer *) h); \
53714 	} while (0)
53715 #define DUK__RZ_OBJECT() do { \
53716 		duk__refcount_refzero_hobject(heap, (duk_hobject *) h, skip_free_pending); \
53717 	} while (0)
53718 
53719 /* XXX: test the effect of inlining here vs. NOINLINE in refzero helpers */
53720 #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
53721 #define DUK__RZ_INLINE DUK_ALWAYS_INLINE
53722 #else
53723 #define DUK__RZ_INLINE /*nop*/
53724 #endif
53725 
53726 DUK_LOCAL DUK__RZ_INLINE void duk__hstring_refzero_helper(duk_hthread *thr, duk_hstring *h) {
53727 	duk_heap *heap;
53728 
53729 	DUK_ASSERT(thr != NULL);
53730 	DUK_ASSERT(h != NULL);
53731 	heap = thr->heap;
53732 
53733 	DUK__RZ_SUPPRESS_CHECK();
53734 	DUK__RZ_STRING();
53735 }
53736 
53737 DUK_LOCAL DUK__RZ_INLINE void duk__hbuffer_refzero_helper(duk_hthread *thr, duk_hbuffer *h) {
53738 	duk_heap *heap;
53739 
53740 	DUK_ASSERT(thr != NULL);
53741 	DUK_ASSERT(h != NULL);
53742 	heap = thr->heap;
53743 
53744 	DUK__RZ_SUPPRESS_CHECK();
53745 	DUK__RZ_BUFFER();
53746 }
53747 
53748 DUK_LOCAL DUK__RZ_INLINE void duk__hobject_refzero_helper(duk_hthread *thr, duk_hobject *h, duk_bool_t skip_free_pending) {
53749 	duk_heap *heap;
53750 
53751 	DUK_ASSERT(thr != NULL);
53752 	DUK_ASSERT(h != NULL);
53753 	heap = thr->heap;
53754 
53755 	DUK__RZ_SUPPRESS_CHECK();
53756 	DUK__RZ_OBJECT();
53757 }
53758 
53759 DUK_LOCAL DUK__RZ_INLINE void duk__heaphdr_refzero_helper(duk_hthread *thr, duk_heaphdr *h, duk_bool_t skip_free_pending) {
53760 	duk_heap *heap;
53761 	duk_small_uint_t htype;
53762 
53763 	DUK_ASSERT(thr != NULL);
53764 	DUK_ASSERT(h != NULL);
53765 	heap = thr->heap;
53766 
53767 	htype = (duk_small_uint_t) DUK_HEAPHDR_GET_TYPE(h);
53768 	DUK_DDD(DUK_DDDPRINT("ms_running=%ld, heap_thread=%p", (long) thr->heap->ms_running, thr->heap->heap_thread));
53769 	DUK__RZ_SUPPRESS_CHECK();
53770 
53771 	switch (htype) {
53772 	case DUK_HTYPE_STRING:
53773 		/* Strings have no internal references but do have "weak"
53774 		 * references in the string cache.  Also note that strings
53775 		 * are not on the heap_allocated list like other heap
53776 		 * elements.
53777 		 */
53778 
53779 		DUK__RZ_STRING();
53780 		break;
53781 
53782 	case DUK_HTYPE_OBJECT:
53783 		/* Objects have internal references.  Must finalize through
53784 		 * the "refzero" work list.
53785 		 */
53786 
53787 		DUK__RZ_OBJECT();
53788 		break;
53789 
53790 	default:
53791 		/* Buffers have no internal references.  However, a dynamic
53792 		 * buffer has a separate allocation for the buffer.  This is
53793 		 * freed by duk_heap_free_heaphdr_raw().
53794 		 */
53795 
53796 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(h) == DUK_HTYPE_BUFFER);
53797 		DUK__RZ_BUFFER();
53798 		break;
53799 	}
53800 }
53801 
53802 DUK_INTERNAL DUK_NOINLINE void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h) {
53803 	duk__heaphdr_refzero_helper(thr, h, 0 /*skip_free_pending*/);
53804 }
53805 
53806 DUK_INTERNAL DUK_NOINLINE void duk_heaphdr_refzero_norz(duk_hthread *thr, duk_heaphdr *h) {
53807 	duk__heaphdr_refzero_helper(thr, h, 1 /*skip_free_pending*/);
53808 }
53809 
53810 DUK_INTERNAL DUK_NOINLINE void duk_hstring_refzero(duk_hthread *thr, duk_hstring *h) {
53811 	duk__hstring_refzero_helper(thr, h);
53812 }
53813 
53814 DUK_INTERNAL DUK_NOINLINE void duk_hbuffer_refzero(duk_hthread *thr, duk_hbuffer *h) {
53815 	duk__hbuffer_refzero_helper(thr, h);
53816 }
53817 
53818 DUK_INTERNAL DUK_NOINLINE void duk_hobject_refzero(duk_hthread *thr, duk_hobject *h) {
53819 	duk__hobject_refzero_helper(thr, h, 0 /*skip_free_pending*/);
53820 }
53821 
53822 DUK_INTERNAL DUK_NOINLINE void duk_hobject_refzero_norz(duk_hthread *thr, duk_hobject *h) {
53823 	duk__hobject_refzero_helper(thr, h, 1 /*skip_free_pending*/);
53824 }
53825 
53826 #if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
53827 DUK_INTERNAL void duk_tval_incref(duk_tval *tv) {
53828 	DUK_ASSERT(tv != NULL);
53829 
53830 	if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {
53831 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
53832 		DUK_ASSERT(h != NULL);
53833 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
53834 		DUK_ASSERT_DISABLE(h->h_refcount >= 0);
53835 		DUK_HEAPHDR_PREINC_REFCOUNT(h);
53836 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) != 0);  /* No wrapping. */
53837 	}
53838 }
53839 
53840 DUK_INTERNAL void duk_tval_decref(duk_hthread *thr, duk_tval *tv) {
53841 	DUK_ASSERT(thr != NULL);
53842 	DUK_ASSERT(tv != NULL);
53843 
53844 	if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {
53845 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
53846 		DUK_ASSERT(h != NULL);
53847 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
53848 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) >= 1);
53849 #if 0
53850 		if (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {
53851 			return;
53852 		}
53853 		duk_heaphdr_refzero(thr, h);
53854 #else
53855 		duk_heaphdr_decref(thr, h);
53856 #endif
53857 	}
53858 }
53859 
53860 DUK_INTERNAL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv) {
53861 	DUK_ASSERT(thr != NULL);
53862 	DUK_ASSERT(tv != NULL);
53863 
53864 	if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {
53865 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
53866 		DUK_ASSERT(h != NULL);
53867 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
53868 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) >= 1);
53869 #if 0
53870 		if (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {
53871 			return;
53872 		}
53873 		duk_heaphdr_refzero_norz(thr, h);
53874 #else
53875 		duk_heaphdr_decref_norz(thr, h);
53876 #endif
53877 	}
53878 }
53879 #endif  /* !DUK_USE_FAST_REFCOUNT_DEFAULT */
53880 
53881 #define DUK__DECREF_ASSERTS() do { \
53882 		DUK_ASSERT(thr != NULL); \
53883 		DUK_ASSERT(thr->heap != NULL); \
53884 		DUK_ASSERT(h != NULL); \
53885 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID((duk_heaphdr *) h)); \
53886 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) >= 1); \
53887 	} while (0)
53888 #if defined(DUK_USE_ROM_OBJECTS)
53889 #define DUK__INCREF_SHARED() do { \
53890 		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) { \
53891 			return; \
53892 		} \
53893 		DUK_HEAPHDR_PREINC_REFCOUNT((duk_heaphdr *) h); \
53894 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) != 0);  /* No wrapping. */ \
53895 	} while (0)
53896 #define DUK__DECREF_SHARED() do { \
53897 		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) { \
53898 			return; \
53899 		} \
53900 		if (DUK_HEAPHDR_PREDEC_REFCOUNT((duk_heaphdr *) h) != 0) { \
53901 			return; \
53902 		} \
53903 	} while (0)
53904 #else
53905 #define DUK__INCREF_SHARED() do { \
53906 		DUK_HEAPHDR_PREINC_REFCOUNT((duk_heaphdr *) h); \
53907 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) != 0);  /* No wrapping. */ \
53908 	} while (0)
53909 #define DUK__DECREF_SHARED() do { \
53910 		if (DUK_HEAPHDR_PREDEC_REFCOUNT((duk_heaphdr *) h) != 0) { \
53911 			return; \
53912 		} \
53913 	} while (0)
53914 #endif
53915 
53916 #if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
53917 /* This will in practice be inlined because it's just an INC instructions
53918  * and a bit test + INC when ROM objects are enabled.
53919  */
53920 DUK_INTERNAL void duk_heaphdr_incref(duk_heaphdr *h) {
53921 	DUK_ASSERT(h != NULL);
53922 	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
53923 	DUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(h) >= 0);
53924 
53925 	DUK__INCREF_SHARED();
53926 }
53927 
53928 DUK_INTERNAL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h) {
53929 	DUK__DECREF_ASSERTS();
53930 	DUK__DECREF_SHARED();
53931 	duk_heaphdr_refzero(thr, h);
53932 
53933 	/* Forced mark-and-sweep when GC torture enabled; this could happen
53934 	 * on any DECREF (but not DECREF_NORZ).
53935 	 */
53936 	DUK_GC_TORTURE(thr->heap);
53937 }
53938 DUK_INTERNAL void duk_heaphdr_decref_norz(duk_hthread *thr, duk_heaphdr *h) {
53939 	DUK__DECREF_ASSERTS();
53940 	DUK__DECREF_SHARED();
53941 	duk_heaphdr_refzero_norz(thr, h);
53942 }
53943 #endif  /* !DUK_USE_FAST_REFCOUNT_DEFAULT */
53944 
53945 #if 0  /* Not needed. */
53946 DUK_INTERNAL void duk_hstring_decref(duk_hthread *thr, duk_hstring *h) {
53947 	DUK__DECREF_ASSERTS();
53948 	DUK__DECREF_SHARED();
53949 	duk_hstring_refzero(thr, h);
53950 }
53951 DUK_INTERNAL void duk_hstring_decref_norz(duk_hthread *thr, duk_hstring *h) {
53952 	DUK__DECREF_ASSERTS();
53953 	DUK__DECREF_SHARED();
53954 	duk_hstring_refzero_norz(thr, h);
53955 }
53956 DUK_INTERNAL void duk_hbuffer_decref(duk_hthread *thr, duk_hbuffer *h) {
53957 	DUK__DECREF_ASSERTS();
53958 	DUK__DECREF_SHARED();
53959 	duk_hbuffer_refzero(thr, h);
53960 }
53961 DUK_INTERNAL void duk_hbuffer_decref_norz(duk_hthread *thr, duk_hbuffer *h) {
53962 	DUK__DECREF_ASSERTS();
53963 	DUK__DECREF_SHARED();
53964 	duk_hbuffer_refzero_norz(thr, h);
53965 }
53966 DUK_INTERNAL void duk_hobject_decref(duk_hthread *thr, duk_hobject *h) {
53967 	DUK__DECREF_ASSERTS();
53968 	DUK__DECREF_SHARED();
53969 	duk_hobject_refzero(thr, h);
53970 }
53971 DUK_INTERNAL void duk_hobject_decref_norz(duk_hthread *thr, duk_hobject *h) {
53972 	DUK__DECREF_ASSERTS();
53973 	DUK__DECREF_SHARED();
53974 	duk_hobject_refzero_norz(thr, h);
53975 }
53976 #endif
53977 
53978 #else  /* DUK_USE_REFERENCE_COUNTING */
53979 
53980 /* no refcounting */
53981 
53982 #endif  /* DUK_USE_REFERENCE_COUNTING */
53983 
53984 /* automatic undefs */
53985 #undef DUK__DECREF_ASSERTS
53986 #undef DUK__DECREF_SHARED
53987 #undef DUK__INCREF_SHARED
53988 #undef DUK__RZ_BUFFER
53989 #undef DUK__RZ_INLINE
53990 #undef DUK__RZ_OBJECT
53991 #undef DUK__RZ_STRING
53992 #undef DUK__RZ_SUPPRESS_ASSERT1
53993 #undef DUK__RZ_SUPPRESS_ASSERT2
53994 #undef DUK__RZ_SUPPRESS_CHECK
53995 #undef DUK__RZ_SUPPRESS_COND
53996 /*
53997  *  String cache.
53998  *
53999  *  Provides a cache to optimize indexed string lookups.  The cache keeps
54000  *  track of (byte offset, char offset) states for a fixed number of strings.
54001  *  Otherwise we'd need to scan from either end of the string, as we store
54002  *  strings in (extended) UTF-8.
54003  */
54004 
54005 /* #include duk_internal.h -> already included */
54006 
54007 /*
54008  *  Delete references to given hstring from the heap string cache.
54009  *
54010  *  String cache references are 'weak': they are not counted towards
54011  *  reference counts, nor serve as roots for mark-and-sweep.  When an
54012  *  object is about to be freed, such references need to be removed.
54013  */
54014 
54015 DUK_INTERNAL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h) {
54016 	duk_uint_t i;
54017 	for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
54018 		duk_strcache_entry *c = heap->strcache + i;
54019 		if (c->h == h) {
54020 			DUK_DD(DUK_DDPRINT("deleting weak strcache reference to hstring %p from heap %p",
54021 			                   (void *) h, (void *) heap));
54022 			c->h = NULL;
54023 
54024 			/* XXX: the string shouldn't appear twice, but we now loop to the
54025 			 * end anyway; if fixed, add a looping assertion to ensure there
54026 			 * is no duplicate.
54027 			 */
54028 		}
54029 	}
54030 }
54031 
54032 /*
54033  *  String scanning helpers
54034  *
54035  *  All bytes other than UTF-8 continuation bytes ([0x80,0xbf]) are
54036  *  considered to contribute a character.  This must match how string
54037  *  character length is computed.
54038  */
54039 
54040 DUK_LOCAL const duk_uint8_t *duk__scan_forwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {
54041 	while (n > 0) {
54042 		for (;;) {
54043 			p++;
54044 			if (p >= q) {
54045 				return NULL;
54046 			}
54047 			if ((*p & 0xc0) != 0x80) {
54048 				break;
54049 			}
54050 		}
54051 		n--;
54052 	}
54053 	return p;
54054 }
54055 
54056 DUK_LOCAL const duk_uint8_t *duk__scan_backwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {
54057 	while (n > 0) {
54058 		for (;;) {
54059 			p--;
54060 			if (p < q) {
54061 				return NULL;
54062 			}
54063 			if ((*p & 0xc0) != 0x80) {
54064 				break;
54065 			}
54066 		}
54067 		n--;
54068 	}
54069 	return p;
54070 }
54071 
54072 /*
54073  *  Convert char offset to byte offset
54074  *
54075  *  Avoid using the string cache if possible: for ASCII strings byte and
54076  *  char offsets are equal and for short strings direct scanning may be
54077  *  better than using the string cache (which may evict a more important
54078  *  entry).
54079  *
54080  *  Typing now assumes 32-bit string byte/char offsets (duk_uint_fast32_t).
54081  *  Better typing might be to use duk_size_t.
54082  *
54083  *  Caller should ensure 'char_offset' is within the string bounds [0,charlen]
54084  *  (endpoint is inclusive).  If this is not the case, no memory unsafe
54085  *  behavior will happen but an error will be thrown.
54086  */
54087 
54088 DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset) {
54089 	duk_heap *heap;
54090 	duk_strcache_entry *sce;
54091 	duk_uint_fast32_t byte_offset;
54092 	duk_uint_t i;
54093 	duk_bool_t use_cache;
54094 	duk_uint_fast32_t dist_start, dist_end, dist_sce;
54095 	duk_uint_fast32_t char_length;
54096 	const duk_uint8_t *p_start;
54097 	const duk_uint8_t *p_end;
54098 	const duk_uint8_t *p_found;
54099 
54100 	/*
54101 	 *  For ASCII strings, the answer is simple.
54102 	 */
54103 
54104 	if (DUK_LIKELY(DUK_HSTRING_IS_ASCII(h))) {
54105 		return char_offset;
54106 	}
54107 
54108 	char_length = (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h);
54109 	DUK_ASSERT(char_offset <= char_length);
54110 
54111 	if (DUK_LIKELY(DUK_HSTRING_IS_ASCII(h))) {
54112 		/* Must recheck because the 'is ascii' flag may be set
54113 		 * lazily.  Alternatively, we could just compare charlen
54114 		 * to bytelen.
54115 		 */
54116 		return char_offset;
54117 	}
54118 
54119 	/*
54120 	 *  For non-ASCII strings, we need to scan forwards or backwards
54121 	 *  from some starting point.  The starting point may be the start
54122 	 *  or end of the string, or some cached midpoint in the string
54123 	 *  cache.
54124 	 *
54125 	 *  For "short" strings we simply scan without checking or updating
54126 	 *  the cache.  For longer strings we check and update the cache as
54127 	 *  necessary, inserting a new cache entry if none exists.
54128 	 */
54129 
54130 	DUK_DDD(DUK_DDDPRINT("non-ascii string %p, char_offset=%ld, clen=%ld, blen=%ld",
54131 	                     (void *) h, (long) char_offset,
54132 	                     (long) DUK_HSTRING_GET_CHARLEN(h),
54133 	                     (long) DUK_HSTRING_GET_BYTELEN(h)));
54134 
54135 	heap = thr->heap;
54136 	sce = NULL;
54137 	use_cache = (char_length > DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT);
54138 
54139 	if (use_cache) {
54140 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
54141 		DUK_DDD(DUK_DDDPRINT("stringcache before char2byte (using cache):"));
54142 		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
54143 			duk_strcache_entry *c = heap->strcache + i;
54144 			DUK_DDD(DUK_DDDPRINT("  [%ld] -> h=%p, cidx=%ld, bidx=%ld",
54145 			                     (long) i, (void *) c->h, (long) c->cidx, (long) c->bidx));
54146 		}
54147 #endif
54148 
54149 		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
54150 			duk_strcache_entry *c = heap->strcache + i;
54151 
54152 			if (c->h == h) {
54153 				sce = c;
54154 				break;
54155 			}
54156 		}
54157 	}
54158 
54159 	/*
54160 	 *  Scan from shortest distance:
54161 	 *    - start of string
54162 	 *    - end of string
54163 	 *    - cache entry (if exists)
54164 	 */
54165 
54166 	DUK_ASSERT(DUK_HSTRING_GET_CHARLEN(h) >= char_offset);
54167 	dist_start = char_offset;
54168 	dist_end = char_length - char_offset;
54169 	dist_sce = 0; DUK_UNREF(dist_sce);  /* initialize for debug prints, needed if sce==NULL */
54170 
54171 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
54172 	p_end = (const duk_uint8_t *) (p_start + DUK_HSTRING_GET_BYTELEN(h));
54173 	p_found = NULL;
54174 
54175 	if (sce) {
54176 		if (char_offset >= sce->cidx) {
54177 			dist_sce = char_offset - sce->cidx;
54178 			if ((dist_sce <= dist_start) && (dist_sce <= dist_end)) {
54179 				DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
54180 				                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
54181 				                     "scan forwards from sce",
54182 				                     (long) use_cache, (void *) (sce ? sce->h : NULL),
54183 				                     (sce ? (long) sce->cidx : (long) -1),
54184 				                     (sce ? (long) sce->bidx : (long) -1),
54185 				                     (long) dist_start, (long) dist_end, (long) dist_sce));
54186 
54187 				p_found = duk__scan_forwards(p_start + sce->bidx,
54188 				                             p_end,
54189 				                             dist_sce);
54190 				goto scan_done;
54191 			}
54192 		} else {
54193 			dist_sce = sce->cidx - char_offset;
54194 			if ((dist_sce <= dist_start) && (dist_sce <= dist_end)) {
54195 				DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
54196 				                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
54197 				                     "scan backwards from sce",
54198 				                     (long) use_cache, (void *) (sce ? sce->h : NULL),
54199 				                     (sce ? (long) sce->cidx : (long) -1),
54200 				                     (sce ? (long) sce->bidx : (long) -1),
54201 				                     (long) dist_start, (long) dist_end, (long) dist_sce));
54202 
54203 				p_found = duk__scan_backwards(p_start + sce->bidx,
54204 				                              p_start,
54205 				                              dist_sce);
54206 				goto scan_done;
54207 			}
54208 		}
54209 	}
54210 
54211 	/* no sce, or sce scan not best */
54212 
54213 	if (dist_start <= dist_end) {
54214 		DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
54215 		                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
54216 		                     "scan forwards from string start",
54217 		                     (long) use_cache, (void *) (sce ? sce->h : NULL),
54218 		                     (sce ? (long) sce->cidx : (long) -1),
54219 		                     (sce ? (long) sce->bidx : (long) -1),
54220 		                     (long) dist_start, (long) dist_end, (long) dist_sce));
54221 
54222 		p_found = duk__scan_forwards(p_start,
54223 		                             p_end,
54224 		                             dist_start);
54225 	} else {
54226 		DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
54227 		                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
54228 		                     "scan backwards from string end",
54229 		                     (long) use_cache, (void *) (sce ? sce->h : NULL),
54230 		                     (sce ? (long) sce->cidx : (long) -1),
54231 		                     (sce ? (long) sce->bidx : (long) -1),
54232 		                     (long) dist_start, (long) dist_end, (long) dist_sce));
54233 
54234 		p_found = duk__scan_backwards(p_end,
54235 		                              p_start,
54236 		                              dist_end);
54237 	}
54238 
54239  scan_done:
54240 
54241 	if (DUK_UNLIKELY(p_found == NULL)) {
54242 		/* Scan error: this shouldn't normally happen; it could happen if
54243 		 * string is not valid UTF-8 data, and clen/blen are not consistent
54244 		 * with the scanning algorithm.
54245 		 */
54246 		goto scan_error;
54247 	}
54248 
54249 	DUK_ASSERT(p_found >= p_start);
54250 	DUK_ASSERT(p_found <= p_end);  /* may be equal */
54251 	byte_offset = (duk_uint32_t) (p_found - p_start);
54252 
54253 	DUK_DDD(DUK_DDDPRINT("-> string %p, cidx %ld -> bidx %ld",
54254 	                     (void *) h, (long) char_offset, (long) byte_offset));
54255 
54256 	/*
54257 	 *  Update cache entry (allocating if necessary), and move the
54258 	 *  cache entry to the first place (in an "LRU" policy).
54259 	 */
54260 
54261 	if (use_cache) {
54262 		/* update entry, allocating if necessary */
54263 		if (!sce) {
54264 			sce = heap->strcache + DUK_HEAP_STRCACHE_SIZE - 1;  /* take last entry */
54265 			sce->h = h;
54266 		}
54267 		DUK_ASSERT(sce != NULL);
54268 		sce->bidx = (duk_uint32_t) (p_found - p_start);
54269 		sce->cidx = (duk_uint32_t) char_offset;
54270 
54271 		/* LRU: move our entry to first */
54272 		if (sce > &heap->strcache[0]) {
54273 			/*
54274 			 *   A                  C
54275 			 *   B                  A
54276 			 *   C <- sce    ==>    B
54277 			 *   D                  D
54278 			 */
54279 			duk_strcache_entry tmp;
54280 
54281 			tmp = *sce;
54282 			duk_memmove((void *) (&heap->strcache[1]),
54283 			            (const void *) (&heap->strcache[0]),
54284 			            (size_t) (((char *) sce) - ((char *) &heap->strcache[0])));
54285 			heap->strcache[0] = tmp;
54286 
54287 			/* 'sce' points to the wrong entry here, but is no longer used */
54288 		}
54289 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
54290 		DUK_DDD(DUK_DDDPRINT("stringcache after char2byte (using cache):"));
54291 		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
54292 			duk_strcache_entry *c = heap->strcache + i;
54293 			DUK_DDD(DUK_DDDPRINT("  [%ld] -> h=%p, cidx=%ld, bidx=%ld",
54294 			                     (long) i, (void *) c->h, (long) c->cidx, (long) c->bidx));
54295 		}
54296 #endif
54297 	}
54298 
54299 	return byte_offset;
54300 
54301  scan_error:
54302 	DUK_ERROR_INTERNAL(thr);
54303 	DUK_WO_NORETURN(return 0;);
54304 }
54305 /*
54306  *  Heap string table handling, string interning.
54307  */
54308 
54309 /* #include duk_internal.h -> already included */
54310 
54311 /* Resize checks not needed if minsize == maxsize, typical for low memory
54312  * targets.
54313  */
54314 #define DUK__STRTAB_RESIZE_CHECK
54315 #if (DUK_USE_STRTAB_MINSIZE == DUK_USE_STRTAB_MAXSIZE)
54316 #undef DUK__STRTAB_RESIZE_CHECK
54317 #endif
54318 
54319 #if defined(DUK_USE_STRTAB_PTRCOMP)
54320 #define DUK__HEAPPTR_ENC16(heap,ptr)    DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (ptr))
54321 #define DUK__HEAPPTR_DEC16(heap,val)    DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (val))
54322 #define DUK__GET_STRTABLE(heap)         ((heap)->strtable16)
54323 #else
54324 #define DUK__HEAPPTR_ENC16(heap,ptr)    (ptr)
54325 #define DUK__HEAPPTR_DEC16(heap,val)    (val)
54326 #define DUK__GET_STRTABLE(heap)         ((heap)->strtable)
54327 #endif
54328 
54329 #define DUK__STRTAB_U32_MAX_STRLEN      10               /* 4'294'967'295 */
54330 
54331 /*
54332  *  Debug dump stringtable.
54333  */
54334 
54335 #if defined(DUK_USE_DEBUG)
54336 DUK_INTERNAL void duk_heap_strtable_dump(duk_heap *heap) {
54337 #if defined(DUK_USE_STRTAB_PTRCOMP)
54338 	duk_uint16_t *strtable;
54339 #else
54340 	duk_hstring **strtable;
54341 #endif
54342 	duk_uint32_t i;
54343 	duk_hstring *h;
54344 	duk_size_t count_total = 0;
54345 	duk_size_t count_chain;
54346 	duk_size_t count_chain_min = DUK_SIZE_MAX;
54347 	duk_size_t count_chain_max = 0;
54348 	duk_size_t count_len[8];  /* chain lengths from 0 to 7 */
54349 
54350 	if (heap == NULL) {
54351 		DUK_D(DUK_DPRINT("string table, heap=NULL"));
54352 		return;
54353 	}
54354 
54355 	strtable = DUK__GET_STRTABLE(heap);
54356 	if (strtable == NULL) {
54357 		DUK_D(DUK_DPRINT("string table, strtab=NULL"));
54358 		return;
54359 	}
54360 
54361 	duk_memzero((void *) count_len, sizeof(count_len));
54362 	for (i = 0; i < heap->st_size; i++) {
54363 		h = DUK__HEAPPTR_DEC16(heap, strtable[i]);
54364 		count_chain = 0;
54365 		while (h != NULL) {
54366 			count_chain++;
54367 			h = h->hdr.h_next;
54368 		}
54369 		if (count_chain < sizeof(count_len) / sizeof(duk_size_t)) {
54370 			count_len[count_chain]++;
54371 		}
54372 		count_chain_max = (count_chain > count_chain_max ? count_chain : count_chain_max);
54373 		count_chain_min = (count_chain < count_chain_min ? count_chain : count_chain_min);
54374 		count_total += count_chain;
54375 	}
54376 
54377 	DUK_D(DUK_DPRINT("string table, strtab=%p, count=%lu, chain min=%lu max=%lu avg=%lf: "
54378 	                 "counts: %lu %lu %lu %lu %lu %lu %lu %lu ...",
54379 	                 (void *) heap->strtable, (unsigned long) count_total,
54380 	                 (unsigned long) count_chain_min, (unsigned long) count_chain_max,
54381 	                 (double) count_total / (double) heap->st_size,
54382 	                 (unsigned long) count_len[0], (unsigned long) count_len[1],
54383 	                 (unsigned long) count_len[2], (unsigned long) count_len[3],
54384 	                 (unsigned long) count_len[4], (unsigned long) count_len[5],
54385 	                 (unsigned long) count_len[6], (unsigned long) count_len[7]));
54386 }
54387 #endif  /* DUK_USE_DEBUG */
54388 
54389 /*
54390  *  Assertion helper to ensure strtable is populated correctly.
54391  */
54392 
54393 #if defined(DUK_USE_ASSERTIONS)
54394 DUK_LOCAL void duk__strtable_assert_checks(duk_heap *heap) {
54395 #if defined(DUK_USE_STRTAB_PTRCOMP)
54396 	duk_uint16_t *strtable;
54397 #else
54398 	duk_hstring **strtable;
54399 #endif
54400 	duk_uint32_t i;
54401 	duk_hstring *h;
54402 	duk_size_t count = 0;
54403 
54404 	DUK_ASSERT(heap != NULL);
54405 
54406 	strtable = DUK__GET_STRTABLE(heap);
54407 	if (strtable != NULL) {
54408 		DUK_ASSERT(heap->st_size != 0);
54409 		DUK_ASSERT(heap->st_mask == heap->st_size - 1);
54410 
54411 		for (i = 0; i < heap->st_size; i++) {
54412 			h = DUK__HEAPPTR_DEC16(heap, strtable[i]);
54413 			while (h != NULL) {
54414 				DUK_ASSERT((DUK_HSTRING_GET_HASH(h) & heap->st_mask) == i);
54415 				count++;
54416 				h = h->hdr.h_next;
54417 			}
54418 		}
54419 	} else {
54420 		DUK_ASSERT(heap->st_size == 0);
54421 		DUK_ASSERT(heap->st_mask == 0);
54422 	}
54423 
54424 #if defined(DUK__STRTAB_RESIZE_CHECK)
54425 	DUK_ASSERT(count == (duk_size_t) heap->st_count);
54426 #endif
54427 }
54428 #endif  /* DUK_USE_ASSERTIONS */
54429 
54430 /*
54431  *  Allocate and initialize a duk_hstring.
54432  *
54433  *  Returns a NULL if allocation or initialization fails for some reason.
54434  *
54435  *  The string won't be inserted into the string table and isn't tracked in
54436  *  any way (link pointers will be NULL).  The caller must place the string
54437  *  into the string table without any risk of a longjmp, otherwise the string
54438  *  is leaked.
54439  */
54440 
54441 DUK_LOCAL duk_hstring *duk__strtable_alloc_hstring(duk_heap *heap,
54442                                                    const duk_uint8_t *str,
54443                                                    duk_uint32_t blen,
54444                                                    duk_uint32_t strhash,
54445                                                    const duk_uint8_t *extdata) {
54446 	duk_hstring *res;
54447 	const duk_uint8_t *data;
54448 #if !defined(DUK_USE_HSTRING_ARRIDX)
54449 	duk_uarridx_t dummy;
54450 #endif
54451 
54452 	DUK_ASSERT(heap != NULL);
54453 	DUK_UNREF(extdata);
54454 
54455 #if defined(DUK_USE_STRLEN16)
54456 	/* If blen <= 0xffffUL, clen is also guaranteed to be <= 0xffffUL. */
54457 	if (blen > 0xffffUL) {
54458 		DUK_D(DUK_DPRINT("16-bit string blen/clen active and blen over 16 bits, reject intern"));
54459 		goto alloc_error;
54460 	}
54461 #endif
54462 
54463 	/* XXX: Memzeroing the allocated structure is not really necessary
54464 	 * because we could just initialize all fields explicitly (almost
54465 	 * all fields are initialized explicitly anyway).
54466 	 */
54467 #if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
54468 	if (extdata) {
54469 		res = (duk_hstring *) DUK_ALLOC(heap, sizeof(duk_hstring_external));
54470 		if (DUK_UNLIKELY(res == NULL)) {
54471 			goto alloc_error;
54472 		}
54473 		duk_memzero(res, sizeof(duk_hstring_external));
54474 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
54475 		DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr);
54476 #endif
54477 		DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, DUK_HSTRING_FLAG_EXTDATA);
54478 
54479 		DUK_ASSERT(extdata[blen] == 0);  /* Application responsibility. */
54480 		data = extdata;
54481 		((duk_hstring_external *) res)->extdata = extdata;
54482 	} else
54483 #endif  /* DUK_USE_HSTRING_EXTDATA && DUK_USE_EXTSTR_INTERN_CHECK */
54484 	{
54485 		duk_uint8_t *data_tmp;
54486 
54487 		/* NUL terminate for convenient C access */
54488 		DUK_ASSERT(sizeof(duk_hstring) + blen + 1 > blen);  /* No wrap, limits ensure. */
54489 		res = (duk_hstring *) DUK_ALLOC(heap, sizeof(duk_hstring) + blen + 1);
54490 		if (DUK_UNLIKELY(res == NULL)) {
54491 			goto alloc_error;
54492 		}
54493 		duk_memzero(res, sizeof(duk_hstring));
54494 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
54495 		DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr);
54496 #endif
54497 		DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, 0);
54498 
54499 		data_tmp = (duk_uint8_t *) (res + 1);
54500 		duk_memcpy(data_tmp, str, blen);
54501 		data_tmp[blen] = (duk_uint8_t) 0;
54502 		data = (const duk_uint8_t *) data_tmp;
54503 	}
54504 
54505 	DUK_HSTRING_SET_BYTELEN(res, blen);
54506 	DUK_HSTRING_SET_HASH(res, strhash);
54507 
54508 	DUK_ASSERT(!DUK_HSTRING_HAS_ARRIDX(res));
54509 #if defined(DUK_USE_HSTRING_ARRIDX)
54510 	res->arridx = duk_js_to_arrayindex_string(data, blen);
54511 	if (res->arridx != DUK_HSTRING_NO_ARRAY_INDEX) {
54512 #else
54513 	dummy = duk_js_to_arrayindex_string(data, blen);
54514 	if (dummy != DUK_HSTRING_NO_ARRAY_INDEX) {
54515 #endif
54516 		/* Array index strings cannot be symbol strings,
54517 		 * and they're always pure ASCII so blen == clen.
54518 		 */
54519 		DUK_HSTRING_SET_ARRIDX(res);
54520 		DUK_HSTRING_SET_ASCII(res);
54521 		DUK_ASSERT(duk_unicode_unvalidated_utf8_length(data, (duk_size_t) blen) == blen);
54522 	} else {
54523 		/* Because 'data' is NUL-terminated, we don't need a
54524 		 * blen > 0 check here.  For NUL (0x00) the symbol
54525 		 * checks will be false.
54526 		 */
54527 		if (DUK_UNLIKELY(data[0] >= 0x80U)) {
54528 			if (data[0] <= 0x81) {
54529 				DUK_HSTRING_SET_SYMBOL(res);
54530 			} else if (data[0] == 0x82U || data[0] == 0xffU) {
54531 				DUK_HSTRING_SET_HIDDEN(res);
54532 				DUK_HSTRING_SET_SYMBOL(res);
54533 			}
54534 		}
54535 
54536 		/* Using an explicit 'ASCII' flag has larger footprint (one call site
54537 		 * only) but is quite useful for the case when there's no explicit
54538 		 * 'clen' in duk_hstring.
54539 		 *
54540 		 * The flag is set lazily for RAM strings.
54541 		 */
54542 		DUK_ASSERT(!DUK_HSTRING_HAS_ASCII(res));
54543 
54544 #if defined(DUK_USE_HSTRING_LAZY_CLEN)
54545 		/* Charlen initialized to 0, updated on-the-fly. */
54546 #else
54547 		duk_hstring_init_charlen(res);  /* Also sets ASCII flag. */
54548 #endif
54549 	}
54550 
54551 	DUK_DDD(DUK_DDDPRINT("interned string, hash=0x%08lx, blen=%ld, has_arridx=%ld, has_extdata=%ld",
54552 	                     (unsigned long) DUK_HSTRING_GET_HASH(res),
54553 	                     (long) DUK_HSTRING_GET_BYTELEN(res),
54554 	                     (long) (DUK_HSTRING_HAS_ARRIDX(res) ? 1 : 0),
54555 	                     (long) (DUK_HSTRING_HAS_EXTDATA(res) ? 1 : 0)));
54556 
54557 	DUK_ASSERT(res != NULL);
54558 	return res;
54559 
54560  alloc_error:
54561 	return NULL;
54562 }
54563 
54564 /*
54565  *  Grow strtable allocation in-place.
54566  */
54567 
54568 #if defined(DUK__STRTAB_RESIZE_CHECK)
54569 DUK_LOCAL void duk__strtable_grow_inplace(duk_heap *heap) {
54570 	duk_uint32_t new_st_size;
54571 	duk_uint32_t old_st_size;
54572 	duk_uint32_t i;
54573 	duk_hstring *h;
54574 	duk_hstring *next;
54575 	duk_hstring *prev;
54576 #if defined(DUK_USE_STRTAB_PTRCOMP)
54577 	duk_uint16_t *new_ptr;
54578 	duk_uint16_t *new_ptr_high;
54579 #else
54580 	duk_hstring **new_ptr;
54581 	duk_hstring **new_ptr_high;
54582 #endif
54583 
54584 	DUK_DD(DUK_DDPRINT("grow in-place: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size * 2));
54585 
54586 	DUK_ASSERT(heap != NULL);
54587 	DUK_ASSERT(heap->st_resizing == 1);
54588 	DUK_ASSERT(heap->st_size >= 2);
54589 	DUK_ASSERT((heap->st_size & (heap->st_size - 1)) == 0);  /* 2^N */
54590 	DUK_ASSERT(DUK__GET_STRTABLE(heap) != NULL);
54591 
54592 	DUK_STATS_INC(heap, stats_strtab_resize_grow);
54593 
54594 	new_st_size = heap->st_size << 1U;
54595 	DUK_ASSERT(new_st_size > heap->st_size);  /* No overflow. */
54596 
54597 	/* Reallocate the strtable first and then work in-place to rehash
54598 	 * strings.  We don't need an indirect allocation here: even if GC
54599 	 * is triggered to satisfy the allocation, recursive strtable resize
54600 	 * is prevented by flags.  This is also why we don't need to use
54601 	 * DUK_REALLOC_INDIRECT().
54602 	 */
54603 
54604 #if defined(DUK_USE_STRTAB_PTRCOMP)
54605 	new_ptr = (duk_uint16_t *) DUK_REALLOC(heap, heap->strtable16, sizeof(duk_uint16_t) * new_st_size);
54606 #else
54607 	new_ptr = (duk_hstring **) DUK_REALLOC(heap, heap->strtable, sizeof(duk_hstring *) * new_st_size);
54608 #endif
54609 	if (DUK_UNLIKELY(new_ptr == NULL)) {
54610 		/* If realloc fails we can continue normally: the string table
54611 		 * won't "fill up" although chains will gradually get longer.
54612 		 * When string insertions continue, we'll quite soon try again
54613 		 * with no special handling.
54614 		 */
54615 		DUK_D(DUK_DPRINT("string table grow failed, ignoring"));
54616 		return;
54617 	}
54618 #if defined(DUK_USE_STRTAB_PTRCOMP)
54619 	heap->strtable16 = new_ptr;
54620 #else
54621 	heap->strtable = new_ptr;
54622 #endif
54623 
54624 	/* Rehash a single bucket into two separate ones.  When we grow
54625 	 * by x2 the highest 'new' bit determines whether a string remains
54626 	 * in its old position (bit is 0) or goes to a new one (bit is 1).
54627 	 */
54628 
54629 	old_st_size = heap->st_size;
54630 	new_ptr_high = new_ptr + old_st_size;
54631 	for (i = 0; i < old_st_size; i++) {
54632 		duk_hstring *new_root;
54633 		duk_hstring *new_root_high;
54634 
54635 		h = DUK__HEAPPTR_DEC16(heap, new_ptr[i]);
54636 		new_root = h;
54637 		new_root_high = NULL;
54638 
54639 		prev = NULL;
54640 		while (h != NULL) {
54641 			duk_uint32_t mask;
54642 
54643 			DUK_ASSERT((DUK_HSTRING_GET_HASH(h) & heap->st_mask) == i);
54644 			next = h->hdr.h_next;
54645 
54646 			/* Example: if previous size was 256, previous mask is 0xFF
54647 			 * and size is 0x100 which corresponds to the new bit that
54648 			 * comes into play.
54649 			 */
54650 			DUK_ASSERT(heap->st_mask == old_st_size - 1);
54651 			mask = old_st_size;
54652 			if (DUK_HSTRING_GET_HASH(h) & mask) {
54653 				if (prev != NULL) {
54654 					prev->hdr.h_next = h->hdr.h_next;
54655 				} else {
54656 					DUK_ASSERT(h == new_root);
54657 					new_root = h->hdr.h_next;
54658 				}
54659 
54660 				h->hdr.h_next = new_root_high;
54661 				new_root_high = h;
54662 			} else {
54663 				prev = h;
54664 			}
54665 			h = next;
54666 		}
54667 
54668 		new_ptr[i] = DUK__HEAPPTR_ENC16(heap, new_root);
54669 		new_ptr_high[i] = DUK__HEAPPTR_ENC16(heap, new_root_high);
54670 	}
54671 
54672 	heap->st_size = new_st_size;
54673 	heap->st_mask = new_st_size - 1;
54674 
54675 #if defined(DUK_USE_ASSERTIONS)
54676 	duk__strtable_assert_checks(heap);
54677 #endif
54678 }
54679 #endif  /* DUK__STRTAB_RESIZE_CHECK */
54680 
54681 /*
54682  *  Shrink strtable allocation in-place.
54683  */
54684 
54685 #if defined(DUK__STRTAB_RESIZE_CHECK)
54686 DUK_LOCAL void duk__strtable_shrink_inplace(duk_heap *heap) {
54687 	duk_uint32_t new_st_size;
54688 	duk_uint32_t i;
54689 	duk_hstring *h;
54690 	duk_hstring *other;
54691 	duk_hstring *root;
54692 #if defined(DUK_USE_STRTAB_PTRCOMP)
54693 	duk_uint16_t *old_ptr;
54694 	duk_uint16_t *old_ptr_high;
54695 	duk_uint16_t *new_ptr;
54696 #else
54697 	duk_hstring **old_ptr;
54698 	duk_hstring **old_ptr_high;
54699 	duk_hstring **new_ptr;
54700 #endif
54701 
54702 	DUK_DD(DUK_DDPRINT("shrink in-place: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size / 2));
54703 
54704 	DUK_ASSERT(heap != NULL);
54705 	DUK_ASSERT(heap->st_resizing == 1);
54706 	DUK_ASSERT(heap->st_size >= 2);
54707 	DUK_ASSERT((heap->st_size & (heap->st_size - 1)) == 0);  /* 2^N */
54708 	DUK_ASSERT(DUK__GET_STRTABLE(heap) != NULL);
54709 
54710 	DUK_STATS_INC(heap, stats_strtab_resize_shrink);
54711 
54712 	new_st_size = heap->st_size >> 1U;
54713 
54714 	/* Combine two buckets into a single one.  When we shrink, one hash
54715 	 * bit (highest) disappears.
54716 	 */
54717 	old_ptr = DUK__GET_STRTABLE(heap);
54718 	old_ptr_high = old_ptr + new_st_size;
54719 	for (i = 0; i < new_st_size; i++) {
54720 		h = DUK__HEAPPTR_DEC16(heap, old_ptr[i]);
54721 		other = DUK__HEAPPTR_DEC16(heap, old_ptr_high[i]);
54722 
54723 		if (h == NULL) {
54724 			/* First chain is empty, so use second one as is. */
54725 			root = other;
54726 		} else {
54727 			/* Find end of first chain, and link in the second. */
54728 			root = h;
54729 			while (h->hdr.h_next != NULL) {
54730 				h = h->hdr.h_next;
54731 			}
54732 			h->hdr.h_next = other;
54733 		}
54734 
54735 		old_ptr[i] = DUK__HEAPPTR_ENC16(heap, root);
54736 	}
54737 
54738 	heap->st_size = new_st_size;
54739 	heap->st_mask = new_st_size - 1;
54740 
54741 	/* The strtable is now consistent and we can realloc safely.  Even
54742 	 * if side effects cause string interning or removal the strtable
54743 	 * updates are safe.  Recursive resize has been prevented by caller.
54744 	 * This is also why we don't need to use DUK_REALLOC_INDIRECT().
54745 	 *
54746 	 * We assume a realloc() to a smaller size is guaranteed to succeed.
54747 	 * It would be relatively straightforward to handle the error by
54748 	 * essentially performing a "grow" step to recover.
54749 	 */
54750 
54751 #if defined(DUK_USE_STRTAB_PTRCOMP)
54752 	new_ptr = (duk_uint16_t *) DUK_REALLOC(heap, heap->strtable16, sizeof(duk_uint16_t) * new_st_size);
54753 	DUK_ASSERT(new_ptr != NULL);
54754 	heap->strtable16 = new_ptr;
54755 #else
54756 	new_ptr = (duk_hstring **) DUK_REALLOC(heap, heap->strtable, sizeof(duk_hstring *) * new_st_size);
54757 	DUK_ASSERT(new_ptr != NULL);
54758 	heap->strtable = new_ptr;
54759 #endif
54760 
54761 #if defined(DUK_USE_ASSERTIONS)
54762 	duk__strtable_assert_checks(heap);
54763 #endif
54764 }
54765 #endif  /* DUK__STRTAB_RESIZE_CHECK */
54766 
54767 /*
54768  *  Grow/shrink check.
54769  */
54770 
54771 #if defined(DUK__STRTAB_RESIZE_CHECK)
54772 DUK_LOCAL DUK_COLD DUK_NOINLINE void duk__strtable_resize_check(duk_heap *heap) {
54773 	duk_uint32_t load_factor;  /* fixed point */
54774 
54775 	DUK_ASSERT(heap != NULL);
54776 #if defined(DUK_USE_STRTAB_PTRCOMP)
54777 	DUK_ASSERT(heap->strtable16 != NULL);
54778 #else
54779 	DUK_ASSERT(heap->strtable != NULL);
54780 #endif
54781 
54782 	DUK_STATS_INC(heap, stats_strtab_resize_check);
54783 
54784 	/* Prevent recursive resizing. */
54785 	if (DUK_UNLIKELY(heap->st_resizing != 0U)) {
54786 		DUK_D(DUK_DPRINT("prevent recursive strtable resize"));
54787 		return;
54788 	}
54789 
54790 	heap->st_resizing = 1;
54791 
54792 	DUK_ASSERT(heap->st_size >= 16U);
54793 	DUK_ASSERT((heap->st_size >> 4U) >= 1);
54794 	load_factor = heap->st_count / (heap->st_size >> 4U);
54795 
54796 	DUK_DD(DUK_DDPRINT("resize check string table: size=%lu, count=%lu, load_factor=%lu (fixed point .4; float %lf)",
54797 	                   (unsigned long) heap->st_size, (unsigned long) heap->st_count,
54798 	                   (unsigned long) load_factor,
54799 	                   (double) heap->st_count / (double) heap->st_size));
54800 
54801 	if (load_factor >= DUK_USE_STRTAB_GROW_LIMIT) {
54802 		if (heap->st_size >= DUK_USE_STRTAB_MAXSIZE) {
54803 			DUK_DD(DUK_DDPRINT("want to grow strtable (based on load factor) but already maximum size"));
54804 		} else {
54805 			DUK_D(DUK_DPRINT("grow string table: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size * 2));
54806 #if defined(DUK_USE_DEBUG)
54807 			duk_heap_strtable_dump(heap);
54808 #endif
54809 			duk__strtable_grow_inplace(heap);
54810 		}
54811 	} else if (load_factor <= DUK_USE_STRTAB_SHRINK_LIMIT) {
54812 		if (heap->st_size <= DUK_USE_STRTAB_MINSIZE) {
54813 			DUK_DD(DUK_DDPRINT("want to shrink strtable (based on load factor) but already minimum size"));
54814 		} else {
54815 			DUK_D(DUK_DPRINT("shrink string table: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size / 2));
54816 #if defined(DUK_USE_DEBUG)
54817 			duk_heap_strtable_dump(heap);
54818 #endif
54819 			duk__strtable_shrink_inplace(heap);
54820 		}
54821 	} else {
54822 		DUK_DD(DUK_DDPRINT("no need for strtable resize"));
54823 	}
54824 
54825 	heap->st_resizing = 0;
54826 }
54827 #endif  /* DUK__STRTAB_RESIZE_CHECK */
54828 
54829 /*
54830  *  Torture grow/shrink: unconditionally grow and shrink back.
54831  */
54832 
54833 #if defined(DUK_USE_STRTAB_TORTURE) && defined(DUK__STRTAB_RESIZE_CHECK)
54834 DUK_LOCAL void duk__strtable_resize_torture(duk_heap *heap) {
54835 	duk_uint32_t old_st_size;
54836 
54837 	DUK_ASSERT(heap != NULL);
54838 
54839 	old_st_size = heap->st_size;
54840 	if (old_st_size >= DUK_USE_STRTAB_MAXSIZE) {
54841 		return;
54842 	}
54843 
54844 	heap->st_resizing = 1;
54845 	duk__strtable_grow_inplace(heap);
54846 	if (heap->st_size > old_st_size) {
54847 		duk__strtable_shrink_inplace(heap);
54848 	}
54849 	heap->st_resizing = 0;
54850 }
54851 #endif  /* DUK_USE_STRTAB_TORTURE && DUK__STRTAB_RESIZE_CHECK */
54852 
54853 /*
54854  *  Raw intern; string already checked not to be present.
54855  */
54856 
54857 DUK_LOCAL duk_hstring *duk__strtable_do_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
54858 	duk_hstring *res;
54859 	const duk_uint8_t *extdata;
54860 #if defined(DUK_USE_STRTAB_PTRCOMP)
54861 	duk_uint16_t *slot;
54862 #else
54863 	duk_hstring **slot;
54864 #endif
54865 
54866 	DUK_DDD(DUK_DDDPRINT("do_intern: heap=%p, str=%p, blen=%lu, strhash=%lx, st_size=%lu, st_count=%lu, load=%lf",
54867 	                     (void *) heap, (const void *) str, (unsigned long) blen, (unsigned long) strhash,
54868 	                     (unsigned long) heap->st_size, (unsigned long) heap->st_count,
54869 	                     (double) heap->st_count / (double) heap->st_size));
54870 
54871 	DUK_ASSERT(heap != NULL);
54872 
54873 	/* Prevent any side effects on the string table and the caller provided
54874 	 * str/blen arguments while interning is in progress.  For example, if
54875 	 * the caller provided str/blen from a dynamic buffer, a finalizer
54876 	 * might resize or modify that dynamic buffer, invalidating the call
54877 	 * arguments.
54878 	 *
54879 	 * While finalizers must be prevented, mark-and-sweep itself is fine.
54880 	 * Recursive string table resize is prevented explicitly here.
54881 	 */
54882 
54883 	heap->pf_prevent_count++;
54884 	DUK_ASSERT(heap->pf_prevent_count != 0);  /* Wrap. */
54885 
54886 #if defined(DUK_USE_STRTAB_TORTURE) && defined(DUK__STRTAB_RESIZE_CHECK)
54887 	duk__strtable_resize_torture(heap);
54888 #endif
54889 
54890 	/* String table grow/shrink check.  Because of chaining (and no
54891 	 * accumulation issues as with hash probe chains and DELETED
54892 	 * markers) there's never a mandatory need to resize right now.
54893 	 * Check for the resize only periodically, based on st_count
54894 	 * bit pattern.  Because string table removal doesn't do a shrink
54895 	 * check, we do that also here.
54896 	 *
54897 	 * Do the resize and possible grow/shrink before the new duk_hstring
54898 	 * has been allocated.  Otherwise we may trigger a GC when the result
54899 	 * duk_hstring is not yet strongly referenced.
54900 	 */
54901 
54902 #if defined(DUK__STRTAB_RESIZE_CHECK)
54903 	if (DUK_UNLIKELY((heap->st_count & DUK_USE_STRTAB_RESIZE_CHECK_MASK) == 0)) {
54904 		duk__strtable_resize_check(heap);
54905 	}
54906 #endif
54907 
54908 	/* External string check (low memory optimization). */
54909 
54910 #if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
54911 	extdata = (const duk_uint8_t *) DUK_USE_EXTSTR_INTERN_CHECK(heap->heap_udata, (void *) DUK_LOSE_CONST(str), (duk_size_t) blen);
54912 #else
54913 	extdata = (const duk_uint8_t *) NULL;
54914 #endif
54915 
54916 	/* Allocate and initialize string, not yet linked.  This may cause a
54917 	 * GC which may cause other strings to be interned and inserted into
54918 	 * the string table before we insert our string.  Finalizer execution
54919 	 * is disabled intentionally to avoid a finalizer from e.g. resizing
54920 	 * a buffer used as a data area for 'str'.
54921 	 */
54922 
54923 	res = duk__strtable_alloc_hstring(heap, str, blen, strhash, extdata);
54924 
54925 	/* Allow side effects again: GC must be avoided until duk_hstring
54926 	 * result (if successful) has been INCREF'd.
54927 	 */
54928 	DUK_ASSERT(heap->pf_prevent_count > 0);
54929 	heap->pf_prevent_count--;
54930 
54931 	/* Alloc error handling. */
54932 
54933 	if (DUK_UNLIKELY(res == NULL)) {
54934 #if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
54935 		if (extdata != NULL) {
54936 			DUK_USE_EXTSTR_FREE(heap->heap_udata, (const void *) extdata);
54937 		}
54938 #endif
54939 		return NULL;
54940 	}
54941 
54942 	/* Insert into string table. */
54943 
54944 #if defined(DUK_USE_STRTAB_PTRCOMP)
54945 	slot = heap->strtable16 + (strhash & heap->st_mask);
54946 #else
54947 	slot = heap->strtable + (strhash & heap->st_mask);
54948 #endif
54949 	DUK_ASSERT(res->hdr.h_next == NULL);  /* This is the case now, but unnecessary zeroing/NULLing. */
54950 	res->hdr.h_next = DUK__HEAPPTR_DEC16(heap, *slot);
54951 	*slot = DUK__HEAPPTR_ENC16(heap, res);
54952 
54953 	/* Update string count only for successful inserts. */
54954 
54955 #if defined(DUK__STRTAB_RESIZE_CHECK)
54956 	heap->st_count++;
54957 #endif
54958 
54959 	/* The duk_hstring is in the string table but is not yet strongly
54960 	 * reachable.  Calling code MUST NOT make any allocations or other
54961 	 * side effects before the duk_hstring has been INCREF'd and made
54962 	 * reachable.
54963 	 */
54964 
54965 	return res;
54966 }
54967 
54968 /*
54969  *  Intern a string from str/blen, returning either an existing duk_hstring
54970  *  or adding a new one into the string table.  The input string does -not-
54971  *  need to be NUL terminated.
54972  *
54973  *  The input 'str' argument may point to a Duktape managed data area such as
54974  *  the data area of a dynamic buffer.  It's crucial to avoid any side effects
54975  *  that might affect the data area (e.g. resize the dynamic buffer, or write
54976  *  to the buffer) before the string is fully interned.
54977  */
54978 
54979 #if defined(DUK_USE_ROM_STRINGS)
54980 DUK_LOCAL duk_hstring *duk__strtab_romstring_lookup(duk_heap *heap, const duk_uint8_t *str, duk_size_t blen, duk_uint32_t strhash) {
54981 	duk_size_t lookup_hash;
54982 	duk_hstring *curr;
54983 
54984 	DUK_ASSERT(heap != NULL);
54985 	DUK_UNREF(heap);
54986 
54987 	lookup_hash = (blen << 4);
54988 	if (blen > 0) {
54989 		lookup_hash += str[0];
54990 	}
54991 	lookup_hash &= 0xff;
54992 
54993 	curr = (duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_lookup[lookup_hash]);
54994 	while (curr != NULL) {
54995 		/* Unsafe memcmp() because for zero blen, str may be NULL. */
54996 		if (strhash == DUK_HSTRING_GET_HASH(curr) &&
54997 		    blen == DUK_HSTRING_GET_BYTELEN(curr) &&
54998 		    duk_memcmp_unsafe((const void *) str, (const void *) DUK_HSTRING_GET_DATA(curr), blen) == 0) {
54999 			DUK_DDD(DUK_DDDPRINT("intern check: rom string: %!O, computed hash 0x%08lx, rom hash 0x%08lx",
55000 			                     curr, (unsigned long) strhash, (unsigned long) DUK_HSTRING_GET_HASH(curr)));
55001 			return curr;
55002 		}
55003 		curr = curr->hdr.h_next;
55004 	}
55005 
55006 	return NULL;
55007 }
55008 #endif  /* DUK_USE_ROM_STRINGS */
55009 
55010 DUK_INTERNAL duk_hstring *duk_heap_strtable_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen) {
55011 	duk_uint32_t strhash;
55012 	duk_hstring *h;
55013 
55014 	DUK_DDD(DUK_DDDPRINT("intern check: heap=%p, str=%p, blen=%lu", (void *) heap, (const void *) str, (unsigned long) blen));
55015 
55016 	/* Preliminaries. */
55017 
55018 	/* XXX: maybe just require 'str != NULL' even for zero size? */
55019 	DUK_ASSERT(heap != NULL);
55020 	DUK_ASSERT(blen == 0 || str != NULL);
55021 	DUK_ASSERT(blen <= DUK_HSTRING_MAX_BYTELEN);  /* Caller is responsible for ensuring this. */
55022 	strhash = duk_heap_hashstring(heap, str, (duk_size_t) blen);
55023 
55024 	/* String table lookup. */
55025 
55026 	DUK_ASSERT(DUK__GET_STRTABLE(heap) != NULL);
55027 	DUK_ASSERT(heap->st_size > 0);
55028 	DUK_ASSERT(heap->st_size == heap->st_mask + 1);
55029 #if defined(DUK_USE_STRTAB_PTRCOMP)
55030 	h = DUK__HEAPPTR_DEC16(heap, heap->strtable16[strhash & heap->st_mask]);
55031 #else
55032 	h = heap->strtable[strhash & heap->st_mask];
55033 #endif
55034 	while (h != NULL) {
55035 		if (DUK_HSTRING_GET_HASH(h) == strhash &&
55036 		    DUK_HSTRING_GET_BYTELEN(h) == blen &&
55037 		    duk_memcmp_unsafe((const void *) str, (const void *) DUK_HSTRING_GET_DATA(h), (size_t) blen) == 0) {
55038 			/* Found existing entry. */
55039 			DUK_STATS_INC(heap, stats_strtab_intern_hit);
55040 			return h;
55041 		}
55042 		h = h->hdr.h_next;
55043 	}
55044 
55045 	/* ROM table lookup.  Because this lookup is slower, do it only after
55046 	 * RAM lookup.  This works because no ROM string is ever interned into
55047 	 * the RAM string table.
55048 	 */
55049 
55050 #if defined(DUK_USE_ROM_STRINGS)
55051 	h = duk__strtab_romstring_lookup(heap, str, blen, strhash);
55052 	if (h != NULL) {
55053 		DUK_STATS_INC(heap, stats_strtab_intern_hit);
55054 		return h;
55055 	}
55056 #endif
55057 
55058 	/* Not found in string table; insert. */
55059 
55060 	DUK_STATS_INC(heap, stats_strtab_intern_miss);
55061 	h = duk__strtable_do_intern(heap, str, blen, strhash);
55062 	return h;  /* may be NULL */
55063 }
55064 
55065 /*
55066  *  Intern a string from u32.
55067  */
55068 
55069 /* XXX: Could arrange some special handling because we know that the result
55070  * will have an arridx flag and an ASCII flag, won't need a clen check, etc.
55071  */
55072 
55073 DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_u32(duk_heap *heap, duk_uint32_t val) {
55074 	duk_uint8_t buf[DUK__STRTAB_U32_MAX_STRLEN];
55075 	duk_uint8_t *p;
55076 
55077 	DUK_ASSERT(heap != NULL);
55078 
55079 	/* This is smaller and faster than a %lu sprintf. */
55080 	p = buf + sizeof(buf);
55081 	do {
55082 		p--;
55083 		*p = duk_lc_digits[val % 10];
55084 		val = val / 10;
55085 	} while (val != 0);  /* For val == 0, emit exactly one '0'. */
55086 	DUK_ASSERT(p >= buf);
55087 
55088 	return duk_heap_strtable_intern(heap, (const duk_uint8_t *) p, (duk_uint32_t) ((buf + sizeof(buf)) - p));
55089 }
55090 
55091 /*
55092  *  Checked convenience variants.
55093  *
55094  *  XXX: Because the main use case is for the checked variants, make them the
55095  *  main functionality and provide a safe variant separately (it is only needed
55096  *  during heap init).  The problem with that is that longjmp state and error
55097  *  creation must already be possible to throw.
55098  */
55099 
55100 DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen) {
55101 	duk_hstring *res;
55102 
55103 	DUK_ASSERT(thr != NULL);
55104 	DUK_ASSERT(thr->heap != NULL);
55105 	DUK_ASSERT(blen == 0 || str != NULL);
55106 
55107 	res = duk_heap_strtable_intern(thr->heap, str, blen);
55108 	if (DUK_UNLIKELY(res == NULL)) {
55109 		DUK_ERROR_ALLOC_FAILED(thr);
55110 		DUK_WO_NORETURN(return NULL;);
55111 	}
55112 	return res;
55113 }
55114 
55115 #if defined(DUK_USE_LITCACHE_SIZE)
55116 DUK_LOCAL duk_uint_t duk__strtable_litcache_key(const duk_uint8_t *str, duk_uint32_t blen) {
55117 	duk_uintptr_t key;
55118 
55119 	DUK_ASSERT(DUK_USE_LITCACHE_SIZE > 0);
55120 	DUK_ASSERT(DUK_IS_POWER_OF_TWO((duk_uint_t) DUK_USE_LITCACHE_SIZE));
55121 
55122 	key = (duk_uintptr_t) blen ^ (duk_uintptr_t) str;
55123 	key &= (duk_uintptr_t) (DUK_USE_LITCACHE_SIZE - 1);  /* Assumes size is power of 2. */
55124 	/* Due to masking, cast is in 32-bit range. */
55125 	DUK_ASSERT(key <= DUK_UINT_MAX);
55126 	return (duk_uint_t) key;
55127 }
55128 
55129 DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_literal_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen) {
55130 	duk_uint_t key;
55131 	duk_litcache_entry *ent;
55132 	duk_hstring *h;
55133 
55134 	/* Fast path check: literal exists in literal cache. */
55135 	key = duk__strtable_litcache_key(str, blen);
55136 	ent = thr->heap->litcache + key;
55137 	if (ent->addr == str) {
55138 		DUK_DD(DUK_DDPRINT("intern check for cached, pinned literal: str=%p, blen=%ld -> duk_hstring %!O",
55139 		                   (const void *) str, (long) blen, (duk_heaphdr *) ent->h));
55140 		DUK_ASSERT(ent->h != NULL);
55141 		DUK_ASSERT(DUK_HSTRING_HAS_PINNED_LITERAL(ent->h));
55142 		DUK_STATS_INC(thr->heap, stats_strtab_litcache_hit);
55143 		return ent->h;
55144 	}
55145 
55146 	/* Intern and update (overwrite) cache entry. */
55147 	h = duk_heap_strtable_intern_checked(thr, str, blen);
55148 	ent->addr = str;
55149 	ent->h = h;
55150 	DUK_STATS_INC(thr->heap, stats_strtab_litcache_miss);
55151 
55152 	/* Pin the duk_hstring until the next mark-and-sweep.  This means
55153 	 * litcache entries don't need to be invalidated until the next
55154 	 * mark-and-sweep as their target duk_hstring is not freed before
55155 	 * the mark-and-sweep happens.  The pin remains even if the literal
55156 	 * cache entry is overwritten, and is still useful to avoid string
55157 	 * table traffic.
55158 	 */
55159 	if (!DUK_HSTRING_HAS_PINNED_LITERAL(h)) {
55160 		DUK_DD(DUK_DDPRINT("pin duk_hstring because it is a literal: %!O", (duk_heaphdr *) h));
55161 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h));
55162 		DUK_HSTRING_INCREF(thr, h);
55163 		DUK_HSTRING_SET_PINNED_LITERAL(h);
55164 		DUK_STATS_INC(thr->heap, stats_strtab_litcache_pin);
55165 	}
55166 
55167 	return h;
55168 }
55169 #endif  /* DUK_USE_LITCACHE_SIZE */
55170 
55171 DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_u32_checked(duk_hthread *thr, duk_uint32_t val) {
55172 	duk_hstring *res;
55173 
55174 	DUK_ASSERT(thr != NULL);
55175 	DUK_ASSERT(thr->heap != NULL);
55176 
55177 	res = duk_heap_strtable_intern_u32(thr->heap, val);
55178 	if (DUK_UNLIKELY(res == NULL)) {
55179 		DUK_ERROR_ALLOC_FAILED(thr);
55180 		DUK_WO_NORETURN(return NULL;);
55181 	}
55182 	return res;
55183 }
55184 
55185 /*
55186  *  Remove (unlink) a string from the string table.
55187  *
55188  *  Just unlinks the duk_hstring, leaving link pointers as garbage.
55189  *  Caller must free the string itself.
55190  */
55191 
55192 #if defined(DUK_USE_REFERENCE_COUNTING)
55193 /* Unlink without a 'prev' pointer. */
55194 DUK_INTERNAL void duk_heap_strtable_unlink(duk_heap *heap, duk_hstring *h) {
55195 #if defined(DUK_USE_STRTAB_PTRCOMP)
55196 	duk_uint16_t *slot;
55197 #else
55198 	duk_hstring **slot;
55199 #endif
55200 	duk_hstring *other;
55201 	duk_hstring *prev;
55202 
55203 	DUK_DDD(DUK_DDDPRINT("remove: heap=%p, h=%p, blen=%lu, strhash=%lx",
55204 	                     (void *) heap, (void *) h,
55205 	                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_BYTELEN(h) : 0),
55206 	                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_HASH(h) : 0)));
55207 
55208 	DUK_ASSERT(heap != NULL);
55209 	DUK_ASSERT(h != NULL);
55210 
55211 #if defined(DUK__STRTAB_RESIZE_CHECK)
55212 	DUK_ASSERT(heap->st_count > 0);
55213 	heap->st_count--;
55214 #endif
55215 
55216 #if defined(DUK_USE_STRTAB_PTRCOMP)
55217 	slot = heap->strtable16 + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
55218 #else
55219 	slot = heap->strtable + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
55220 #endif
55221 	other = DUK__HEAPPTR_DEC16(heap, *slot);
55222 	DUK_ASSERT(other != NULL);  /* At least argument string is in the chain. */
55223 
55224 	prev = NULL;
55225 	while (other != h) {
55226 		prev = other;
55227 		other = other->hdr.h_next;
55228 		DUK_ASSERT(other != NULL);  /* We'll eventually find 'h'. */
55229 	}
55230 	if (prev != NULL) {
55231 		/* Middle of list. */
55232 		prev->hdr.h_next = h->hdr.h_next;
55233 	} else {
55234 		/* Head of list. */
55235 		*slot = DUK__HEAPPTR_ENC16(heap, h->hdr.h_next);
55236 	}
55237 
55238 	/* There's no resize check on a string free.  The next string
55239 	 * intern will do one.
55240 	 */
55241 }
55242 #endif  /* DUK_USE_REFERENCE_COUNTING */
55243 
55244 /* Unlink with a 'prev' pointer. */
55245 DUK_INTERNAL void duk_heap_strtable_unlink_prev(duk_heap *heap, duk_hstring *h, duk_hstring *prev) {
55246 #if defined(DUK_USE_STRTAB_PTRCOMP)
55247 	duk_uint16_t *slot;
55248 #else
55249 	duk_hstring **slot;
55250 #endif
55251 
55252 	DUK_DDD(DUK_DDDPRINT("remove: heap=%p, prev=%p, h=%p, blen=%lu, strhash=%lx",
55253 	                     (void *) heap, (void *) prev, (void *) h,
55254 	                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_BYTELEN(h) : 0),
55255 	                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_HASH(h) : 0)));
55256 
55257 	DUK_ASSERT(heap != NULL);
55258 	DUK_ASSERT(h != NULL);
55259 	DUK_ASSERT(prev == NULL || prev->hdr.h_next == h);
55260 
55261 #if defined(DUK__STRTAB_RESIZE_CHECK)
55262 	DUK_ASSERT(heap->st_count > 0);
55263 	heap->st_count--;
55264 #endif
55265 
55266 	if (prev != NULL) {
55267 		/* Middle of list. */
55268 		prev->hdr.h_next = h->hdr.h_next;
55269 	} else {
55270 		/* Head of list. */
55271 #if defined(DUK_USE_STRTAB_PTRCOMP)
55272 		slot = heap->strtable16 + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
55273 #else
55274 		slot = heap->strtable + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
55275 #endif
55276 		DUK_ASSERT(DUK__HEAPPTR_DEC16(heap, *slot) == h);
55277 		*slot = DUK__HEAPPTR_ENC16(heap, h->hdr.h_next);
55278 	}
55279 }
55280 
55281 /*
55282  *  Force string table resize check in mark-and-sweep.
55283  */
55284 
55285 DUK_INTERNAL void duk_heap_strtable_force_resize(duk_heap *heap) {
55286 	/* Does only one grow/shrink step if needed.  The heap->st_resizing
55287 	 * flag protects against recursive resizing.
55288 	 */
55289 
55290 	DUK_ASSERT(heap != NULL);
55291 	DUK_UNREF(heap);
55292 
55293 #if defined(DUK__STRTAB_RESIZE_CHECK)
55294 #if defined(DUK_USE_STRTAB_PTRCOMP)
55295 	if (heap->strtable16 != NULL) {
55296 #else
55297 	if (heap->strtable != NULL) {
55298 #endif
55299 		duk__strtable_resize_check(heap);
55300 	}
55301 #endif
55302 }
55303 
55304 /*
55305  *  Free strings in the string table and the string table itself.
55306  */
55307 
55308 DUK_INTERNAL void duk_heap_strtable_free(duk_heap *heap) {
55309 #if defined(DUK_USE_STRTAB_PTRCOMP)
55310 	duk_uint16_t *strtable;
55311 	duk_uint16_t *st;
55312 #else
55313 	duk_hstring **strtable;
55314 	duk_hstring **st;
55315 #endif
55316 	duk_hstring *h;
55317 
55318 	DUK_ASSERT(heap != NULL);
55319 
55320 #if defined(DUK_USE_ASSERTIONS)
55321 	duk__strtable_assert_checks(heap);
55322 #endif
55323 
55324 	/* Strtable can be NULL if heap init fails.  However, in that case
55325 	 * heap->st_size is 0, so strtable == strtable_end and we skip the
55326 	 * loop without a special check.
55327 	 */
55328 	strtable = DUK__GET_STRTABLE(heap);
55329 	st = strtable + heap->st_size;
55330 	DUK_ASSERT(strtable != NULL || heap->st_size == 0);
55331 
55332 	while (strtable != st) {
55333 		--st;
55334 		h = DUK__HEAPPTR_DEC16(heap, *st);
55335 		while (h) {
55336 			duk_hstring *h_next;
55337 			h_next = h->hdr.h_next;
55338 
55339 			/* Strings may have inner refs (extdata) in some cases. */
55340 			duk_free_hstring(heap, h);
55341 
55342 			h = h_next;
55343 		}
55344 	}
55345 
55346 	DUK_FREE(heap, strtable);
55347 }
55348 
55349 /* automatic undefs */
55350 #undef DUK__GET_STRTABLE
55351 #undef DUK__HEAPPTR_DEC16
55352 #undef DUK__HEAPPTR_ENC16
55353 #undef DUK__STRTAB_U32_MAX_STRLEN
55354 /*
55355  *  duk_heaphdr assertion helpers
55356  */
55357 
55358 /* #include duk_internal.h -> already included */
55359 
55360 #if defined(DUK_USE_ASSERTIONS)
55361 
55362 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
55363 DUK_INTERNAL void duk_heaphdr_assert_links(duk_heap *heap, duk_heaphdr *h) {
55364 	DUK_UNREF(heap);
55365 	if (h != NULL) {
55366 		duk_heaphdr *h_prev, *h_next;
55367 		h_prev = DUK_HEAPHDR_GET_PREV(heap, h);
55368 		h_next = DUK_HEAPHDR_GET_NEXT(heap, h);
55369 		DUK_ASSERT(h_prev == NULL || (DUK_HEAPHDR_GET_NEXT(heap, h_prev) == h));
55370 		DUK_ASSERT(h_next == NULL || (DUK_HEAPHDR_GET_PREV(heap, h_next) == h));
55371 	}
55372 }
55373 #else
55374 DUK_INTERNAL void duk_heaphdr_assert_links(duk_heap *heap, duk_heaphdr *h) {
55375 	DUK_UNREF(heap);
55376 	DUK_UNREF(h);
55377 }
55378 #endif
55379 
55380 DUK_INTERNAL void duk_heaphdr_assert_valid(duk_heaphdr *h) {
55381 	DUK_ASSERT(h != NULL);
55382 	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
55383 }
55384 
55385 /* Assert validity of a heaphdr, including all subclasses. */
55386 DUK_INTERNAL void duk_heaphdr_assert_valid_subclassed(duk_heaphdr *h) {
55387 	switch (DUK_HEAPHDR_GET_TYPE(h)) {
55388 	case DUK_HTYPE_OBJECT: {
55389 		duk_hobject *h_obj = (duk_hobject *) h;
55390 		DUK_HOBJECT_ASSERT_VALID(h_obj);
55391 		if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
55392 			DUK_HCOMPFUNC_ASSERT_VALID((duk_hcompfunc *) h_obj);
55393 		} else if (DUK_HOBJECT_IS_NATFUNC(h_obj)) {
55394 			DUK_HNATFUNC_ASSERT_VALID((duk_hnatfunc *) h_obj);
55395 		} else if (DUK_HOBJECT_IS_DECENV(h_obj)) {
55396 			DUK_HDECENV_ASSERT_VALID((duk_hdecenv *) h_obj);
55397 		} else if (DUK_HOBJECT_IS_OBJENV(h_obj)) {
55398 			DUK_HOBJENV_ASSERT_VALID((duk_hobjenv *) h_obj);
55399 		} else if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
55400 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
55401 			DUK_HBUFOBJ_ASSERT_VALID((duk_hbufobj *) h_obj);
55402 #endif
55403 		} else if (DUK_HOBJECT_IS_BOUNDFUNC(h_obj)) {
55404 			DUK_HBOUNDFUNC_ASSERT_VALID((duk_hboundfunc *) h_obj);
55405 		} else if (DUK_HOBJECT_IS_PROXY(h_obj)) {
55406 			DUK_HPROXY_ASSERT_VALID((duk_hproxy *) h_obj);
55407 		} else if (DUK_HOBJECT_IS_THREAD(h_obj)) {
55408 			DUK_HTHREAD_ASSERT_VALID((duk_hthread *) h_obj);
55409 		} else {
55410 			/* Just a plain object. */
55411 			;
55412 		}
55413 		break;
55414 	}
55415 	case DUK_HTYPE_STRING: {
55416 		duk_hstring *h_str = (duk_hstring *) h;
55417 		DUK_HSTRING_ASSERT_VALID(h_str);
55418 		break;
55419 	}
55420 	case DUK_HTYPE_BUFFER: {
55421 		duk_hbuffer *h_buf = (duk_hbuffer *) h;
55422 		DUK_HBUFFER_ASSERT_VALID(h_buf);
55423 		break;
55424 	}
55425 	default: {
55426 		DUK_ASSERT(0);
55427 	}
55428 	}
55429 }
55430 
55431 #endif  /* DUK_USE_ASSERTIONS */
55432 /*
55433  *  Hobject allocation.
55434  *
55435  *  Provides primitive allocation functions for all object types (plain object,
55436  *  compiled function, native function, thread).  The object return is not yet
55437  *  in "heap allocated" list and has a refcount of zero, so caller must careful.
55438  */
55439 
55440 /* XXX: In most cases there's no need for plain allocation without pushing
55441  * to the value stack.  Maybe rework contract?
55442  */
55443 
55444 /* #include duk_internal.h -> already included */
55445 
55446 /*
55447  *  Helpers.
55448  */
55449 
55450 DUK_LOCAL void duk__init_object_parts(duk_heap *heap, duk_uint_t hobject_flags, duk_hobject *obj) {
55451 	DUK_ASSERT(obj != NULL);
55452 	/* Zeroed by caller. */
55453 
55454 	obj->hdr.h_flags = hobject_flags | DUK_HTYPE_OBJECT;
55455 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(&obj->hdr) == DUK_HTYPE_OBJECT);  /* Assume zero shift. */
55456 
55457 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
55458 	DUK_HOBJECT_SET_PROTOTYPE(heap, obj, NULL);
55459 	DUK_HOBJECT_SET_PROPS(heap, obj, NULL);
55460 #endif
55461 #if defined(DUK_USE_HEAPPTR16)
55462 	/* Zero encoded pointer is required to match NULL. */
55463 	DUK_HEAPHDR_SET_NEXT(heap, &obj->hdr, NULL);
55464 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
55465 	DUK_HEAPHDR_SET_PREV(heap, &obj->hdr, NULL);
55466 #endif
55467 #endif
55468 	DUK_HEAPHDR_ASSERT_LINKS(heap, &obj->hdr);
55469 	DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &obj->hdr);
55470 
55471 	/* obj->props is intentionally left as NULL, and duk_hobject_props.c must deal
55472 	 * with this properly.  This is intentional: empty objects consume a minimum
55473 	 * amount of memory.  Further, an initial allocation might fail and cause
55474 	 * 'obj' to "leak" (require a mark-and-sweep) since it is not reachable yet.
55475 	 */
55476 }
55477 
55478 DUK_LOCAL void *duk__hobject_alloc_init(duk_hthread *thr, duk_uint_t hobject_flags, duk_size_t size) {
55479 	void *res;
55480 
55481 	res = (void *) DUK_ALLOC_CHECKED_ZEROED(thr, size);
55482 	DUK_ASSERT(res != NULL);
55483 	duk__init_object_parts(thr->heap, hobject_flags, (duk_hobject *) res);
55484 	return res;
55485 }
55486 
55487 /*
55488  *  Allocate an duk_hobject.
55489  *
55490  *  The allocated object has no allocation for properties; the caller may
55491  *  want to force a resize if a desired size is known.
55492  *
55493  *  The allocated object has zero reference count and is not reachable.
55494  *  The caller MUST make the object reachable and increase its reference
55495  *  count before invoking any operation that might require memory allocation.
55496  */
55497 
55498 DUK_INTERNAL duk_hobject *duk_hobject_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags) {
55499 	duk_hobject *res;
55500 
55501 	DUK_ASSERT(heap != NULL);
55502 
55503 	/* different memory layout, alloc size, and init */
55504 	DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_COMPFUNC) == 0);
55505 	DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_NATFUNC) == 0);
55506 	DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_BOUNDFUNC) == 0);
55507 
55508 	res = (duk_hobject *) DUK_ALLOC_ZEROED(heap, sizeof(duk_hobject));
55509 	if (DUK_UNLIKELY(res == NULL)) {
55510 		return NULL;
55511 	}
55512 	DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(res));
55513 
55514 	duk__init_object_parts(heap, hobject_flags, res);
55515 
55516 	DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(res));
55517 	return res;
55518 }
55519 
55520 DUK_INTERNAL duk_hobject *duk_hobject_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
55521 	duk_hobject *res;
55522 
55523 	res = (duk_hobject *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hobject));
55524 	return res;
55525 }
55526 
55527 DUK_INTERNAL duk_hcompfunc *duk_hcompfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
55528 	duk_hcompfunc *res;
55529 
55530 	res = (duk_hcompfunc *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hcompfunc));
55531 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
55532 #if defined(DUK_USE_HEAPPTR16)
55533 	/* NULL pointer is required to encode to zero, so memset is enough. */
55534 #else
55535 	res->data = NULL;
55536 	res->funcs = NULL;
55537 	res->bytecode = NULL;
55538 #endif
55539 	res->lex_env = NULL;
55540 	res->var_env = NULL;
55541 #endif
55542 
55543 	return res;
55544 }
55545 
55546 DUK_INTERNAL duk_hnatfunc *duk_hnatfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
55547 	duk_hnatfunc *res;
55548 
55549 	res = (duk_hnatfunc *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hnatfunc));
55550 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
55551 	res->func = NULL;
55552 #endif
55553 
55554 	return res;
55555 }
55556 
55557 DUK_INTERNAL duk_hboundfunc *duk_hboundfunc_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
55558 	duk_hboundfunc *res;
55559 
55560 	res = (duk_hboundfunc *) DUK_ALLOC(heap, sizeof(duk_hboundfunc));
55561 	if (!res) {
55562 		return NULL;
55563 	}
55564 	duk_memzero(res, sizeof(duk_hboundfunc));
55565 
55566 	duk__init_object_parts(heap, hobject_flags, &res->obj);
55567 
55568 	DUK_TVAL_SET_UNDEFINED(&res->target);
55569 	DUK_TVAL_SET_UNDEFINED(&res->this_binding);
55570 
55571 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
55572 	res->args = NULL;
55573 #endif
55574 
55575 	return res;
55576 }
55577 
55578 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
55579 DUK_INTERNAL duk_hbufobj *duk_hbufobj_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
55580 	duk_hbufobj *res;
55581 
55582 	res = (duk_hbufobj *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hbufobj));
55583 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
55584 	res->buf = NULL;
55585 	res->buf_prop = NULL;
55586 #endif
55587 
55588 	DUK_HBUFOBJ_ASSERT_VALID(res);
55589 	return res;
55590 }
55591 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
55592 
55593 /* Allocate a new thread.
55594  *
55595  * Leaves the built-ins array uninitialized.  The caller must either
55596  * initialize a new global context or share existing built-ins from
55597  * another thread.
55598  */
55599 DUK_INTERNAL duk_hthread *duk_hthread_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags) {
55600 	duk_hthread *res;
55601 
55602 	res = (duk_hthread *) DUK_ALLOC(heap, sizeof(duk_hthread));
55603 	if (DUK_UNLIKELY(res == NULL)) {
55604 		return NULL;
55605 	}
55606 	duk_memzero(res, sizeof(duk_hthread));
55607 
55608 	duk__init_object_parts(heap, hobject_flags, &res->obj);
55609 
55610 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
55611 	res->ptr_curr_pc = NULL;
55612 	res->heap = NULL;
55613 	res->valstack = NULL;
55614 	res->valstack_end = NULL;
55615 	res->valstack_alloc_end = NULL;
55616 	res->valstack_bottom = NULL;
55617 	res->valstack_top = NULL;
55618 	res->callstack_curr = NULL;
55619 	res->resumer = NULL;
55620 	res->compile_ctx = NULL,
55621 #if defined(DUK_USE_HEAPPTR16)
55622 	res->strs16 = NULL;
55623 #else
55624 	res->strs = NULL;
55625 #endif
55626 	{
55627 		duk_small_uint_t i;
55628 		for (i = 0; i < DUK_NUM_BUILTINS; i++) {
55629 			res->builtins[i] = NULL;
55630 		}
55631 	}
55632 #endif
55633 	/* When nothing is running, API calls are in non-strict mode. */
55634 	DUK_ASSERT(res->strict == 0);
55635 
55636 	res->heap = heap;
55637 
55638 	/* XXX: Any reason not to merge duk_hthread_alloc.c here? */
55639 	return res;
55640 }
55641 
55642 DUK_INTERNAL duk_hthread *duk_hthread_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
55643 	duk_hthread *res;
55644 
55645 	res = duk_hthread_alloc_unchecked(thr->heap, hobject_flags);
55646 	if (res == NULL) {
55647 		DUK_ERROR_ALLOC_FAILED(thr);
55648 		DUK_WO_NORETURN(return NULL;);
55649 	}
55650 	return res;
55651 }
55652 
55653 DUK_INTERNAL duk_harray *duk_harray_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
55654 	duk_harray *res;
55655 
55656 	res = (duk_harray *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_harray));
55657 
55658 	DUK_ASSERT(res->length == 0);
55659 
55660 	return res;
55661 }
55662 
55663 DUK_INTERNAL duk_hdecenv *duk_hdecenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
55664 	duk_hdecenv *res;
55665 
55666 	res = (duk_hdecenv *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hdecenv));
55667 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
55668 	res->thread = NULL;
55669 	res->varmap = NULL;
55670 #endif
55671 
55672 	DUK_ASSERT(res->thread == NULL);
55673 	DUK_ASSERT(res->varmap == NULL);
55674 	DUK_ASSERT(res->regbase_byteoff == 0);
55675 
55676 	return res;
55677 }
55678 
55679 DUK_INTERNAL duk_hobjenv *duk_hobjenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
55680 	duk_hobjenv *res;
55681 
55682 	res = (duk_hobjenv *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hobjenv));
55683 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
55684 	res->target = NULL;
55685 #endif
55686 
55687 	DUK_ASSERT(res->target == NULL);
55688 
55689 	return res;
55690 }
55691 
55692 DUK_INTERNAL duk_hproxy *duk_hproxy_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
55693 	duk_hproxy *res;
55694 
55695 	res = (duk_hproxy *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hproxy));
55696 
55697 	/* Leave ->target and ->handler uninitialized, as caller will always
55698 	 * explicitly initialize them before any side effects are possible.
55699 	 */
55700 
55701 	return res;
55702 }
55703 /*
55704  *  duk_hobject and subclass assertion helpers
55705  */
55706 
55707 /* #include duk_internal.h -> already included */
55708 
55709 #if defined(DUK_USE_ASSERTIONS)
55710 
55711 DUK_INTERNAL void duk_hobject_assert_valid(duk_hobject *h) {
55712 	DUK_ASSERT(h != NULL);
55713 	DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE(h) ||
55714 	           DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_FUNCTION);
55715 	DUK_ASSERT(!DUK_HOBJECT_IS_BUFOBJ(h) ||
55716 	           (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAYBUFFER ||
55717 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_DATAVIEW ||
55718 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_INT8ARRAY ||
55719 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_UINT8ARRAY ||
55720 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY ||
55721 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_INT16ARRAY ||
55722 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_UINT16ARRAY ||
55723 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_INT32ARRAY ||
55724 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_UINT32ARRAY ||
55725 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_FLOAT32ARRAY ||
55726 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_FLOAT64ARRAY));
55727 	/* Object is an Array <=> object has exotic array behavior */
55728 	DUK_ASSERT((DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY && DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)) ||
55729 	           (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_ARRAY && !DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)));
55730 }
55731 
55732 DUK_INTERNAL void duk_harray_assert_valid(duk_harray *h) {
55733 	DUK_ASSERT(h != NULL);
55734 	DUK_ASSERT(DUK_HOBJECT_IS_ARRAY((duk_hobject *) h));
55735 	DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY((duk_hobject *) h));
55736 }
55737 
55738 DUK_INTERNAL void duk_hboundfunc_assert_valid(duk_hboundfunc *h) {
55739 	DUK_ASSERT(h != NULL);
55740 	DUK_ASSERT(DUK_HOBJECT_IS_BOUNDFUNC((duk_hobject *) h));
55741 	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(&h->target) ||
55742 	           (DUK_TVAL_IS_OBJECT(&h->target) &&
55743 	            DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(&h->target))));
55744 	DUK_ASSERT(!DUK_TVAL_IS_UNUSED(&h->this_binding));
55745 	DUK_ASSERT(h->nargs == 0 || h->args != NULL);
55746 }
55747 
55748 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
55749 DUK_INTERNAL void duk_hbufobj_assert_valid(duk_hbufobj *h) {
55750 	DUK_ASSERT(h != NULL);
55751 	DUK_ASSERT(h->shift <= 3);
55752 	DUK_ASSERT(h->elem_type <= DUK_HBUFOBJ_ELEM_MAX);
55753 	DUK_ASSERT((h->shift == 0 && h->elem_type == DUK_HBUFOBJ_ELEM_UINT8) ||
55754 	           (h->shift == 0 && h->elem_type == DUK_HBUFOBJ_ELEM_UINT8CLAMPED) ||
55755 	           (h->shift == 0 && h->elem_type == DUK_HBUFOBJ_ELEM_INT8) ||
55756 	           (h->shift == 1 && h->elem_type == DUK_HBUFOBJ_ELEM_UINT16) ||
55757 	           (h->shift == 1 && h->elem_type == DUK_HBUFOBJ_ELEM_INT16) ||
55758 	           (h->shift == 2 && h->elem_type == DUK_HBUFOBJ_ELEM_UINT32) ||
55759 	           (h->shift == 2 && h->elem_type == DUK_HBUFOBJ_ELEM_INT32) ||
55760 	           (h->shift == 2 && h->elem_type == DUK_HBUFOBJ_ELEM_FLOAT32) ||
55761 	           (h->shift == 3 && h->elem_type == DUK_HBUFOBJ_ELEM_FLOAT64));
55762 	DUK_ASSERT(h->is_typedarray == 0 || h->is_typedarray == 1);
55763 	DUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) h));
55764 	if (h->buf == NULL) {
55765 		DUK_ASSERT(h->offset == 0);
55766 		DUK_ASSERT(h->length == 0);
55767 	} else {
55768 		/* No assertions for offset or length; in particular,
55769 		 * it's OK for length to be longer than underlying
55770 		 * buffer.  Just ensure they don't wrap when added.
55771 		 */
55772 		DUK_ASSERT(h->offset + h->length >= h->offset);
55773 	}
55774 }
55775 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
55776 
55777 DUK_INTERNAL void duk_hcompfunc_assert_valid(duk_hcompfunc *h) {
55778 	DUK_ASSERT(h != NULL);
55779 }
55780 
55781 DUK_INTERNAL void duk_hnatfunc_assert_valid(duk_hnatfunc *h) {
55782 	DUK_ASSERT(h != NULL);
55783 }
55784 
55785 DUK_INTERNAL void duk_hdecenv_assert_valid(duk_hdecenv *h) {
55786 	DUK_ASSERT(h != NULL);
55787 	DUK_ASSERT(DUK_HOBJECT_IS_DECENV((duk_hobject *) h));
55788 	DUK_ASSERT(h->thread == NULL || h->varmap != NULL);
55789 }
55790 
55791 DUK_INTERNAL void duk_hobjenv_assert_valid(duk_hobjenv *h) {
55792 	DUK_ASSERT(h != NULL);
55793 	DUK_ASSERT(DUK_HOBJECT_IS_OBJENV((duk_hobject *) h));
55794 	DUK_ASSERT(h->target != NULL);
55795 	DUK_ASSERT(h->has_this == 0 || h->has_this == 1);
55796 }
55797 
55798 DUK_INTERNAL void duk_hproxy_assert_valid(duk_hproxy *h) {
55799 	DUK_ASSERT(h != NULL);
55800 	DUK_ASSERT(h->target != NULL);
55801 	DUK_ASSERT(h->handler != NULL);
55802 	DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ((duk_hobject *) h));
55803 }
55804 
55805 DUK_INTERNAL void duk_hthread_assert_valid(duk_hthread *thr) {
55806 	DUK_ASSERT(thr != NULL);
55807 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) thr) == DUK_HTYPE_OBJECT);
55808 	DUK_ASSERT(DUK_HOBJECT_IS_THREAD((duk_hobject *) thr));
55809 	DUK_ASSERT(thr->unused1 == 0);
55810 	DUK_ASSERT(thr->unused2 == 0);
55811 }
55812 
55813 DUK_INTERNAL void duk_ctx_assert_valid(duk_hthread *thr) {
55814 	DUK_ASSERT(thr != NULL);
55815 	DUK_HTHREAD_ASSERT_VALID(thr);
55816 	DUK_ASSERT(thr->valstack != NULL);
55817 	DUK_ASSERT(thr->valstack_bottom != NULL);
55818 	DUK_ASSERT(thr->valstack_top != NULL);
55819 	DUK_ASSERT(thr->valstack_end != NULL);
55820 	DUK_ASSERT(thr->valstack_alloc_end != NULL);
55821 	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack);
55822 	DUK_ASSERT(thr->valstack_end >= thr->valstack);
55823 	DUK_ASSERT(thr->valstack_top >= thr->valstack);
55824 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
55825 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
55826 	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);
55827 }
55828 
55829 #endif  /* DUK_USE_ASSERTIONS */
55830 /*
55831  *  Object enumeration support.
55832  *
55833  *  Creates an internal enumeration state object to be used e.g. with for-in
55834  *  enumeration.  The state object contains a snapshot of target object keys
55835  *  and internal control state for enumeration.  Enumerator flags allow caller
55836  *  to e.g. request internal/non-enumerable properties, and to enumerate only
55837  *  "own" properties.
55838  *
55839  *  Also creates the result value for e.g. Object.keys() based on the same
55840  *  internal structure.
55841  *
55842  *  This snapshot-based enumeration approach is used to simplify enumeration:
55843  *  non-snapshot-based approaches are difficult to reconcile with mutating
55844  *  the enumeration target, running multiple long-lived enumerators at the
55845  *  same time, garbage collection details, etc.  The downside is that the
55846  *  enumerator object is memory inefficient especially for iterating arrays.
55847  */
55848 
55849 /* #include duk_internal.h -> already included */
55850 
55851 /* XXX: identify enumeration target with an object index (not top of stack) */
55852 
55853 /* First enumerated key index in enumerator object, must match exactly the
55854  * number of control properties inserted to the enumerator.
55855  */
55856 #define DUK__ENUM_START_INDEX  2
55857 
55858 /* Current implementation suffices for ES2015 for now because there's no symbol
55859  * sorting, so commented out for now.
55860  */
55861 
55862 /*
55863  *  Helper to sort enumeration keys using a callback for pairwise duk_hstring
55864  *  comparisons.  The keys are in the enumeration object entry part, starting
55865  *  from DUK__ENUM_START_INDEX, and the entry part is dense.  Entry part values
55866  *  are all "true", e.g. "1" -> true, "3" -> true, "foo" -> true, "2" -> true,
55867  *  so it suffices to just switch keys without switching values.
55868  *
55869  *  ES2015 [[OwnPropertyKeys]] enumeration order for ordinary objects:
55870  *  (1) array indices in ascending order,
55871  *  (2) non-array-index keys in insertion order, and
55872  *  (3) symbols in insertion order.
55873  *  http://www.ecma-international.org/ecma-262/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys.
55874  *
55875  *  This rule is applied to "own properties" at each inheritance level;
55876  *  non-duplicate parent keys always follow child keys.  For example,
55877  *  an inherited array index will enumerate -after- a symbol in the
55878  *  child.
55879  *
55880  *  Insertion sort is used because (1) it's simple and compact, (2) works
55881  *  in-place, (3) minimizes operations if data is already nearly sorted,
55882  *  (4) doesn't reorder elements considered equal.
55883  *  http://en.wikipedia.org/wiki/Insertion_sort
55884  */
55885 
55886 /* Sort key, must hold array indices, "not array index" marker, and one more
55887  * higher value for symbols.
55888  */
55889 #if !defined(DUK_USE_SYMBOL_BUILTIN)
55890 typedef duk_uint32_t duk__sort_key_t;
55891 #elif defined(DUK_USE_64BIT_OPS)
55892 typedef duk_uint64_t duk__sort_key_t;
55893 #else
55894 typedef duk_double_t duk__sort_key_t;
55895 #endif
55896 
55897 /* Get sort key for a duk_hstring. */
55898 DUK_LOCAL duk__sort_key_t duk__hstring_sort_key(duk_hstring *x) {
55899 	duk__sort_key_t val;
55900 
55901 	/* For array indices [0,0xfffffffe] use the array index as is.
55902 	 * For strings, use 0xffffffff, the marker 'arridx' already in
55903 	 * duk_hstring.  For symbols, any value above 0xffffffff works,
55904 	 * as long as it is the same for all symbols; currently just add
55905 	 * the masked flag field into the arridx temporary.
55906 	 */
55907 	DUK_ASSERT(x != NULL);
55908 	DUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(x) || DUK_HSTRING_GET_ARRIDX_FAST(x) == DUK_HSTRING_NO_ARRAY_INDEX);
55909 
55910 	val = (duk__sort_key_t) DUK_HSTRING_GET_ARRIDX_FAST(x);
55911 
55912 #if defined(DUK_USE_SYMBOL_BUILTIN)
55913 	val = val + (duk__sort_key_t) (DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) x) & DUK_HSTRING_FLAG_SYMBOL);
55914 #endif
55915 
55916 	return (duk__sort_key_t) val;
55917 }
55918 
55919 /* Insert element 'b' after element 'a'? */
55920 DUK_LOCAL duk_bool_t duk__sort_compare_es6(duk_hstring *a, duk_hstring *b, duk__sort_key_t val_b) {
55921 	duk__sort_key_t val_a;
55922 
55923 	DUK_ASSERT(a != NULL);
55924 	DUK_ASSERT(b != NULL);
55925 	DUK_UNREF(b);  /* Not actually needed now, val_b suffices. */
55926 
55927 	val_a = duk__hstring_sort_key(a);
55928 
55929 	if (val_a > val_b) {
55930 		return 0;
55931 	} else {
55932 		return 1;
55933 	}
55934 }
55935 
55936 DUK_LOCAL void duk__sort_enum_keys_es6(duk_hthread *thr, duk_hobject *h_obj, duk_int_fast32_t idx_start, duk_int_fast32_t idx_end) {
55937 	duk_hstring **keys;
55938 	duk_int_fast32_t idx;
55939 
55940 	DUK_ASSERT(h_obj != NULL);
55941 	DUK_ASSERT(idx_start >= DUK__ENUM_START_INDEX);
55942 	DUK_ASSERT(idx_end >= idx_start);
55943 	DUK_UNREF(thr);
55944 
55945 	if (idx_end <= idx_start + 1) {
55946 		return;  /* Zero or one element(s). */
55947 	}
55948 
55949 	keys = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, h_obj);
55950 
55951 	for (idx = idx_start + 1; idx < idx_end; idx++) {
55952 		duk_hstring *h_curr;
55953 		duk_int_fast32_t idx_insert;
55954 		duk__sort_key_t val_curr;
55955 
55956 		h_curr = keys[idx];
55957 		DUK_ASSERT(h_curr != NULL);
55958 
55959 		/* Scan backwards for insertion place.  This works very well
55960 		 * when the elements are nearly in order which is the common
55961 		 * (and optimized for) case.
55962 		 */
55963 
55964 		val_curr = duk__hstring_sort_key(h_curr);  /* Remains same during scanning. */
55965 		for (idx_insert = idx - 1; idx_insert >= idx_start; idx_insert--) {
55966 			duk_hstring *h_insert;
55967 			h_insert = keys[idx_insert];
55968 			DUK_ASSERT(h_insert != NULL);
55969 
55970 			if (duk__sort_compare_es6(h_insert, h_curr, val_curr)) {
55971 				break;
55972 			}
55973 		}
55974 		/* If we're out of indices, idx_insert == idx_start - 1 and idx_insert++
55975 		 * brings us back to idx_start.
55976 		 */
55977 		idx_insert++;
55978 		DUK_ASSERT(idx_insert >= 0 && idx_insert <= idx);
55979 
55980 		/*        .-- p_insert   .-- p_curr
55981 		 *        v              v
55982 		 *  | ... | insert | ... | curr
55983 		 */
55984 
55985 		/* This could also done when the keys are in order, i.e.
55986 		 * idx_insert == idx.  The result would be an unnecessary
55987 		 * memmove() but we use an explicit check because the keys
55988 		 * are very often in order already.
55989 		 */
55990 		if (idx != idx_insert) {
55991 			duk_memmove((void *) (keys + idx_insert + 1),
55992 			            (const void *) (keys + idx_insert),
55993 			            ((size_t) (idx - idx_insert) * sizeof(duk_hstring *)));
55994 			keys[idx_insert] = h_curr;
55995 		}
55996 	}
55997 
55998 	/* Entry part has been reordered now with no side effects.
55999 	 * If the object has a hash part, it will now be incorrect
56000 	 * and we need to rehash.  Do that by forcing a resize to
56001 	 * the current size.
56002 	 */
56003 	duk_hobject_resize_entrypart(thr, h_obj, DUK_HOBJECT_GET_ESIZE(h_obj));
56004 }
56005 
56006 /*
56007  *  Create an internal enumerator object E, which has its keys ordered
56008  *  to match desired enumeration ordering.  Also initialize internal control
56009  *  properties for enumeration.
56010  *
56011  *  Note: if an array was used to hold enumeration keys instead, an array
56012  *  scan would be needed to eliminate duplicates found in the prototype chain.
56013  */
56014 
56015 DUK_LOCAL void duk__add_enum_key(duk_hthread *thr, duk_hstring *k) {
56016 	/* 'k' may be unreachable on entry so must push without any
56017 	 * potential for GC.
56018 	 */
56019 	duk_push_hstring(thr, k);
56020 	duk_push_true(thr);
56021 	duk_put_prop(thr, -3);
56022 }
56023 
56024 DUK_LOCAL void duk__add_enum_key_stridx(duk_hthread *thr, duk_small_uint_t stridx) {
56025 	duk__add_enum_key(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
56026 }
56027 
56028 DUK_INTERNAL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint_t enum_flags) {
56029 	duk_hobject *enum_target;
56030 	duk_hobject *curr;
56031 	duk_hobject *res;
56032 #if defined(DUK_USE_ES6_PROXY)
56033 	duk_hobject *h_proxy_target;
56034 	duk_hobject *h_proxy_handler;
56035 	duk_hobject *h_trap_result;
56036 #endif
56037 	duk_uint_fast32_t i, len;  /* used for array, stack, and entry indices */
56038 	duk_uint_fast32_t sort_start_index;
56039 
56040 	DUK_ASSERT(thr != NULL);
56041 
56042 	enum_target = duk_require_hobject(thr, -1);
56043 	DUK_ASSERT(enum_target != NULL);
56044 
56045 	duk_push_bare_object(thr);
56046 	res = duk_known_hobject(thr, -1);
56047 
56048 	/* [enum_target res] */
56049 
56050 	/* Target must be stored so that we can recheck whether or not
56051 	 * keys still exist when we enumerate.  This is not done if the
56052 	 * enumeration result comes from a proxy trap as there is no
56053 	 * real object to check against.
56054 	 */
56055 	duk_push_hobject(thr, enum_target);
56056 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_INT_TARGET);  /* Target is bare, plain put OK. */
56057 
56058 	/* Initialize index so that we skip internal control keys. */
56059 	duk_push_int(thr, DUK__ENUM_START_INDEX);
56060 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_INT_NEXT);  /* Target is bare, plain put OK. */
56061 
56062 	/*
56063 	 *  Proxy object handling
56064 	 */
56065 
56066 #if defined(DUK_USE_ES6_PROXY)
56067 	if (DUK_LIKELY((enum_flags & DUK_ENUM_NO_PROXY_BEHAVIOR) != 0)) {
56068 		goto skip_proxy;
56069 	}
56070 	if (DUK_LIKELY(!duk_hobject_proxy_check(enum_target,
56071 	                                        &h_proxy_target,
56072 	                                        &h_proxy_handler))) {
56073 		goto skip_proxy;
56074 	}
56075 
56076 	/* XXX: share code with Object.keys() Proxy handling */
56077 
56078 	/* In ES2015 for-in invoked the "enumerate" trap; in ES2016 "enumerate"
56079 	 * has been obsoleted and "ownKeys" is used instead.
56080 	 */
56081 	DUK_DDD(DUK_DDDPRINT("proxy enumeration"));
56082 	duk_push_hobject(thr, h_proxy_handler);
56083 	if (!duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_OWN_KEYS)) {
56084 		/* No need to replace the 'enum_target' value in stack, only the
56085 		 * enum_target reference.  This also ensures that the original
56086 		 * enum target is reachable, which keeps the proxy and the proxy
56087 		 * target reachable.  We do need to replace the internal _Target.
56088 		 */
56089 		DUK_DDD(DUK_DDDPRINT("no ownKeys trap, enumerate proxy target instead"));
56090 		DUK_DDD(DUK_DDDPRINT("h_proxy_target=%!O", (duk_heaphdr *) h_proxy_target));
56091 		enum_target = h_proxy_target;
56092 
56093 		duk_push_hobject(thr, enum_target);  /* -> [ ... enum_target res handler undefined target ] */
56094 		duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_INT_TARGET);  /* Target is bare, plain put OK. */
56095 
56096 		duk_pop_2(thr);  /* -> [ ... enum_target res ] */
56097 		goto skip_proxy;
56098 	}
56099 
56100 	/* [ ... enum_target res handler trap ] */
56101 	duk_insert(thr, -2);
56102 	duk_push_hobject(thr, h_proxy_target);    /* -> [ ... enum_target res trap handler target ] */
56103 	duk_call_method(thr, 1 /*nargs*/);        /* -> [ ... enum_target res trap_result ] */
56104 	h_trap_result = duk_require_hobject(thr, -1);
56105 	DUK_UNREF(h_trap_result);
56106 
56107 	duk_proxy_ownkeys_postprocess(thr, h_proxy_target, enum_flags);
56108 	/* -> [ ... enum_target res trap_result keys_array ] */
56109 
56110 	/* Copy cleaned up trap result keys into the enumerator object. */
56111 	/* XXX: result is a dense array; could make use of that. */
56112 	DUK_ASSERT(duk_is_array(thr, -1));
56113 	len = (duk_uint_fast32_t) duk_get_length(thr, -1);
56114 	for (i = 0; i < len; i++) {
56115 		(void) duk_get_prop_index(thr, -1, (duk_uarridx_t) i);
56116 		DUK_ASSERT(duk_is_string(thr, -1));  /* postprocess cleaned up */
56117 		/* [ ... enum_target res trap_result keys_array val ] */
56118 		duk_push_true(thr);
56119 		/* [ ... enum_target res trap_result keys_array val true ] */
56120 		duk_put_prop(thr, -5);
56121 	}
56122 	/* [ ... enum_target res trap_result keys_array ] */
56123 	duk_pop_2(thr);
56124 	duk_remove_m2(thr);
56125 
56126 	/* [ ... res ] */
56127 
56128 	/* The internal _Target property is kept pointing to the original
56129 	 * enumeration target (the proxy object), so that the enumerator
56130 	 * 'next' operation can read property values if so requested.  The
56131 	 * fact that the _Target is a proxy disables key existence check
56132 	 * during enumeration.
56133 	 */
56134 	DUK_DDD(DUK_DDDPRINT("proxy enumeration, final res: %!O", (duk_heaphdr *) res));
56135 	goto compact_and_return;
56136 
56137  skip_proxy:
56138 #endif  /* DUK_USE_ES6_PROXY */
56139 
56140 	curr = enum_target;
56141 	sort_start_index = DUK__ENUM_START_INDEX;
56142 	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(res) == DUK__ENUM_START_INDEX);
56143 	while (curr) {
56144 		duk_uint_fast32_t sort_end_index;
56145 #if !defined(DUK_USE_PREFER_SIZE)
56146 		duk_bool_t need_sort = 0;
56147 #endif
56148 		duk_bool_t cond;
56149 
56150 		/* Enumeration proceeds by inheritance level.  Virtual
56151 		 * properties need to be handled specially, followed by
56152 		 * array part, and finally entry part.
56153 		 *
56154 		 * If there are array index keys in the entry part or any
56155 		 * other risk of the ES2015 [[OwnPropertyKeys]] order being
56156 		 * violated, need_sort is set and an explicit ES2015 sort is
56157 		 * done for the inheritance level.
56158 		 */
56159 
56160 		/* XXX: inheriting from proxy */
56161 
56162 		/*
56163 		 *  Virtual properties.
56164 		 *
56165 		 *  String and buffer indices are virtual and always enumerable,
56166 		 *  'length' is virtual and non-enumerable.  Array and arguments
56167 		 *  object props have special behavior but are concrete.
56168 		 *
56169 		 *  String and buffer objects don't have an array part so as long
56170 		 *  as virtual array index keys are enumerated first, we don't
56171 		 *  need to set need_sort.
56172 		 */
56173 
56174 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
56175 		cond = DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr) || DUK_HOBJECT_IS_BUFOBJ(curr);
56176 #else
56177 		cond = DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr);
56178 #endif
56179 		cond = cond && !(enum_flags & DUK_ENUM_EXCLUDE_STRINGS);
56180 		if (cond) {
56181 			duk_bool_t have_length = 1;
56182 
56183 			/* String and buffer enumeration behavior is identical now,
56184 			 * so use shared handler.
56185 			 */
56186 			if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr)) {
56187 				duk_hstring *h_val;
56188 				h_val = duk_hobject_get_internal_value_string(thr->heap, curr);
56189 				DUK_ASSERT(h_val != NULL);  /* string objects must not created without internal value */
56190 				len = (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h_val);
56191 			}
56192 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
56193 			else {
56194 				duk_hbufobj *h_bufobj;
56195 				DUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ(curr));
56196 				h_bufobj = (duk_hbufobj *) curr;
56197 
56198 				if (h_bufobj == NULL || !h_bufobj->is_typedarray) {
56199 					/* Zero length seems like a good behavior for neutered buffers.
56200 					 * ArrayBuffer (non-view) and DataView don't have index properties
56201 					 * or .length property.
56202 					 */
56203 					len = 0;
56204 					have_length = 0;
56205 				} else {
56206 					/* There's intentionally no check for
56207 					 * current underlying buffer length.
56208 					 */
56209 					len = (duk_uint_fast32_t) (h_bufobj->length >> h_bufobj->shift);
56210 				}
56211 			}
56212 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
56213 
56214 			for (i = 0; i < len; i++) {
56215 				duk_hstring *k;
56216 
56217 				/* This is a bit fragile: the string is not
56218 				 * reachable until it is pushed by the helper.
56219 				 */
56220 				k = duk_heap_strtable_intern_u32_checked(thr, (duk_uint32_t) i);
56221 				DUK_ASSERT(k);
56222 
56223 				duk__add_enum_key(thr, k);
56224 
56225 				/* [enum_target res] */
56226 			}
56227 
56228 			/* 'length' and other virtual properties are not
56229 			 * enumerable, but are included if non-enumerable
56230 			 * properties are requested.
56231 			 */
56232 
56233 			if (have_length && (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE)) {
56234 				duk__add_enum_key_stridx(thr, DUK_STRIDX_LENGTH);
56235 			}
56236 		}
56237 
56238 		/*
56239 		 *  Array part
56240 		 */
56241 
56242 		cond = !(enum_flags & DUK_ENUM_EXCLUDE_STRINGS);
56243 		if (cond) {
56244 			for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(curr); i++) {
56245 				duk_hstring *k;
56246 				duk_tval *tv;
56247 
56248 				tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, curr, i);
56249 				if (DUK_TVAL_IS_UNUSED(tv)) {
56250 					continue;
56251 				}
56252 				k = duk_heap_strtable_intern_u32_checked(thr, (duk_uint32_t) i);  /* Fragile reachability. */
56253 				DUK_ASSERT(k);
56254 
56255 				duk__add_enum_key(thr, k);
56256 
56257 				/* [enum_target res] */
56258 			}
56259 
56260 			if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(curr)) {
56261 				/* Array .length comes after numeric indices. */
56262 				if (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) {
56263 					duk__add_enum_key_stridx(thr, DUK_STRIDX_LENGTH);
56264 				}
56265 			}
56266 		}
56267 
56268 		/*
56269 		 *  Entries part
56270 		 */
56271 
56272 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(curr); i++) {
56273 			duk_hstring *k;
56274 
56275 			k = DUK_HOBJECT_E_GET_KEY(thr->heap, curr, i);
56276 			if (!k) {
56277 				continue;
56278 			}
56279 			if (!(enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) &&
56280 			    !DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(thr->heap, curr, i)) {
56281 				continue;
56282 			}
56283 			if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(k))) {
56284 				if (!(enum_flags & DUK_ENUM_INCLUDE_HIDDEN) &&
56285 				    DUK_HSTRING_HAS_HIDDEN(k)) {
56286 					continue;
56287 				}
56288 				if (!(enum_flags & DUK_ENUM_INCLUDE_SYMBOLS)) {
56289 					continue;
56290 				}
56291 #if !defined(DUK_USE_PREFER_SIZE)
56292 				need_sort = 1;
56293 #endif
56294 			} else {
56295 				DUK_ASSERT(!DUK_HSTRING_HAS_HIDDEN(k));  /* would also have symbol flag */
56296 				if (enum_flags & DUK_ENUM_EXCLUDE_STRINGS) {
56297 					continue;
56298 				}
56299 			}
56300 			if (DUK_HSTRING_HAS_ARRIDX(k)) {
56301 				/* This in currently only possible if the
56302 				 * object has no array part: the array part
56303 				 * is exhaustive when it is present.
56304 				 */
56305 #if !defined(DUK_USE_PREFER_SIZE)
56306 				need_sort = 1;
56307 #endif
56308 			} else {
56309 				if (enum_flags & DUK_ENUM_ARRAY_INDICES_ONLY) {
56310 					continue;
56311 				}
56312 			}
56313 
56314 			DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, curr, i) ||
56315 			           !DUK_TVAL_IS_UNUSED(&DUK_HOBJECT_E_GET_VALUE_PTR(thr->heap, curr, i)->v));
56316 
56317 			duk__add_enum_key(thr, k);
56318 
56319 			/* [enum_target res] */
56320 		}
56321 
56322 		/* Sort enumerated keys according to ES2015 requirements for
56323 		 * the "inheritance level" just processed.  This is far from
56324 		 * optimal, ES2015 semantics could be achieved more efficiently
56325 		 * by handling array index string keys (and symbol keys)
56326 		 * specially above in effect doing the sort inline.
56327 		 *
56328 		 * Skip the sort if array index sorting is requested because
56329 		 * we must consider all keys, also inherited, so an explicit
56330 		 * sort is done for the whole result after we're done with the
56331 		 * prototype chain.
56332 		 *
56333 		 * Also skip the sort if need_sort == 0, i.e. we know for
56334 		 * certain that the enumerated order is already correct.
56335 		 */
56336 		sort_end_index = DUK_HOBJECT_GET_ENEXT(res);
56337 
56338 		if (!(enum_flags & DUK_ENUM_SORT_ARRAY_INDICES)) {
56339 #if defined(DUK_USE_PREFER_SIZE)
56340 			duk__sort_enum_keys_es6(thr, res, (duk_int_fast32_t) sort_start_index, (duk_int_fast32_t) sort_end_index);
56341 #else
56342 			if (need_sort) {
56343 				DUK_DDD(DUK_DDDPRINT("need to sort"));
56344 				duk__sort_enum_keys_es6(thr, res, (duk_int_fast32_t) sort_start_index, (duk_int_fast32_t) sort_end_index);
56345 			} else {
56346 				DUK_DDD(DUK_DDDPRINT("no need to sort"));
56347 			}
56348 #endif
56349 		}
56350 
56351 		sort_start_index = sort_end_index;
56352 
56353 		if (enum_flags & DUK_ENUM_OWN_PROPERTIES_ONLY) {
56354 			break;
56355 		}
56356 
56357 		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
56358 	}
56359 
56360 	/* [enum_target res] */
56361 
56362 	duk_remove_m2(thr);
56363 
56364 	/* [res] */
56365 
56366 	if (enum_flags & DUK_ENUM_SORT_ARRAY_INDICES) {
56367 		/* Some E5/E5.1 algorithms require that array indices are iterated
56368 		 * in a strictly ascending order.  This is the case for e.g.
56369 		 * Array.prototype.forEach() and JSON.stringify() PropertyList
56370 		 * handling.  The caller can request an explicit sort in these
56371 		 * cases.
56372 		 */
56373 
56374 		/* Sort to ES2015 order which works for pure array incides but
56375 		 * also for mixed keys.
56376 		 */
56377 		duk__sort_enum_keys_es6(thr, res, (duk_int_fast32_t) DUK__ENUM_START_INDEX, (duk_int_fast32_t) DUK_HOBJECT_GET_ENEXT(res));
56378 	}
56379 
56380 #if defined(DUK_USE_ES6_PROXY)
56381  compact_and_return:
56382 #endif
56383 	/* compact; no need to seal because object is internal */
56384 	duk_hobject_compact_props(thr, res);
56385 
56386 	DUK_DDD(DUK_DDDPRINT("created enumerator object: %!iT", (duk_tval *) duk_get_tval(thr, -1)));
56387 }
56388 
56389 /*
56390  *  Returns non-zero if a key and/or value was enumerated, and:
56391  *
56392  *   [enum] -> [key]        (get_value == 0)
56393  *   [enum] -> [key value]  (get_value == 1)
56394  *
56395  *  Returns zero without pushing anything on the stack otherwise.
56396  */
56397 DUK_INTERNAL duk_bool_t duk_hobject_enumerator_next(duk_hthread *thr, duk_bool_t get_value) {
56398 	duk_hobject *e;
56399 	duk_hobject *enum_target;
56400 	duk_hstring *res = NULL;
56401 	duk_uint_fast32_t idx;
56402 	duk_bool_t check_existence;
56403 
56404 	DUK_ASSERT(thr != NULL);
56405 
56406 	/* [... enum] */
56407 
56408 	e = duk_require_hobject(thr, -1);
56409 
56410 	/* XXX use get tval ptr, more efficient */
56411 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_NEXT);
56412 	idx = (duk_uint_fast32_t) duk_require_uint(thr, -1);
56413 	duk_pop(thr);
56414 	DUK_DDD(DUK_DDDPRINT("enumeration: index is: %ld", (long) idx));
56415 
56416 	/* Enumeration keys are checked against the enumeration target (to see
56417 	 * that they still exist).  In the proxy enumeration case _Target will
56418 	 * be the proxy, and checking key existence against the proxy is not
56419 	 * required (or sensible, as the keys may be fully virtual).
56420 	 */
56421 	duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_TARGET);
56422 	enum_target = duk_require_hobject(thr, -1);
56423 	DUK_ASSERT(enum_target != NULL);
56424 #if defined(DUK_USE_ES6_PROXY)
56425 	check_existence = (!DUK_HOBJECT_IS_PROXY(enum_target));
56426 #else
56427 	check_existence = 1;
56428 #endif
56429 	duk_pop(thr);  /* still reachable */
56430 
56431 	DUK_DDD(DUK_DDDPRINT("getting next enum value, enum_target=%!iO, enumerator=%!iT",
56432 	                     (duk_heaphdr *) enum_target, (duk_tval *) duk_get_tval(thr, -1)));
56433 
56434 	/* no array part */
56435 	for (;;) {
56436 		duk_hstring *k;
56437 
56438 		if (idx >= DUK_HOBJECT_GET_ENEXT(e)) {
56439 			DUK_DDD(DUK_DDDPRINT("enumeration: ran out of elements"));
56440 			break;
56441 		}
56442 
56443 		/* we know these because enum objects are internally created */
56444 		k = DUK_HOBJECT_E_GET_KEY(thr->heap, e, idx);
56445 		DUK_ASSERT(k != NULL);
56446 		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, e, idx));
56447 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(&DUK_HOBJECT_E_GET_VALUE(thr->heap, e, idx).v));
56448 
56449 		idx++;
56450 
56451 		/* recheck that the property still exists */
56452 		if (check_existence && !duk_hobject_hasprop_raw(thr, enum_target, k)) {
56453 			DUK_DDD(DUK_DDDPRINT("property deleted during enumeration, skip"));
56454 			continue;
56455 		}
56456 
56457 		DUK_DDD(DUK_DDDPRINT("enumeration: found element, key: %!O", (duk_heaphdr *) k));
56458 		res = k;
56459 		break;
56460 	}
56461 
56462 	DUK_DDD(DUK_DDDPRINT("enumeration: updating next index to %ld", (long) idx));
56463 
56464 	duk_push_u32(thr, (duk_uint32_t) idx);
56465 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_INT_NEXT);
56466 
56467 	/* [... enum] */
56468 
56469 	if (res) {
56470 		duk_push_hstring(thr, res);
56471 		if (get_value) {
56472 			duk_push_hobject(thr, enum_target);
56473 			duk_dup_m2(thr);       /* -> [... enum key enum_target key] */
56474 			duk_get_prop(thr, -2); /* -> [... enum key enum_target val] */
56475 			duk_remove_m2(thr);    /* -> [... enum key val] */
56476 			duk_remove(thr, -3);   /* -> [... key val] */
56477 		} else {
56478 			duk_remove_m2(thr);    /* -> [... key] */
56479 		}
56480 		return 1;
56481 	} else {
56482 		duk_pop(thr);  /* -> [...] */
56483 		return 0;
56484 	}
56485 }
56486 
56487 /*
56488  *  Get enumerated keys in an ECMAScript array.  Matches Object.keys() behavior
56489  *  described in E5 Section 15.2.3.14.
56490  */
56491 
56492 DUK_INTERNAL duk_ret_t duk_hobject_get_enumerated_keys(duk_hthread *thr, duk_small_uint_t enum_flags) {
56493 	duk_hobject *e;
56494 	duk_hstring **keys;
56495 	duk_tval *tv;
56496 	duk_uint_fast32_t count;
56497 
56498 	DUK_ASSERT(thr != NULL);
56499 	DUK_ASSERT(duk_get_hobject(thr, -1) != NULL);
56500 
56501 	/* Create a temporary enumerator to get the (non-duplicated) key list;
56502 	 * the enumerator state is initialized without being needed, but that
56503 	 * has little impact.
56504 	 */
56505 
56506 	duk_hobject_enumerator_create(thr, enum_flags);
56507 	e = duk_known_hobject(thr, -1);
56508 
56509 	/* [enum_target enum res] */
56510 
56511 	/* Create dense result array to exact size. */
56512 	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(e) >= DUK__ENUM_START_INDEX);
56513 	count = (duk_uint32_t) (DUK_HOBJECT_GET_ENEXT(e) - DUK__ENUM_START_INDEX);
56514 
56515 	/* XXX: uninit would be OK */
56516 	tv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) count);
56517 	DUK_ASSERT(count == 0 || tv != NULL);
56518 	DUK_ASSERT(!duk_is_bare_object(thr, -1));
56519 
56520 	/* Fill result array, no side effects. */
56521 
56522 	keys = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, e);
56523 	keys += DUK__ENUM_START_INDEX;
56524 
56525 	while (count-- > 0) {
56526 		duk_hstring *k;
56527 
56528 		k = *keys++;
56529 		DUK_ASSERT(k != NULL);  /* enumerator must have no keys deleted */
56530 
56531 		DUK_TVAL_SET_STRING(tv, k);
56532 		tv++;
56533 		DUK_HSTRING_INCREF(thr, k);
56534 	}
56535 
56536 	/* [enum_target enum res] */
56537 	duk_remove_m2(thr);
56538 
56539 	/* [enum_target res] */
56540 
56541 	return 1;  /* return 1 to allow callers to tail call */
56542 }
56543 
56544 /* automatic undefs */
56545 #undef DUK__ENUM_START_INDEX
56546 /*
56547  *  Misc support functions
56548  */
56549 
56550 /* #include duk_internal.h -> already included */
56551 
56552 DUK_INTERNAL duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *thr, duk_hobject *h, duk_hobject *p, duk_bool_t ignore_loop) {
56553 	duk_uint_t sanity;
56554 
56555 	DUK_ASSERT(thr != NULL);
56556 
56557 	/* False if the object is NULL or the prototype 'p' is NULL.
56558 	 * In particular, false if both are NULL (don't compare equal).
56559 	 */
56560 	if (h == NULL || p == NULL) {
56561 		return 0;
56562 	}
56563 
56564 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
56565 	do {
56566 		if (h == p) {
56567 			return 1;
56568 		}
56569 
56570 		if (sanity-- == 0) {
56571 			if (ignore_loop) {
56572 				break;
56573 			} else {
56574 				DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
56575 				DUK_WO_NORETURN(return 0;);
56576 			}
56577 		}
56578 		h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
56579 	} while (h);
56580 
56581 	return 0;
56582 }
56583 
56584 DUK_INTERNAL void duk_hobject_set_prototype_updref(duk_hthread *thr, duk_hobject *h, duk_hobject *p) {
56585 #if defined(DUK_USE_REFERENCE_COUNTING)
56586 	duk_hobject *tmp;
56587 
56588 	DUK_ASSERT(h);
56589 	tmp = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
56590 	DUK_HOBJECT_SET_PROTOTYPE(thr->heap, h, p);
56591 	DUK_HOBJECT_INCREF_ALLOWNULL(thr, p);  /* avoid problems if p == h->prototype */
56592 	DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
56593 #else
56594 	DUK_ASSERT(h);
56595 	DUK_UNREF(thr);
56596 	DUK_HOBJECT_SET_PROTOTYPE(thr->heap, h, p);
56597 #endif
56598 }
56599 /*
56600  *  Helpers for creating and querying pc2line debug data, which
56601  *  converts a bytecode program counter to a source line number.
56602  *
56603  *  The run-time pc2line data is bit-packed, and documented in:
56604  *
56605  *    doc/function-objects.rst
56606  */
56607 
56608 /* #include duk_internal.h -> already included */
56609 
56610 #if defined(DUK_USE_PC2LINE)
56611 
56612 /* Generate pc2line data for an instruction sequence, leaving a buffer on stack top. */
56613 DUK_INTERNAL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_uint_fast32_t length) {
56614 	duk_hbuffer_dynamic *h_buf;
56615 	duk_bitencoder_ctx be_ctx_alloc;
56616 	duk_bitencoder_ctx *be_ctx = &be_ctx_alloc;
56617 	duk_uint32_t *hdr;
56618 	duk_size_t new_size;
56619 	duk_uint_fast32_t num_header_entries;
56620 	duk_uint_fast32_t curr_offset;
56621 	duk_int_fast32_t curr_line, next_line, diff_line;
56622 	duk_uint_fast32_t curr_pc;
56623 	duk_uint_fast32_t hdr_index;
56624 
56625 	DUK_ASSERT(length <= DUK_COMPILER_MAX_BYTECODE_LENGTH);
56626 
56627 	num_header_entries = (length + DUK_PC2LINE_SKIP - 1) / DUK_PC2LINE_SKIP;
56628 	curr_offset = (duk_uint_fast32_t) (sizeof(duk_uint32_t) + num_header_entries * sizeof(duk_uint32_t) * 2);
56629 
56630 	duk_push_dynamic_buffer(thr, (duk_size_t) curr_offset);
56631 	h_buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, -1);
56632 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h_buf) && !DUK_HBUFFER_HAS_EXTERNAL(h_buf));
56633 
56634 	hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf);
56635 	DUK_ASSERT(hdr != NULL);
56636 	hdr[0] = (duk_uint32_t) length;  /* valid pc range is [0, length[ */
56637 
56638 	curr_pc = 0U;
56639 	while (curr_pc < length) {
56640 		new_size = (duk_size_t) (curr_offset + DUK_PC2LINE_MAX_DIFF_LENGTH);
56641 		duk_hbuffer_resize(thr, h_buf, new_size);
56642 
56643 		hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf);
56644 		DUK_ASSERT(hdr != NULL);
56645 		DUK_ASSERT(curr_pc < length);
56646 		hdr_index = 1 + (curr_pc / DUK_PC2LINE_SKIP) * 2;
56647 		curr_line = (duk_int_fast32_t) instrs[curr_pc].line;
56648 		hdr[hdr_index + 0] = (duk_uint32_t) curr_line;
56649 		hdr[hdr_index + 1] = (duk_uint32_t) curr_offset;
56650 
56651 #if 0
56652 		DUK_DDD(DUK_DDDPRINT("hdr[%ld]: pc=%ld line=%ld offset=%ld",
56653 		                     (long) (curr_pc / DUK_PC2LINE_SKIP),
56654 		                     (long) curr_pc,
56655 		                     (long) hdr[hdr_index + 0],
56656 		                     (long) hdr[hdr_index + 1]));
56657 #endif
56658 
56659 		duk_memzero(be_ctx, sizeof(*be_ctx));
56660 		be_ctx->data = ((duk_uint8_t *) hdr) + curr_offset;
56661 		be_ctx->length = (duk_size_t) DUK_PC2LINE_MAX_DIFF_LENGTH;
56662 
56663 		for (;;) {
56664 			curr_pc++;
56665 			if ( ((curr_pc % DUK_PC2LINE_SKIP) == 0) ||  /* end of diff run */
56666 			     (curr_pc >= length) ) {                 /* end of bytecode */
56667 				break;
56668 			}
56669 			DUK_ASSERT(curr_pc < length);
56670 			next_line = (duk_int32_t) instrs[curr_pc].line;
56671 			diff_line = next_line - curr_line;
56672 
56673 #if 0
56674 			DUK_DDD(DUK_DDDPRINT("curr_line=%ld, next_line=%ld -> diff_line=%ld",
56675 			                     (long) curr_line, (long) next_line, (long) diff_line));
56676 #endif
56677 
56678 			if (diff_line == 0) {
56679 				/* 0 */
56680 				duk_be_encode(be_ctx, 0, 1);
56681 			} else if (diff_line >= 1 && diff_line <= 4) {
56682 				/* 1 0 <2 bits> */
56683 				duk_be_encode(be_ctx, (duk_uint32_t) ((0x02 << 2) + (diff_line - 1)), 4);
56684 			} else if (diff_line >= -0x80 && diff_line <= 0x7f) {
56685 				/* 1 1 0 <8 bits> */
56686 				DUK_ASSERT(diff_line + 0x80 >= 0 && diff_line + 0x80 <= 0xff);
56687 				duk_be_encode(be_ctx, (duk_uint32_t) ((0x06 << 8) + (diff_line + 0x80)), 11);
56688 			} else {
56689 				/* 1 1 1 <32 bits>
56690 				 * Encode in two parts to avoid bitencode 24-bit limitation
56691 				 */
56692 				duk_be_encode(be_ctx, (duk_uint32_t) ((0x07 << 16) + ((next_line >> 16) & 0xffff)), 19);
56693 				duk_be_encode(be_ctx, (duk_uint32_t) (next_line & 0xffff), 16);
56694 			}
56695 
56696 			curr_line = next_line;
56697 		}
56698 
56699 		duk_be_finish(be_ctx);
56700 		DUK_ASSERT(!be_ctx->truncated);
56701 
56702 		/* be_ctx->offset == length of encoded bitstream */
56703 		curr_offset += (duk_uint_fast32_t) be_ctx->offset;
56704 	}
56705 
56706 	/* compact */
56707 	new_size = (duk_size_t) curr_offset;
56708 	duk_hbuffer_resize(thr, h_buf, new_size);
56709 
56710 	(void) duk_to_fixed_buffer(thr, -1, NULL);
56711 
56712 	DUK_DDD(DUK_DDDPRINT("final pc2line data: pc_limit=%ld, length=%ld, %lf bits/opcode --> %!ixT",
56713 	                     (long) length, (long) new_size, (double) new_size * 8.0 / (double) length,
56714 	                     (duk_tval *) duk_get_tval(thr, -1)));
56715 }
56716 
56717 /* PC is unsigned.  If caller does PC arithmetic and gets a negative result,
56718  * it will map to a large PC which is out of bounds and causes a zero to be
56719  * returned.
56720  */
56721 DUK_LOCAL duk_uint_fast32_t duk__hobject_pc2line_query_raw(duk_hthread *thr, duk_hbuffer_fixed *buf, duk_uint_fast32_t pc) {
56722 	duk_bitdecoder_ctx bd_ctx_alloc;
56723 	duk_bitdecoder_ctx *bd_ctx = &bd_ctx_alloc;
56724 	duk_uint32_t *hdr;
56725 	duk_uint_fast32_t start_offset;
56726 	duk_uint_fast32_t pc_limit;
56727 	duk_uint_fast32_t hdr_index;
56728 	duk_uint_fast32_t pc_base;
56729 	duk_uint_fast32_t n;
56730 	duk_uint_fast32_t curr_line;
56731 
56732 	DUK_ASSERT(buf != NULL);
56733 	DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) buf) && !DUK_HBUFFER_HAS_EXTERNAL((duk_hbuffer *) buf));
56734 	DUK_UNREF(thr);
56735 
56736 	/*
56737 	 *  Use the index in the header to find the right starting point
56738 	 */
56739 
56740 	hdr_index = pc / DUK_PC2LINE_SKIP;
56741 	pc_base = hdr_index * DUK_PC2LINE_SKIP;
56742 	n = pc - pc_base;
56743 
56744 	if (DUK_HBUFFER_FIXED_GET_SIZE(buf) <= sizeof(duk_uint32_t)) {
56745 		DUK_DD(DUK_DDPRINT("pc2line lookup failed: buffer is smaller than minimal header"));
56746 		goto pc2line_error;
56747 	}
56748 
56749 	hdr = (duk_uint32_t *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, buf);
56750 	pc_limit = hdr[0];
56751 	if (pc >= pc_limit) {
56752 		/* Note: pc is unsigned and cannot be negative */
56753 		DUK_DD(DUK_DDPRINT("pc2line lookup failed: pc out of bounds (pc=%ld, limit=%ld)",
56754 		                   (long) pc, (long) pc_limit));
56755 		goto pc2line_error;
56756 	}
56757 
56758 	curr_line = hdr[1 + hdr_index * 2];
56759 	start_offset = hdr[1 + hdr_index * 2 + 1];
56760 	if ((duk_size_t) start_offset > DUK_HBUFFER_FIXED_GET_SIZE(buf)) {
56761 		DUK_DD(DUK_DDPRINT("pc2line lookup failed: start_offset out of bounds (start_offset=%ld, buffer_size=%ld)",
56762 		                   (long) start_offset, (long) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) buf)));
56763 		goto pc2line_error;
56764 	}
56765 
56766 	/*
56767 	 *  Iterate the bitstream (line diffs) until PC is reached
56768 	 */
56769 
56770 	duk_memzero(bd_ctx, sizeof(*bd_ctx));
56771 	bd_ctx->data = ((duk_uint8_t *) hdr) + start_offset;
56772 	bd_ctx->length = (duk_size_t) (DUK_HBUFFER_FIXED_GET_SIZE(buf) - start_offset);
56773 
56774 #if 0
56775 	DUK_DDD(DUK_DDDPRINT("pc2line lookup: pc=%ld -> hdr_index=%ld, pc_base=%ld, n=%ld, start_offset=%ld",
56776 	                     (long) pc, (long) hdr_index, (long) pc_base, (long) n, (long) start_offset));
56777 #endif
56778 
56779 	while (n > 0) {
56780 #if 0
56781 		DUK_DDD(DUK_DDDPRINT("lookup: n=%ld, curr_line=%ld", (long) n, (long) curr_line));
56782 #endif
56783 
56784 		if (duk_bd_decode_flag(bd_ctx)) {
56785 			if (duk_bd_decode_flag(bd_ctx)) {
56786 				if (duk_bd_decode_flag(bd_ctx)) {
56787 					/* 1 1 1 <32 bits> */
56788 					duk_uint_fast32_t t;
56789 					t = duk_bd_decode(bd_ctx, 16);  /* workaround: max nbits = 24 now */
56790 					t = (t << 16) + duk_bd_decode(bd_ctx, 16);
56791 					curr_line = t;
56792 				} else {
56793 					/* 1 1 0 <8 bits> */
56794 					duk_uint_fast32_t t;
56795 					t = duk_bd_decode(bd_ctx, 8);
56796 					curr_line = curr_line + t - 0x80;
56797 				}
56798 			} else {
56799 				/* 1 0 <2 bits> */
56800 				duk_uint_fast32_t t;
56801 				t = duk_bd_decode(bd_ctx, 2);
56802 				curr_line = curr_line + t + 1;
56803 			}
56804 		} else {
56805 			/* 0: no change */
56806 		}
56807 
56808 		n--;
56809 	}
56810 
56811 	DUK_DDD(DUK_DDDPRINT("pc2line lookup result: pc %ld -> line %ld", (long) pc, (long) curr_line));
56812 	return curr_line;
56813 
56814  pc2line_error:
56815 	DUK_D(DUK_DPRINT("pc2line conversion failed for pc=%ld", (long) pc));
56816 	return 0;
56817 }
56818 
56819 DUK_INTERNAL duk_uint_fast32_t duk_hobject_pc2line_query(duk_hthread *thr, duk_idx_t idx_func, duk_uint_fast32_t pc) {
56820 	duk_hbuffer_fixed *pc2line;
56821 	duk_uint_fast32_t line;
56822 
56823 	/* XXX: now that pc2line is used by the debugger quite heavily in
56824 	 * checked execution, this should be optimized to avoid value stack
56825 	 * and perhaps also implement some form of pc2line caching (see
56826 	 * future work in debugger.rst).
56827 	 */
56828 
56829 	duk_xget_owndataprop_stridx_short(thr, idx_func, DUK_STRIDX_INT_PC2LINE);
56830 	pc2line = (duk_hbuffer_fixed *) (void *) duk_get_hbuffer(thr, -1);
56831 	if (pc2line != NULL) {
56832 		DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) pc2line) && !DUK_HBUFFER_HAS_EXTERNAL((duk_hbuffer *) pc2line));
56833 		line = duk__hobject_pc2line_query_raw(thr, pc2line, (duk_uint_fast32_t) pc);
56834 	} else {
56835 		line = 0;
56836 	}
56837 	duk_pop(thr);
56838 
56839 	return line;
56840 }
56841 
56842 #endif  /* DUK_USE_PC2LINE */
56843 /*
56844  *  duk_hobject property access functionality.
56845  *
56846  *  This is very central functionality for size, performance, and compliance.
56847  *  It is also rather intricate; see hobject-algorithms.rst for discussion on
56848  *  the algorithms and memory-management.rst for discussion on refcounts and
56849  *  side effect issues.
56850  *
56851  *  Notes:
56852  *
56853  *    - It might be tempting to assert "refcount nonzero" for objects
56854  *      being operated on, but that's not always correct: objects with
56855  *      a zero refcount may be operated on by the refcount implementation
56856  *      (finalization) for instance.  Hence, no refcount assertions are made.
56857  *
56858  *    - Many operations (memory allocation, identifier operations, etc)
56859  *      may cause arbitrary side effects (e.g. through GC and finalization).
56860  *      These side effects may invalidate duk_tval pointers which point to
56861  *      areas subject to reallocation (like value stack).  Heap objects
56862  *      themselves have stable pointers.  Holding heap object pointers or
56863  *      duk_tval copies is not problematic with respect to side effects;
56864  *      care must be taken when holding and using argument duk_tval pointers.
56865  *
56866  *    - If a finalizer is executed, it may operate on the same object
56867  *      we're currently dealing with.  For instance, the finalizer might
56868  *      delete a certain property which has already been looked up and
56869  *      confirmed to exist.  Ideally finalizers would be disabled if GC
56870  *      happens during property access.  At the moment property table realloc
56871  *      disables finalizers, and all DECREFs may cause arbitrary changes so
56872  *      handle DECREF carefully.
56873  *
56874  *    - The order of operations for a DECREF matters.  When DECREF is executed,
56875  *      the entire object graph must be consistent; note that a refzero may
56876  *      lead to a mark-and-sweep through a refcount finalizer.  Use NORZ macros
56877  *      and an explicit DUK_REFZERO_CHECK_xxx() if achieving correct order is hard.
56878  */
56879 
56880 /*
56881  *  XXX: array indices are mostly typed as duk_uint32_t here; duk_uarridx_t
56882  *  might be more appropriate.
56883  */
56884 
56885 /* #include duk_internal.h -> already included */
56886 
56887 /*
56888  *  Local defines
56889  */
56890 
56891 #define DUK__NO_ARRAY_INDEX             DUK_HSTRING_NO_ARRAY_INDEX
56892 
56893 /* Marker values for hash part. */
56894 #define DUK__HASH_UNUSED                DUK_HOBJECT_HASHIDX_UNUSED
56895 #define DUK__HASH_DELETED               DUK_HOBJECT_HASHIDX_DELETED
56896 
56897 /* Valstack space that suffices for all local calls, excluding any recursion
56898  * into ECMAScript or Duktape/C calls (Proxy, getters, etc).
56899  */
56900 #define DUK__VALSTACK_SPACE             10
56901 
56902 /* Valstack space allocated especially for proxy lookup which does a
56903  * recursive property lookup.
56904  */
56905 #define DUK__VALSTACK_PROXY_LOOKUP      20
56906 
56907 /*
56908  *  Local prototypes
56909  */
56910 
56911 DUK_LOCAL_DECL duk_bool_t duk__check_arguments_map_for_get(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc);
56912 DUK_LOCAL_DECL void duk__check_arguments_map_for_put(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc, duk_bool_t throw_flag);
56913 DUK_LOCAL_DECL void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc);
56914 
56915 DUK_LOCAL_DECL duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr, duk_hobject *obj, duk_uint32_t old_len, duk_uint32_t new_len, duk_bool_t force_flag, duk_uint32_t *out_result_len);
56916 DUK_LOCAL_DECL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *obj);
56917 
56918 DUK_LOCAL_DECL duk_bool_t duk__get_propdesc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags);
56919 DUK_LOCAL_DECL duk_bool_t duk__get_own_propdesc_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_uint32_t arr_idx, duk_propdesc *out_desc, duk_small_uint_t flags);
56920 
56921 DUK_LOCAL_DECL void duk__abandon_array_part(duk_hthread *thr, duk_hobject *obj);
56922 DUK_LOCAL_DECL void duk__grow_props_for_array_item(duk_hthread *thr, duk_hobject *obj, duk_uint32_t highest_arr_idx);
56923 
56924 /*
56925  *  Misc helpers
56926  */
56927 
56928 /* Convert a duk_tval number (caller checks) to a 32-bit index.  Returns
56929  * DUK__NO_ARRAY_INDEX if the number is not whole or not a valid array
56930  * index.
56931  */
56932 /* XXX: for fastints, could use a variant which assumes a double duk_tval
56933  * (and doesn't need to check for fastint again).
56934  */
56935 DUK_LOCAL duk_uint32_t duk__tval_number_to_arr_idx(duk_tval *tv) {
56936 	duk_double_t dbl;
56937 	duk_uint32_t idx;
56938 
56939 	DUK_ASSERT(tv != NULL);
56940 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
56941 
56942 	/* -0 is accepted here as index 0 because ToString(-0) == "0" which is
56943 	 * in canonical form and thus an array index.
56944 	 */
56945 	dbl = DUK_TVAL_GET_NUMBER(tv);
56946 	idx = (duk_uint32_t) dbl;
56947 	if (duk_double_equals((duk_double_t) idx, dbl)) {
56948 	        /* Is whole and within 32 bit range.  If the value happens to be 0xFFFFFFFF,
56949 		 * it's not a valid array index but will then match DUK__NO_ARRAY_INDEX.
56950 		 */
56951 		return idx;
56952 	}
56953 	return DUK__NO_ARRAY_INDEX;
56954 }
56955 
56956 #if defined(DUK_USE_FASTINT)
56957 /* Convert a duk_tval fastint (caller checks) to a 32-bit index. */
56958 DUK_LOCAL duk_uint32_t duk__tval_fastint_to_arr_idx(duk_tval *tv) {
56959 	duk_int64_t t;
56960 
56961 	DUK_ASSERT(tv != NULL);
56962 	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
56963 
56964 	t = DUK_TVAL_GET_FASTINT(tv);
56965 	if (((duk_uint64_t) t & ~DUK_U64_CONSTANT(0xffffffff)) != 0) {
56966 		/* Catches >0x100000000 and negative values. */
56967 		return DUK__NO_ARRAY_INDEX;
56968 	}
56969 
56970 	/* If the value happens to be 0xFFFFFFFF, it's not a valid array index
56971 	 * but will then match DUK__NO_ARRAY_INDEX.
56972 	 */
56973 	return (duk_uint32_t) t;
56974 }
56975 #endif  /* DUK_USE_FASTINT */
56976 
56977 /* Convert a duk_tval on the value stack (in a trusted index we don't validate)
56978  * to a string or symbol using ES2015 ToPropertyKey():
56979  * http://www.ecma-international.org/ecma-262/6.0/#sec-topropertykey.
56980  *
56981  * Also check if it's a valid array index and return that (or DUK__NO_ARRAY_INDEX
56982  * if not).
56983  */
56984 DUK_LOCAL duk_uint32_t duk__to_property_key(duk_hthread *thr, duk_idx_t idx, duk_hstring **out_h) {
56985 	duk_uint32_t arr_idx;
56986 	duk_hstring *h;
56987 	duk_tval *tv_dst;
56988 
56989 	DUK_ASSERT(thr != NULL);
56990 	DUK_ASSERT(out_h != NULL);
56991 	DUK_ASSERT(duk_is_valid_index(thr, idx));
56992 	DUK_ASSERT(idx < 0);
56993 
56994 	/* XXX: The revised ES2015 ToPropertyKey() handling (ES5.1 was just
56995 	 * ToString()) involves a ToPrimitive(), a symbol check, and finally
56996 	 * a ToString().  Figure out the best way to have a good fast path
56997 	 * but still be compliant and share code.
56998 	 */
56999 
57000 	tv_dst = DUK_GET_TVAL_NEGIDX(thr, idx);  /* intentionally unvalidated */
57001 	if (DUK_TVAL_IS_STRING(tv_dst)) {
57002 		/* Most important path: strings and plain symbols are used as
57003 		 * is.  For symbols the array index check below is unnecessary
57004 		 * (they're never valid array indices) but checking that the
57005 		 * string is a symbol would make the plain string path slower
57006 		 * unnecessarily.
57007 		 */
57008 		h = DUK_TVAL_GET_STRING(tv_dst);
57009 	} else {
57010 		h = duk_to_property_key_hstring(thr, idx);
57011 	}
57012 	DUK_ASSERT(h != NULL);
57013 	*out_h = h;
57014 
57015 	arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(h);
57016 	return arr_idx;
57017 }
57018 
57019 DUK_LOCAL duk_uint32_t duk__push_tval_to_property_key(duk_hthread *thr, duk_tval *tv_key, duk_hstring **out_h) {
57020 	duk_push_tval(thr, tv_key);  /* XXX: could use an unsafe push here */
57021 	return duk__to_property_key(thr, -1, out_h);
57022 }
57023 
57024 /* String is an own (virtual) property of a plain buffer. */
57025 DUK_LOCAL duk_bool_t duk__key_is_plain_buf_ownprop(duk_hthread *thr, duk_hbuffer *buf, duk_hstring *key, duk_uint32_t arr_idx) {
57026 	DUK_UNREF(thr);
57027 
57028 	/* Virtual index properties.  Checking explicitly for
57029 	 * 'arr_idx != DUK__NO_ARRAY_INDEX' is not necessary
57030 	 * because DUK__NO_ARRAY_INDEXi is always larger than
57031 	 * maximum allowed buffer size.
57032 	 */
57033 	DUK_ASSERT(DUK__NO_ARRAY_INDEX >= DUK_HBUFFER_GET_SIZE(buf));
57034 	if (arr_idx < DUK_HBUFFER_GET_SIZE(buf)) {
57035 		return 1;
57036 	}
57037 
57038 	/* Other virtual properties. */
57039 	return (key == DUK_HTHREAD_STRING_LENGTH(thr));
57040 }
57041 
57042 /*
57043  *  Helpers for managing property storage size
57044  */
57045 
57046 /* Get default hash part size for a certain entry part size. */
57047 #if defined(DUK_USE_HOBJECT_HASH_PART)
57048 DUK_LOCAL duk_uint32_t duk__get_default_h_size(duk_uint32_t e_size) {
57049 	DUK_ASSERT(e_size <= DUK_HOBJECT_MAX_PROPERTIES);
57050 
57051 	if (e_size >= DUK_USE_HOBJECT_HASH_PROP_LIMIT) {
57052 		duk_uint32_t res;
57053 		duk_uint32_t tmp;
57054 
57055 		/* Hash size should be 2^N where N is chosen so that 2^N is
57056 		 * larger than e_size.  Extra shifting is used to ensure hash
57057 		 * is relatively sparse.
57058 		 */
57059 		tmp = e_size;
57060 		res = 2;  /* Result will be 2 ** (N + 1). */
57061 		while (tmp >= 0x40) {
57062 			tmp >>= 6;
57063 			res <<= 6;
57064 		}
57065 		while (tmp != 0) {
57066 			tmp >>= 1;
57067 			res <<= 1;
57068 		}
57069 		DUK_ASSERT((DUK_HOBJECT_MAX_PROPERTIES << 2U) > DUK_HOBJECT_MAX_PROPERTIES);  /* Won't wrap, even shifted by 2. */
57070 		DUK_ASSERT(res > e_size);
57071 		return res;
57072 	} else {
57073 		return 0;
57074 	}
57075 }
57076 #endif  /* USE_PROP_HASH_PART */
57077 
57078 /* Get minimum entry part growth for a certain size. */
57079 DUK_LOCAL duk_uint32_t duk__get_min_grow_e(duk_uint32_t e_size) {
57080 	duk_uint32_t res;
57081 
57082 	res = (e_size + DUK_USE_HOBJECT_ENTRY_MINGROW_ADD) / DUK_USE_HOBJECT_ENTRY_MINGROW_DIVISOR;
57083 	DUK_ASSERT(res >= 1);  /* important for callers */
57084 	return res;
57085 }
57086 
57087 /* Get minimum array part growth for a certain size. */
57088 DUK_LOCAL duk_uint32_t duk__get_min_grow_a(duk_uint32_t a_size) {
57089 	duk_uint32_t res;
57090 
57091 	res = (a_size + DUK_USE_HOBJECT_ARRAY_MINGROW_ADD) / DUK_USE_HOBJECT_ARRAY_MINGROW_DIVISOR;
57092 	DUK_ASSERT(res >= 1);  /* important for callers */
57093 	return res;
57094 }
57095 
57096 /* Count actually used entry part entries (non-NULL keys). */
57097 DUK_LOCAL duk_uint32_t duk__count_used_e_keys(duk_hthread *thr, duk_hobject *obj) {
57098 	duk_uint_fast32_t i;
57099 	duk_uint_fast32_t n = 0;
57100 	duk_hstring **e;
57101 
57102 	DUK_ASSERT(obj != NULL);
57103 	DUK_UNREF(thr);
57104 
57105 	e = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, obj);
57106 	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
57107 		if (*e++) {
57108 			n++;
57109 		}
57110 	}
57111 	return (duk_uint32_t) n;
57112 }
57113 
57114 /* Count actually used array part entries and array minimum size.
57115  * NOTE: 'out_min_size' can be computed much faster by starting from the
57116  * end and breaking out early when finding first used entry, but this is
57117  * not needed now.
57118  */
57119 DUK_LOCAL void duk__compute_a_stats(duk_hthread *thr, duk_hobject *obj, duk_uint32_t *out_used, duk_uint32_t *out_min_size) {
57120 	duk_uint_fast32_t i;
57121 	duk_uint_fast32_t used = 0;
57122 	duk_uint_fast32_t highest_idx = (duk_uint_fast32_t) -1;  /* see below */
57123 	duk_tval *a;
57124 
57125 	DUK_ASSERT(obj != NULL);
57126 	DUK_ASSERT(out_used != NULL);
57127 	DUK_ASSERT(out_min_size != NULL);
57128 	DUK_UNREF(thr);
57129 
57130 	a = DUK_HOBJECT_A_GET_BASE(thr->heap, obj);
57131 	for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
57132 		duk_tval *tv = a++;
57133 		if (!DUK_TVAL_IS_UNUSED(tv)) {
57134 			used++;
57135 			highest_idx = i;
57136 		}
57137 	}
57138 
57139 	/* Initial value for highest_idx is -1 coerced to unsigned.  This
57140 	 * is a bit odd, but (highest_idx + 1) will then wrap to 0 below
57141 	 * for out_min_size as intended.
57142 	 */
57143 
57144 	*out_used = (duk_uint32_t) used;
57145 	*out_min_size = (duk_uint32_t) (highest_idx + 1);  /* 0 if no used entries */
57146 }
57147 
57148 /* Check array density and indicate whether or not the array part should be abandoned. */
57149 DUK_LOCAL duk_bool_t duk__abandon_array_density_check(duk_uint32_t a_used, duk_uint32_t a_size) {
57150 	/*
57151 	 *  Array abandon check; abandon if:
57152 	 *
57153 	 *    new_used / new_size < limit
57154 	 *    new_used < limit * new_size        || limit is 3 bits fixed point
57155 	 *    new_used < limit' / 8 * new_size   || *8
57156 	 *    8*new_used < limit' * new_size     || :8
57157 	 *    new_used < limit' * (new_size / 8)
57158 	 *
57159 	 *  Here, new_used = a_used, new_size = a_size.
57160 	 *
57161 	 *  Note: some callers use approximate values for a_used and/or a_size
57162 	 *  (e.g. dropping a '+1' term).  This doesn't affect the usefulness
57163 	 *  of the check, but may confuse debugging.
57164 	 */
57165 
57166 	return (a_used < DUK_USE_HOBJECT_ARRAY_ABANDON_LIMIT * (a_size >> 3));
57167 }
57168 
57169 /* Fast check for extending array: check whether or not a slow density check is required. */
57170 DUK_LOCAL duk_bool_t duk__abandon_array_slow_check_required(duk_uint32_t arr_idx, duk_uint32_t old_size) {
57171 	duk_uint32_t new_size_min;
57172 
57173 	/*
57174 	 *  In a fast check we assume old_size equals old_used (i.e., existing
57175 	 *  array is fully dense).
57176 	 *
57177 	 *  Slow check if:
57178 	 *
57179 	 *    (new_size - old_size) / old_size > limit
57180 	 *    new_size - old_size > limit * old_size
57181 	 *    new_size > (1 + limit) * old_size        || limit' is 3 bits fixed point
57182 	 *    new_size > (1 + (limit' / 8)) * old_size || * 8
57183 	 *    8 * new_size > (8 + limit') * old_size   || : 8
57184 	 *    new_size > (8 + limit') * (old_size / 8)
57185 	 *    new_size > limit'' * (old_size / 8)      || limit'' = 9 -> max 25% increase
57186 	 *    arr_idx + 1 > limit'' * (old_size / 8)
57187 	 *
57188 	 *  This check doesn't work well for small values, so old_size is rounded
57189 	 *  up for the check (and the '+ 1' of arr_idx can be ignored in practice):
57190 	 *
57191 	 *    arr_idx > limit'' * ((old_size + 7) / 8)
57192 	 */
57193 
57194 	new_size_min = arr_idx + 1;
57195 	return (new_size_min >= DUK_USE_HOBJECT_ARRAY_ABANDON_MINSIZE) &&
57196 	       (arr_idx > DUK_USE_HOBJECT_ARRAY_FAST_RESIZE_LIMIT * ((old_size + 7) >> 3));
57197 }
57198 
57199 DUK_LOCAL duk_bool_t duk__abandon_array_check(duk_hthread *thr, duk_uint32_t arr_idx, duk_hobject *obj) {
57200 	duk_uint32_t min_size;
57201 	duk_uint32_t old_used;
57202 	duk_uint32_t old_size;
57203 
57204 	if (!duk__abandon_array_slow_check_required(arr_idx, DUK_HOBJECT_GET_ASIZE(obj))) {
57205 		DUK_DDD(DUK_DDDPRINT("=> fast resize is OK"));
57206 		return 0;
57207 	}
57208 
57209 	duk__compute_a_stats(thr, obj, &old_used, &old_size);
57210 
57211 	DUK_DDD(DUK_DDDPRINT("abandon check, array stats: old_used=%ld, old_size=%ld, arr_idx=%ld",
57212 	                     (long) old_used, (long) old_size, (long) arr_idx));
57213 
57214 	min_size = arr_idx + 1;
57215 #if defined(DUK_USE_OBJSIZES16)
57216 	if (min_size > DUK_UINT16_MAX) {
57217 		goto do_abandon;
57218 	}
57219 #endif
57220 	DUK_UNREF(min_size);
57221 
57222 	/* Note: intentionally use approximations to shave a few instructions:
57223 	 *   a_used = old_used  (accurate: old_used + 1)
57224 	 *   a_size = arr_idx   (accurate: arr_idx + 1)
57225 	 */
57226 	if (duk__abandon_array_density_check(old_used, arr_idx)) {
57227 		DUK_DD(DUK_DDPRINT("write to new array entry beyond current length, "
57228 		                   "decided to abandon array part (would become too sparse)"));
57229 
57230 		/* Abandoning requires a props allocation resize and
57231 		 * 'rechecks' the valstack, invalidating any existing
57232 		 * valstack value pointers.
57233 		 */
57234 		goto do_abandon;
57235 	}
57236 
57237 	DUK_DDD(DUK_DDDPRINT("=> decided to keep array part"));
57238 	return 0;
57239 
57240  do_abandon:
57241 	duk__abandon_array_part(thr, obj);
57242 	DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(obj));
57243 	return 1;
57244 }
57245 
57246 DUK_LOCAL duk_tval *duk__obtain_arridx_slot_slowpath(duk_hthread *thr, duk_uint32_t arr_idx, duk_hobject *obj) {
57247 	/*
57248 	 *  Array needs to grow, but we don't want it becoming too sparse.
57249 	 *  If it were to become sparse, abandon array part, moving all
57250 	 *  array entries into the entries part (for good).
57251 	 *
57252 	 *  Since we don't keep track of actual density (used vs. size) of
57253 	 *  the array part, we need to estimate somehow.  The check is made
57254 	 *  in two parts:
57255 	 *
57256 	 *    - Check whether the resize need is small compared to the
57257 	 *      current size (relatively); if so, resize without further
57258 	 *      checking (essentially we assume that the original part is
57259 	 *      "dense" so that the result would be dense enough).
57260 	 *
57261 	 *    - Otherwise, compute the resize using an actual density
57262 	 *      measurement based on counting the used array entries.
57263 	 */
57264 
57265 	DUK_DDD(DUK_DDDPRINT("write to new array requires array resize, decide whether to do a "
57266 	                     "fast resize without abandon check (arr_idx=%ld, old_size=%ld)",
57267 	                     (long) arr_idx, (long) DUK_HOBJECT_GET_ASIZE(obj)));
57268 
57269 	if (DUK_UNLIKELY(duk__abandon_array_check(thr, arr_idx, obj) != 0)) {
57270 		DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(obj));
57271 		return NULL;
57272 	}
57273 
57274 	DUK_DD(DUK_DDPRINT("write to new array entry beyond current length, "
57275 	                   "decided to extend current allocation"));
57276 
57277 	/* In principle it's possible to run out of memory extending the
57278 	 * array but with the allocation going through if we were to abandon
57279 	 * the array part and try again.  In practice this should be rare
57280 	 * because abandoned arrays have a higher per-entry footprint.
57281 	 */
57282 
57283 	duk__grow_props_for_array_item(thr, obj, arr_idx);
57284 
57285 	DUK_ASSERT(DUK_HOBJECT_HAS_ARRAY_PART(obj));
57286 	DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(obj));
57287 	return DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
57288 }
57289 
57290 DUK_LOCAL DUK_INLINE duk_tval *duk__obtain_arridx_slot(duk_hthread *thr, duk_uint32_t arr_idx, duk_hobject *obj) {
57291 	if (DUK_LIKELY(arr_idx < DUK_HOBJECT_GET_ASIZE(obj))) {
57292 		return DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
57293 	} else {
57294 		return duk__obtain_arridx_slot_slowpath(thr, arr_idx, obj);
57295 	}
57296 }
57297 
57298 /*
57299  *  Proxy helpers
57300  */
57301 
57302 #if defined(DUK_USE_ES6_PROXY)
57303 DUK_INTERNAL duk_bool_t duk_hobject_proxy_check(duk_hobject *obj, duk_hobject **out_target, duk_hobject **out_handler) {
57304 	duk_hproxy *h_proxy;
57305 
57306 	DUK_ASSERT(obj != NULL);
57307 	DUK_ASSERT(out_target != NULL);
57308 	DUK_ASSERT(out_handler != NULL);
57309 
57310 	/* Caller doesn't need to check exotic proxy behavior (but does so for
57311 	 * some fast paths).
57312 	 */
57313 	if (DUK_LIKELY(!DUK_HOBJECT_IS_PROXY(obj))) {
57314 		return 0;
57315 	}
57316 	h_proxy = (duk_hproxy *) obj;
57317 	DUK_HPROXY_ASSERT_VALID(h_proxy);
57318 
57319 	DUK_ASSERT(h_proxy->handler != NULL);
57320 	DUK_ASSERT(h_proxy->target != NULL);
57321 	*out_handler = h_proxy->handler;
57322 	*out_target = h_proxy->target;
57323 
57324 	return 1;
57325 }
57326 #endif  /* DUK_USE_ES6_PROXY */
57327 
57328 /* Get Proxy target object.  If the argument is not a Proxy, return it as is.
57329  * If a Proxy is revoked, an error is thrown.
57330  */
57331 #if defined(DUK_USE_ES6_PROXY)
57332 DUK_INTERNAL duk_hobject *duk_hobject_resolve_proxy_target(duk_hobject *obj) {
57333 	DUK_ASSERT(obj != NULL);
57334 
57335 	/* Resolve Proxy targets until Proxy chain ends.  No explicit check for
57336 	 * a Proxy loop: user code cannot create such a loop (it would only be
57337 	 * possible by editing duk_hproxy references directly).
57338 	 */
57339 
57340 	while (DUK_HOBJECT_IS_PROXY(obj)) {
57341 		duk_hproxy *h_proxy;
57342 
57343 		h_proxy = (duk_hproxy *) obj;
57344 		DUK_HPROXY_ASSERT_VALID(h_proxy);
57345 		obj = h_proxy->target;
57346 		DUK_ASSERT(obj != NULL);
57347 	}
57348 
57349 	DUK_ASSERT(obj != NULL);
57350 	return obj;
57351 }
57352 #endif  /* DUK_USE_ES6_PROXY */
57353 
57354 #if defined(DUK_USE_ES6_PROXY)
57355 DUK_LOCAL duk_bool_t duk__proxy_check_prop(duk_hthread *thr, duk_hobject *obj, duk_small_uint_t stridx_trap, duk_tval *tv_key, duk_hobject **out_target) {
57356 	duk_hobject *h_handler;
57357 
57358 	DUK_ASSERT(thr != NULL);
57359 	DUK_ASSERT(obj != NULL);
57360 	DUK_ASSERT(tv_key != NULL);
57361 	DUK_ASSERT(out_target != NULL);
57362 
57363 	if (!duk_hobject_proxy_check(obj, out_target, &h_handler)) {
57364 		return 0;
57365 	}
57366 	DUK_ASSERT(*out_target != NULL);
57367 	DUK_ASSERT(h_handler != NULL);
57368 
57369 	/* XXX: At the moment Duktape accesses internal keys like _Finalizer using a
57370 	 * normal property set/get which would allow a proxy handler to interfere with
57371 	 * such behavior and to get access to internal key strings.  This is not a problem
57372 	 * as such because internal key strings can be created in other ways too (e.g.
57373 	 * through buffers).  The best fix is to change Duktape internal lookups to
57374 	 * skip proxy behavior.  Until that, internal property accesses bypass the
57375 	 * proxy and are applied to the target (as if the handler did not exist).
57376 	 * This has some side effects, see test-bi-proxy-internal-keys.js.
57377 	 */
57378 
57379 	if (DUK_TVAL_IS_STRING(tv_key)) {
57380 		duk_hstring *h_key = (duk_hstring *) DUK_TVAL_GET_STRING(tv_key);
57381 		DUK_ASSERT(h_key != NULL);
57382 		if (DUK_HSTRING_HAS_HIDDEN(h_key)) {
57383 			/* Symbol accesses must go through proxy lookup in ES2015.
57384 			 * Hidden symbols behave like Duktape 1.x internal keys
57385 			 * and currently won't.
57386 			 */
57387 			DUK_DDD(DUK_DDDPRINT("hidden key, skip proxy handler and apply to target"));
57388 			return 0;
57389 		}
57390 	}
57391 
57392 	/* The handler is looked up with a normal property lookup; it may be an
57393 	 * accessor or the handler object itself may be a proxy object.  If the
57394 	 * handler is a proxy, we need to extend the valstack as we make a
57395 	 * recursive proxy check without a function call in between (in fact
57396 	 * there is no limit to the potential recursion here).
57397 	 *
57398 	 * (For sanity, proxy creation rejects another proxy object as either
57399 	 * the handler or the target at the moment so recursive proxy cases
57400 	 * are not realized now.)
57401 	 */
57402 
57403 	/* XXX: C recursion limit if proxies are allowed as handler/target values */
57404 
57405 	duk_require_stack(thr, DUK__VALSTACK_PROXY_LOOKUP);
57406 	duk_push_hobject(thr, h_handler);
57407 	if (duk_get_prop_stridx_short(thr, -1, stridx_trap)) {
57408 		/* -> [ ... handler trap ] */
57409 		duk_insert(thr, -2);  /* -> [ ... trap handler ] */
57410 
57411 		/* stack prepped for func call: [ ... trap handler ] */
57412 		return 1;
57413 	} else {
57414 		duk_pop_2_unsafe(thr);
57415 		return 0;
57416 	}
57417 }
57418 #endif  /* DUK_USE_ES6_PROXY */
57419 
57420 /*
57421  *  Reallocate property allocation, moving properties to the new allocation.
57422  *
57423  *  Includes key compaction, rehashing, and can also optionally abandon
57424  *  the array part, 'migrating' array entries into the beginning of the
57425  *  new entry part.
57426  *
57427  *  There is no support for in-place reallocation or just compacting keys
57428  *  without resizing the property allocation.  This is intentional to keep
57429  *  code size minimal, but would be useful future work.
57430  *
57431  *  The implementation is relatively straightforward, except for the array
57432  *  abandonment process.  Array abandonment requires that new string keys
57433  *  are interned, which may trigger GC.  All keys interned so far must be
57434  *  reachable for GC at all times and correctly refcounted for; valstack is
57435  *  used for that now.
57436  *
57437  *  Also, a GC triggered during this reallocation process must not interfere
57438  *  with the object being resized.  This is currently controlled by preventing
57439  *  finalizers (as they may affect ANY object) and object compaction in
57440  *  mark-and-sweep.  It would suffice to protect only this particular object
57441  *  from compaction, however.  DECREF refzero cascades are side effect free
57442  *  and OK.
57443  *
57444  *  Note: because we need to potentially resize the valstack (as part
57445  *  of abandoning the array part), any tval pointers to the valstack
57446  *  will become invalid after this call.
57447  */
57448 
57449 DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
57450                                             duk_hobject *obj,
57451                                             duk_uint32_t new_e_size,
57452                                             duk_uint32_t new_a_size,
57453                                             duk_uint32_t new_h_size,
57454                                             duk_bool_t abandon_array) {
57455 	duk_small_uint_t prev_ms_base_flags;
57456 	duk_uint32_t new_alloc_size;
57457 	duk_uint32_t new_e_size_adjusted;
57458 	duk_uint8_t *new_p;
57459 	duk_hstring **new_e_k;
57460 	duk_propvalue *new_e_pv;
57461 	duk_uint8_t *new_e_f;
57462 	duk_tval *new_a;
57463 	duk_uint32_t *new_h;
57464 	duk_uint32_t new_e_next;
57465 	duk_uint_fast32_t i;
57466 	duk_size_t array_copy_size;
57467 #if defined(DUK_USE_ASSERTIONS)
57468 	duk_bool_t prev_error_not_allowed;
57469 #endif
57470 
57471 	DUK_ASSERT(thr != NULL);
57472 	DUK_ASSERT(obj != NULL);
57473 	DUK_ASSERT(!abandon_array || new_a_size == 0);  /* if abandon_array, new_a_size must be 0 */
57474 	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL || (DUK_HOBJECT_GET_ESIZE(obj) == 0 && DUK_HOBJECT_GET_ASIZE(obj) == 0));
57475 	DUK_ASSERT(new_h_size == 0 || new_h_size >= new_e_size);  /* required to guarantee success of rehashing,
57476 	                                                           * intentionally use unadjusted new_e_size
57477 	                                                           */
57478 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
57479 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
57480 
57481 	DUK_STATS_INC(thr->heap, stats_object_realloc_props);
57482 
57483 	/*
57484 	 *  Pre resize assertions.
57485 	 */
57486 
57487 #if defined(DUK_USE_ASSERTIONS)
57488 	/* XXX: pre-checks (such as no duplicate keys) */
57489 #endif
57490 
57491 	/*
57492 	 *  For property layout 1, tweak e_size to ensure that the whole entry
57493 	 *  part (key + val + flags) is a suitable multiple for alignment
57494 	 *  (platform specific).
57495 	 *
57496 	 *  Property layout 2 does not require this tweaking and is preferred
57497 	 *  on low RAM platforms requiring alignment.
57498 	 */
57499 
57500 #if defined(DUK_USE_HOBJECT_LAYOUT_2) || defined(DUK_USE_HOBJECT_LAYOUT_3)
57501 	DUK_DDD(DUK_DDDPRINT("using layout 2 or 3, no need to pad e_size: %ld", (long) new_e_size));
57502 	new_e_size_adjusted = new_e_size;
57503 #elif defined(DUK_USE_HOBJECT_LAYOUT_1) && (DUK_HOBJECT_ALIGN_TARGET == 1)
57504 	DUK_DDD(DUK_DDDPRINT("using layout 1, but no need to pad e_size: %ld", (long) new_e_size));
57505 	new_e_size_adjusted = new_e_size;
57506 #elif defined(DUK_USE_HOBJECT_LAYOUT_1) && ((DUK_HOBJECT_ALIGN_TARGET == 4) || (DUK_HOBJECT_ALIGN_TARGET == 8))
57507 	new_e_size_adjusted = (new_e_size + (duk_uint32_t) DUK_HOBJECT_ALIGN_TARGET - 1U) &
57508 	                      (~((duk_uint32_t) DUK_HOBJECT_ALIGN_TARGET - 1U));
57509 	DUK_DDD(DUK_DDDPRINT("using layout 1, and alignment target is %ld, adjusted e_size: %ld -> %ld",
57510 	                     (long) DUK_HOBJECT_ALIGN_TARGET, (long) new_e_size, (long) new_e_size_adjusted));
57511 	DUK_ASSERT(new_e_size_adjusted >= new_e_size);
57512 #else
57513 #error invalid hobject layout defines
57514 #endif
57515 
57516 	/*
57517 	 *  Debug logging after adjustment.
57518 	 */
57519 
57520 	DUK_DDD(DUK_DDDPRINT("attempt to resize hobject %p props (%ld -> %ld bytes), from {p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld} to "
57521 	                     "{e_size=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
57522 	                     (void *) obj,
57523 	                     (long) DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
57524 	                                                       DUK_HOBJECT_GET_ASIZE(obj),
57525 	                                                       DUK_HOBJECT_GET_HSIZE(obj)),
57526 	                     (long) DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size),
57527 	                     (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
57528 	                     (long) DUK_HOBJECT_GET_ESIZE(obj),
57529 	                     (long) DUK_HOBJECT_GET_ENEXT(obj),
57530 	                     (long) DUK_HOBJECT_GET_ASIZE(obj),
57531 	                     (long) DUK_HOBJECT_GET_HSIZE(obj),
57532 	                     (long) new_e_size_adjusted,
57533 	                     (long) new_a_size,
57534 	                     (long) new_h_size,
57535 	                     (long) abandon_array,
57536 	                     (long) new_e_size));
57537 
57538 	/*
57539 	 *  Property count check.  This is the only point where we ensure that
57540 	 *  we don't get more (allocated) property space that we can handle.
57541 	 *  There aren't hard limits as such, but some algorithms may fail
57542 	 *  if we get too close to the 4G property limit.
57543 	 *
57544 	 *  Since this works based on allocation size (not actually used size),
57545 	 *  the limit is a bit approximate but good enough in practice.
57546 	 */
57547 
57548 	if (new_e_size_adjusted + new_a_size > DUK_HOBJECT_MAX_PROPERTIES) {
57549 		DUK_ERROR_ALLOC_FAILED(thr);
57550 		DUK_WO_NORETURN(return;);
57551 	}
57552 #if defined(DUK_USE_OBJSIZES16)
57553 	if (new_e_size_adjusted > DUK_UINT16_MAX || new_a_size > DUK_UINT16_MAX) {
57554 		/* If caller gave us sizes larger than what we can store,
57555 		 * fail memory safely with an internal error rather than
57556 		 * truncating the sizes.
57557 		 */
57558 		DUK_ERROR_INTERNAL(thr);
57559 		DUK_WO_NORETURN(return;);
57560 	}
57561 #endif
57562 
57563 	/*
57564 	 *  Compute new alloc size and alloc new area.
57565 	 *
57566 	 *  The new area is not tracked in the heap at all, so it's critical
57567 	 *  we get to free/keep it in a controlled manner.
57568 	 */
57569 
57570 #if defined(DUK_USE_ASSERTIONS)
57571 	/* Whole path must be error throw free, but we may be called from
57572 	 * within error handling so can't assert for error_not_allowed == 0.
57573 	 */
57574 	prev_error_not_allowed = thr->heap->error_not_allowed;
57575 	thr->heap->error_not_allowed = 1;
57576 #endif
57577 	prev_ms_base_flags = thr->heap->ms_base_flags;
57578 	thr->heap->ms_base_flags |=
57579 	        DUK_MS_FLAG_NO_OBJECT_COMPACTION;      /* Avoid attempt to compact the current object (all objects really). */
57580 	thr->heap->pf_prevent_count++;                 /* Avoid finalizers. */
57581 	DUK_ASSERT(thr->heap->pf_prevent_count != 0);  /* Wrap. */
57582 
57583 	new_alloc_size = DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size);
57584 	DUK_DDD(DUK_DDDPRINT("new hobject allocation size is %ld", (long) new_alloc_size));
57585 	if (new_alloc_size == 0) {
57586 		DUK_ASSERT(new_e_size_adjusted == 0);
57587 		DUK_ASSERT(new_a_size == 0);
57588 		DUK_ASSERT(new_h_size == 0);
57589 		new_p = NULL;
57590 	} else {
57591 		/* Alloc may trigger mark-and-sweep but no compaction, and
57592 		 * cannot throw.
57593 		 */
57594 #if 0  /* XXX: inject test */
57595 		if (1) {
57596 			new_p = NULL;
57597 			goto alloc_failed;
57598 		}
57599 #endif
57600 		new_p = (duk_uint8_t *) DUK_ALLOC(thr->heap, new_alloc_size);
57601 		if (new_p == NULL) {
57602 			/* NULL always indicates alloc failure because
57603 			 * new_alloc_size > 0.
57604 			 */
57605 			goto alloc_failed;
57606 		}
57607 	}
57608 
57609 	/* Set up pointers to the new property area: this is hidden behind a macro
57610 	 * because it is memory layout specific.
57611 	 */
57612 	DUK_HOBJECT_P_SET_REALLOC_PTRS(new_p, new_e_k, new_e_pv, new_e_f, new_a, new_h,
57613 	                               new_e_size_adjusted, new_a_size, new_h_size);
57614 	DUK_UNREF(new_h);  /* happens when hash part dropped */
57615 	new_e_next = 0;
57616 
57617 	/* if new_p == NULL, all of these pointers are NULL */
57618 	DUK_ASSERT((new_p != NULL) ||
57619 	           (new_e_k == NULL && new_e_pv == NULL && new_e_f == NULL &&
57620 	            new_a == NULL && new_h == NULL));
57621 
57622 	DUK_DDD(DUK_DDDPRINT("new alloc size %ld, new_e_k=%p, new_e_pv=%p, new_e_f=%p, new_a=%p, new_h=%p",
57623 	                     (long) new_alloc_size, (void *) new_e_k, (void *) new_e_pv, (void *) new_e_f,
57624 	                     (void *) new_a, (void *) new_h));
57625 
57626 	/*
57627 	 *  Migrate array part to start of entries if requested.
57628 	 *
57629 	 *  Note: from an enumeration perspective the order of entry keys matters.
57630 	 *  Array keys should appear wherever they appeared before the array abandon
57631 	 *  operation.  (This no longer matters much because keys are ES2015 sorted.)
57632 	 */
57633 
57634 	if (abandon_array) {
57635 		/* Assuming new_a_size == 0, and that entry part contains
57636 		 * no conflicting keys, refcounts do not need to be adjusted for
57637 		 * the values, as they remain exactly the same.
57638 		 *
57639 		 * The keys, however, need to be interned, incref'd, and be
57640 		 * reachable for GC.  Any intern attempt may trigger a GC and
57641 		 * claim any non-reachable strings, so every key must be reachable
57642 		 * at all times.  Refcounts must be correct to satisfy refcount
57643 		 * assertions.
57644 		 *
57645 		 * A longjmp must not occur here, as the new_p allocation would
57646 		 * leak.  Refcounts would come out correctly as the interned
57647 		 * strings are valstack tracked.
57648 		 */
57649 		DUK_ASSERT(new_a_size == 0);
57650 
57651 		DUK_STATS_INC(thr->heap, stats_object_abandon_array);
57652 
57653 		for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
57654 			duk_tval *tv1;
57655 			duk_tval *tv2;
57656 			duk_hstring *key;
57657 
57658 			DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
57659 
57660 			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
57661 			if (DUK_TVAL_IS_UNUSED(tv1)) {
57662 				continue;
57663 			}
57664 
57665 			DUK_ASSERT(new_p != NULL && new_e_k != NULL &&
57666 			           new_e_pv != NULL && new_e_f != NULL);
57667 
57668 			/*
57669 			 *  Intern key via the valstack to ensure reachability behaves
57670 			 *  properly.  We must avoid longjmp's here so use non-checked
57671 			 *  primitives.
57672 			 *
57673 			 *  Note: duk_check_stack() potentially reallocs the valstack,
57674 			 *  invalidating any duk_tval pointers to valstack.  Callers
57675 			 *  must be careful.
57676 			 */
57677 
57678 #if 0  /* XXX: inject test */
57679 			if (1) {
57680 				goto abandon_error;
57681 			}
57682 #endif
57683 			/* Never shrinks; auto-adds DUK_VALSTACK_INTERNAL_EXTRA, which
57684 			 * is generous.
57685 			 */
57686 			if (!duk_check_stack(thr, 1)) {
57687 				goto abandon_error;
57688 			}
57689 			DUK_ASSERT_VALSTACK_SPACE(thr, 1);
57690 			key = duk_heap_strtable_intern_u32(thr->heap, (duk_uint32_t) i);
57691 			if (key == NULL) {
57692 				goto abandon_error;
57693 			}
57694 			duk_push_hstring(thr, key);  /* keep key reachable for GC etc; guaranteed not to fail */
57695 
57696 			/* Key is now reachable in the valstack, don't INCREF
57697 			 * the new allocation yet (we'll steal the refcounts
57698 			 * from the value stack once all keys are done).
57699 			 */
57700 
57701 			new_e_k[new_e_next] = key;
57702 			tv2 = &new_e_pv[new_e_next].v;  /* array entries are all plain values */
57703 			DUK_TVAL_SET_TVAL(tv2, tv1);
57704 			new_e_f[new_e_next] = DUK_PROPDESC_FLAG_WRITABLE |
57705 			                      DUK_PROPDESC_FLAG_ENUMERABLE |
57706 			                      DUK_PROPDESC_FLAG_CONFIGURABLE;
57707 			new_e_next++;
57708 
57709 			/* Note: new_e_next matches pushed temp key count, and nothing can
57710 			 * fail above between the push and this point.
57711 			 */
57712 		}
57713 
57714 		/* Steal refcounts from value stack. */
57715 		DUK_DDD(DUK_DDDPRINT("abandon array: pop %ld key temps from valstack", (long) new_e_next));
57716 		duk_pop_n_nodecref_unsafe(thr, (duk_idx_t) new_e_next);
57717 	}
57718 
57719 	/*
57720 	 *  Copy keys and values in the entry part (compacting them at the same time).
57721 	 */
57722 
57723 	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
57724 		duk_hstring *key;
57725 
57726 		DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
57727 
57728 		key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
57729 		if (key == NULL) {
57730 			continue;
57731 		}
57732 
57733 		DUK_ASSERT(new_p != NULL && new_e_k != NULL &&
57734 		           new_e_pv != NULL && new_e_f != NULL);
57735 
57736 		new_e_k[new_e_next] = key;
57737 		new_e_pv[new_e_next] = DUK_HOBJECT_E_GET_VALUE(thr->heap, obj, i);
57738 		new_e_f[new_e_next] = DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, i);
57739 		new_e_next++;
57740 	}
57741 	/* the entries [new_e_next, new_e_size_adjusted[ are left uninitialized on purpose (ok, not gc reachable) */
57742 
57743 	/*
57744 	 *  Copy array elements to new array part.  If the new array part is
57745 	 *  larger, initialize the unused entries as UNUSED because they are
57746 	 *  GC reachable.
57747 	 */
57748 
57749 #if defined(DUK_USE_ASSERTIONS)
57750 	/* Caller must have decref'd values above new_a_size (if that is necessary). */
57751 	if (!abandon_array) {
57752 		for (i = new_a_size; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
57753 			duk_tval *tv;
57754 			tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
57755 			DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv));
57756 		}
57757 	}
57758 #endif
57759 	if (new_a_size > DUK_HOBJECT_GET_ASIZE(obj)) {
57760 		array_copy_size = sizeof(duk_tval) * DUK_HOBJECT_GET_ASIZE(obj);
57761 	} else {
57762 		array_copy_size = sizeof(duk_tval) * new_a_size;
57763 	}
57764 
57765 	DUK_ASSERT(new_a != NULL || array_copy_size == 0U);
57766 	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL || array_copy_size == 0U);
57767 	DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(obj) > 0 || array_copy_size == 0U);
57768 	duk_memcpy_unsafe((void *) new_a,
57769 	                  (const void *) DUK_HOBJECT_A_GET_BASE(thr->heap, obj),
57770 	                  array_copy_size);
57771 
57772 	for (i = DUK_HOBJECT_GET_ASIZE(obj); i < new_a_size; i++) {
57773 		duk_tval *tv = &new_a[i];
57774 		DUK_TVAL_SET_UNUSED(tv);
57775 	}
57776 
57777 	/*
57778 	 *  Rebuild the hash part always from scratch (guaranteed to finish
57779 	 *  as long as caller gave consistent parameters).
57780 	 *
57781 	 *  Any resize of hash part requires rehashing.  In addition, by rehashing
57782 	 *  get rid of any elements marked deleted (DUK__HASH_DELETED) which is critical
57783 	 *  to ensuring the hash part never fills up.
57784 	 */
57785 
57786 #if defined(DUK_USE_HOBJECT_HASH_PART)
57787 	if (new_h_size == 0) {
57788 		DUK_DDD(DUK_DDDPRINT("no hash part, no rehash"));
57789 	} else {
57790 		duk_uint32_t mask;
57791 
57792 		DUK_ASSERT(new_h != NULL);
57793 
57794 		/* fill new_h with u32 0xff = UNUSED */
57795 		DUK_ASSERT(new_h_size > 0);
57796 		duk_memset(new_h, 0xff, sizeof(duk_uint32_t) * new_h_size);
57797 
57798 		DUK_ASSERT(new_e_next <= new_h_size);  /* equality not actually possible */
57799 
57800 		mask = new_h_size - 1;
57801 		for (i = 0; i < new_e_next; i++) {
57802 			duk_hstring *key = new_e_k[i];
57803 			duk_uint32_t j, step;
57804 
57805 			DUK_ASSERT(key != NULL);
57806 			j = DUK_HSTRING_GET_HASH(key) & mask;
57807 			step = 1;  /* Cache friendly but clustering prone. */
57808 
57809 			for (;;) {
57810 				DUK_ASSERT(new_h[j] != DUK__HASH_DELETED);  /* should never happen */
57811 				if (new_h[j] == DUK__HASH_UNUSED) {
57812 					DUK_DDD(DUK_DDDPRINT("rebuild hit %ld -> %ld", (long) j, (long) i));
57813 					new_h[j] = (duk_uint32_t) i;
57814 					break;
57815 				}
57816 				DUK_DDD(DUK_DDDPRINT("rebuild miss %ld, step %ld", (long) j, (long) step));
57817 				j = (j + step) & mask;
57818 
57819 				/* Guaranteed to finish (hash is larger than #props). */
57820 			}
57821 		}
57822 	}
57823 #endif  /* DUK_USE_HOBJECT_HASH_PART */
57824 
57825 	/*
57826 	 *  Nice debug log.
57827 	 */
57828 
57829 	DUK_DD(DUK_DDPRINT("resized hobject %p props (%ld -> %ld bytes), from {p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld} to "
57830 	                   "{p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
57831 	                   (void *) obj,
57832 	                   (long) DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
57833 	                                                     DUK_HOBJECT_GET_ASIZE(obj),
57834 	                                                     DUK_HOBJECT_GET_HSIZE(obj)),
57835 	                   (long) new_alloc_size,
57836 	                   (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
57837 	                   (long) DUK_HOBJECT_GET_ESIZE(obj),
57838 	                   (long) DUK_HOBJECT_GET_ENEXT(obj),
57839 	                   (long) DUK_HOBJECT_GET_ASIZE(obj),
57840 	                   (long) DUK_HOBJECT_GET_HSIZE(obj),
57841 	                   (void *) new_p,
57842 	                   (long) new_e_size_adjusted,
57843 	                   (long) new_e_next,
57844 	                   (long) new_a_size,
57845 	                   (long) new_h_size,
57846 	                   (long) abandon_array,
57847 	                   (long) new_e_size));
57848 
57849 	/*
57850 	 *  All done, switch properties ('p') allocation to new one.
57851 	 */
57852 
57853 	DUK_FREE_CHECKED(thr, DUK_HOBJECT_GET_PROPS(thr->heap, obj));  /* NULL obj->p is OK */
57854 	DUK_HOBJECT_SET_PROPS(thr->heap, obj, new_p);
57855 	DUK_HOBJECT_SET_ESIZE(obj, new_e_size_adjusted);
57856 	DUK_HOBJECT_SET_ENEXT(obj, new_e_next);
57857 	DUK_HOBJECT_SET_ASIZE(obj, new_a_size);
57858 	DUK_HOBJECT_SET_HSIZE(obj, new_h_size);
57859 
57860 	/* Clear array part flag only after switching. */
57861 	if (abandon_array) {
57862 		DUK_HOBJECT_CLEAR_ARRAY_PART(obj);
57863 	}
57864 
57865 	DUK_DDD(DUK_DDDPRINT("resize result: %!O", (duk_heaphdr *) obj));
57866 
57867 	DUK_ASSERT(thr->heap->pf_prevent_count > 0);
57868 	thr->heap->pf_prevent_count--;
57869 	thr->heap->ms_base_flags = prev_ms_base_flags;
57870 #if defined(DUK_USE_ASSERTIONS)
57871 	DUK_ASSERT(thr->heap->error_not_allowed == 1);
57872 	thr->heap->error_not_allowed = prev_error_not_allowed;
57873 #endif
57874 
57875 	/*
57876 	 *  Post resize assertions.
57877 	 */
57878 
57879 #if defined(DUK_USE_ASSERTIONS)
57880 	/* XXX: post-checks (such as no duplicate keys) */
57881 #endif
57882 	return;
57883 
57884 	/*
57885 	 *  Abandon array failed.  We don't need to DECREF anything
57886 	 *  because the references in the new allocation are not
57887 	 *  INCREF'd until abandon is complete.  The string interned
57888 	 *  keys are on the value stack and are handled normally by
57889 	 *  unwind.
57890 	 */
57891 
57892  abandon_error:
57893  alloc_failed:
57894 	DUK_D(DUK_DPRINT("object property table resize failed"));
57895 
57896 	DUK_FREE_CHECKED(thr, new_p);  /* OK for NULL. */
57897 
57898 	thr->heap->pf_prevent_count--;
57899 	thr->heap->ms_base_flags = prev_ms_base_flags;
57900 #if defined(DUK_USE_ASSERTIONS)
57901 	DUK_ASSERT(thr->heap->error_not_allowed == 1);
57902 	thr->heap->error_not_allowed = prev_error_not_allowed;
57903 #endif
57904 
57905 	DUK_ERROR_ALLOC_FAILED(thr);
57906 	DUK_WO_NORETURN(return;);
57907 }
57908 
57909 /*
57910  *  Helpers to resize properties allocation on specific needs.
57911  */
57912 
57913 DUK_INTERNAL void duk_hobject_resize_entrypart(duk_hthread *thr,
57914                                                duk_hobject *obj,
57915                                                duk_uint32_t new_e_size) {
57916 	duk_uint32_t old_e_size;
57917 	duk_uint32_t new_a_size;
57918 	duk_uint32_t new_h_size;
57919 
57920 	DUK_ASSERT(thr != NULL);
57921 	DUK_ASSERT(obj != NULL);
57922 
57923 	old_e_size = DUK_HOBJECT_GET_ESIZE(obj);
57924 	if (old_e_size > new_e_size) {
57925 		new_e_size = old_e_size;
57926 	}
57927 #if defined(DUK_USE_HOBJECT_HASH_PART)
57928 	new_h_size = duk__get_default_h_size(new_e_size);
57929 #else
57930 	new_h_size = 0;
57931 #endif
57932 	new_a_size = DUK_HOBJECT_GET_ASIZE(obj);
57933 
57934 	duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
57935 }
57936 
57937 /* Grow entry part allocation for one additional entry. */
57938 DUK_LOCAL void duk__grow_props_for_new_entry_item(duk_hthread *thr, duk_hobject *obj) {
57939 	duk_uint32_t old_e_used;  /* actually used, non-NULL entries */
57940 	duk_uint32_t new_e_size_minimum;
57941 	duk_uint32_t new_e_size;
57942 	duk_uint32_t new_a_size;
57943 	duk_uint32_t new_h_size;
57944 
57945 	DUK_ASSERT(thr != NULL);
57946 	DUK_ASSERT(obj != NULL);
57947 
57948 	/* Duktape 0.11.0 and prior tried to optimize the resize by not
57949 	 * counting the number of actually used keys prior to the resize.
57950 	 * This worked mostly well but also caused weird leak-like behavior
57951 	 * as in: test-bug-object-prop-alloc-unbounded.js.  So, now we count
57952 	 * the keys explicitly to compute the new entry part size.
57953 	 */
57954 
57955 	old_e_used = duk__count_used_e_keys(thr, obj);
57956 	new_e_size_minimum = old_e_used + 1;
57957 	new_e_size = old_e_used + duk__get_min_grow_e(old_e_used);
57958 #if defined(DUK_USE_HOBJECT_HASH_PART)
57959 	new_h_size = duk__get_default_h_size(new_e_size);
57960 #else
57961 	new_h_size = 0;
57962 #endif
57963 	new_a_size = DUK_HOBJECT_GET_ASIZE(obj);
57964 
57965 #if defined(DUK_USE_OBJSIZES16)
57966 	if (new_e_size > DUK_UINT16_MAX) {
57967 		new_e_size = DUK_UINT16_MAX;
57968 	}
57969 	if (new_h_size > DUK_UINT16_MAX) {
57970 		new_h_size = DUK_UINT16_MAX;
57971 	}
57972 	if (new_a_size > DUK_UINT16_MAX) {
57973 		new_a_size = DUK_UINT16_MAX;
57974 	}
57975 #endif
57976 	DUK_ASSERT(new_h_size == 0 || new_h_size >= new_e_size);
57977 
57978 	if (!(new_e_size >= new_e_size_minimum)) {
57979 		DUK_ERROR_ALLOC_FAILED(thr);
57980 		DUK_WO_NORETURN(return;);
57981 	}
57982 
57983 	duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
57984 }
57985 
57986 /* Grow array part for a new highest array index. */
57987 DUK_LOCAL void duk__grow_props_for_array_item(duk_hthread *thr, duk_hobject *obj, duk_uint32_t highest_arr_idx) {
57988 	duk_uint32_t new_e_size;
57989 	duk_uint32_t new_a_size;
57990 	duk_uint32_t new_a_size_minimum;
57991 	duk_uint32_t new_h_size;
57992 
57993 	DUK_ASSERT(thr != NULL);
57994 	DUK_ASSERT(obj != NULL);
57995 	DUK_ASSERT(highest_arr_idx >= DUK_HOBJECT_GET_ASIZE(obj));
57996 
57997 	new_e_size = DUK_HOBJECT_GET_ESIZE(obj);
57998 	new_h_size = DUK_HOBJECT_GET_HSIZE(obj);
57999 	new_a_size_minimum = highest_arr_idx + 1;
58000 	new_a_size = highest_arr_idx + duk__get_min_grow_a(highest_arr_idx);
58001 	DUK_ASSERT(new_a_size >= highest_arr_idx + 1);  /* duk__get_min_grow_a() is always >= 1 */
58002 
58003 #if defined(DUK_USE_OBJSIZES16)
58004 	if (new_e_size > DUK_UINT16_MAX) {
58005 		new_e_size = DUK_UINT16_MAX;
58006 	}
58007 	if (new_h_size > DUK_UINT16_MAX) {
58008 		new_h_size = DUK_UINT16_MAX;
58009 	}
58010 	if (new_a_size > DUK_UINT16_MAX) {
58011 		new_a_size = DUK_UINT16_MAX;
58012 	}
58013 #endif
58014 
58015 	if (!(new_a_size >= new_a_size_minimum)) {
58016 		DUK_ERROR_ALLOC_FAILED(thr);
58017 		DUK_WO_NORETURN(return;);
58018 	}
58019 
58020 	duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
58021 }
58022 
58023 /* Abandon array part, moving array entries into entries part.
58024  * This requires a props resize, which is a heavy operation.
58025  * We also compact the entries part while we're at it, although
58026  * this is not strictly required.
58027  */
58028 DUK_LOCAL void duk__abandon_array_part(duk_hthread *thr, duk_hobject *obj) {
58029 	duk_uint32_t new_e_size_minimum;
58030 	duk_uint32_t new_e_size;
58031 	duk_uint32_t new_a_size;
58032 	duk_uint32_t new_h_size;
58033 	duk_uint32_t e_used;  /* actually used, non-NULL keys */
58034 	duk_uint32_t a_used;
58035 	duk_uint32_t a_size;
58036 
58037 	DUK_ASSERT(thr != NULL);
58038 	DUK_ASSERT(obj != NULL);
58039 
58040 	e_used = duk__count_used_e_keys(thr, obj);
58041 	duk__compute_a_stats(thr, obj, &a_used, &a_size);
58042 
58043 	/*
58044 	 *  Must guarantee all actually used array entries will fit into
58045 	 *  new entry part.  Add one growth step to ensure we don't run out
58046 	 *  of space right away.
58047 	 */
58048 
58049 	new_e_size_minimum = e_used + a_used;
58050 	new_e_size = new_e_size_minimum + duk__get_min_grow_e(new_e_size_minimum);
58051 	new_a_size = 0;
58052 #if defined(DUK_USE_HOBJECT_HASH_PART)
58053 	new_h_size = duk__get_default_h_size(new_e_size);
58054 #else
58055 	new_h_size = 0;
58056 #endif
58057 
58058 #if defined(DUK_USE_OBJSIZES16)
58059 	if (new_e_size > DUK_UINT16_MAX) {
58060 		new_e_size = DUK_UINT16_MAX;
58061 	}
58062 	if (new_h_size > DUK_UINT16_MAX) {
58063 		new_h_size = DUK_UINT16_MAX;
58064 	}
58065 	if (new_a_size > DUK_UINT16_MAX) {
58066 		new_a_size = DUK_UINT16_MAX;
58067 	}
58068 #endif
58069 
58070 	if (!(new_e_size >= new_e_size_minimum)) {
58071 		DUK_ERROR_ALLOC_FAILED(thr);
58072 		DUK_WO_NORETURN(return;);
58073 	}
58074 
58075 	DUK_DD(DUK_DDPRINT("abandon array part for hobject %p, "
58076 	                   "array stats before: e_used=%ld, a_used=%ld, a_size=%ld; "
58077 	                   "resize to e_size=%ld, a_size=%ld, h_size=%ld",
58078 	                   (void *) obj, (long) e_used, (long) a_used, (long) a_size,
58079 	                   (long) new_e_size, (long) new_a_size, (long) new_h_size));
58080 
58081 	duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 1);
58082 }
58083 
58084 /*
58085  *  Compact an object.  Minimizes allocation size for objects which are
58086  *  not likely to be extended.  This is useful for internal and non-
58087  *  extensible objects, but can also be called for non-extensible objects.
58088  *  May abandon the array part if it is computed to be too sparse.
58089  *
58090  *  This call is relatively expensive, as it needs to scan both the
58091  *  entries and the array part.
58092  *
58093  *  The call may fail due to allocation error.
58094  */
58095 
58096 DUK_INTERNAL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj) {
58097 	duk_uint32_t e_size;       /* currently used -> new size */
58098 	duk_uint32_t a_size;       /* currently required */
58099 	duk_uint32_t a_used;       /* actually used */
58100 	duk_uint32_t h_size;
58101 	duk_bool_t abandon_array;
58102 
58103 	DUK_ASSERT(thr != NULL);
58104 	DUK_ASSERT(obj != NULL);
58105 
58106 #if defined(DUK_USE_ROM_OBJECTS)
58107 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
58108 		DUK_DD(DUK_DDPRINT("ignore attempt to compact a rom object"));
58109 		return;
58110 	}
58111 #endif
58112 
58113 	e_size = duk__count_used_e_keys(thr, obj);
58114 	duk__compute_a_stats(thr, obj, &a_used, &a_size);
58115 
58116 	DUK_DD(DUK_DDPRINT("compacting hobject, used e keys %ld, used a keys %ld, min a size %ld, "
58117 	                   "resized array density would be: %ld/%ld = %lf",
58118 	                   (long) e_size, (long) a_used, (long) a_size,
58119 	                   (long) a_used, (long) a_size,
58120 	                   (double) a_used / (double) a_size));
58121 
58122 	if (duk__abandon_array_density_check(a_used, a_size)) {
58123 		DUK_DD(DUK_DDPRINT("decided to abandon array during compaction, a_used=%ld, a_size=%ld",
58124 		                   (long) a_used, (long) a_size));
58125 		abandon_array = 1;
58126 		e_size += a_used;
58127 		a_size = 0;
58128 	} else {
58129 		DUK_DD(DUK_DDPRINT("decided to keep array during compaction"));
58130 		abandon_array = 0;
58131 	}
58132 
58133 #if defined(DUK_USE_HOBJECT_HASH_PART)
58134 	if (e_size >= DUK_USE_HOBJECT_HASH_PROP_LIMIT) {
58135 		h_size = duk__get_default_h_size(e_size);
58136 	} else {
58137 		h_size = 0;
58138 	}
58139 #else
58140 	h_size = 0;
58141 #endif
58142 
58143 	DUK_DD(DUK_DDPRINT("compacting hobject -> new e_size %ld, new a_size=%ld, new h_size=%ld, abandon_array=%ld",
58144 	                   (long) e_size, (long) a_size, (long) h_size, (long) abandon_array));
58145 
58146 	duk_hobject_realloc_props(thr, obj, e_size, a_size, h_size, abandon_array);
58147 }
58148 
58149 /*
58150  *  Find an existing key from entry part either by linear scan or by
58151  *  using the hash index (if it exists).
58152  *
58153  *  Sets entry index (and possibly the hash index) to output variables,
58154  *  which allows the caller to update the entry and hash entries in-place.
58155  *  If entry is not found, both values are set to -1.  If entry is found
58156  *  but there is no hash part, h_idx is set to -1.
58157  */
58158 
58159 DUK_INTERNAL duk_bool_t duk_hobject_find_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx) {
58160 	DUK_ASSERT(obj != NULL);
58161 	DUK_ASSERT(key != NULL);
58162 	DUK_ASSERT(e_idx != NULL);
58163 	DUK_ASSERT(h_idx != NULL);
58164 	DUK_UNREF(heap);
58165 
58166 	if (DUK_LIKELY(DUK_HOBJECT_GET_HSIZE(obj) == 0))
58167 	{
58168 		/* Linear scan: more likely because most objects are small.
58169 		 * This is an important fast path.
58170 		 *
58171 		 * XXX: this might be worth inlining for property lookups.
58172 		 */
58173 		duk_uint_fast32_t i;
58174 		duk_uint_fast32_t n;
58175 		duk_hstring **h_keys_base;
58176 		DUK_DDD(DUK_DDDPRINT("duk_hobject_find_entry() using linear scan for lookup"));
58177 
58178 		h_keys_base = DUK_HOBJECT_E_GET_KEY_BASE(heap, obj);
58179 		n = DUK_HOBJECT_GET_ENEXT(obj);
58180 		for (i = 0; i < n; i++) {
58181 			if (h_keys_base[i] == key) {
58182 				*e_idx = (duk_int_t) i;
58183 				*h_idx = -1;
58184 				return 1;
58185 			}
58186 		}
58187 	}
58188 #if defined(DUK_USE_HOBJECT_HASH_PART)
58189 	else
58190 	{
58191 		/* hash lookup */
58192 		duk_uint32_t n;
58193 		duk_uint32_t i, step;
58194 		duk_uint32_t *h_base;
58195 		duk_uint32_t mask;
58196 
58197 		DUK_DDD(DUK_DDDPRINT("duk_hobject_find_entry() using hash part for lookup"));
58198 
58199 		h_base = DUK_HOBJECT_H_GET_BASE(heap, obj);
58200 		n = DUK_HOBJECT_GET_HSIZE(obj);
58201 		mask = n - 1;
58202 		i = DUK_HSTRING_GET_HASH(key) & mask;
58203 		step = 1;  /* Cache friendly but clustering prone. */
58204 
58205 		for (;;) {
58206 			duk_uint32_t t;
58207 
58208 			DUK_ASSERT_DISABLE(i >= 0);  /* unsigned */
58209 			DUK_ASSERT(i < DUK_HOBJECT_GET_HSIZE(obj));
58210 			t = h_base[i];
58211 			DUK_ASSERT(t == DUK__HASH_UNUSED || t == DUK__HASH_DELETED ||
58212 			           (t < DUK_HOBJECT_GET_ESIZE(obj)));  /* t >= 0 always true, unsigned */
58213 
58214 			if (t == DUK__HASH_UNUSED) {
58215 				break;
58216 			} else if (t == DUK__HASH_DELETED) {
58217 				DUK_DDD(DUK_DDDPRINT("lookup miss (deleted) i=%ld, t=%ld",
58218 				                     (long) i, (long) t));
58219 			} else {
58220 				DUK_ASSERT(t < DUK_HOBJECT_GET_ESIZE(obj));
58221 				if (DUK_HOBJECT_E_GET_KEY(heap, obj, t) == key) {
58222 					DUK_DDD(DUK_DDDPRINT("lookup hit i=%ld, t=%ld -> key %p",
58223 					                     (long) i, (long) t, (void *) key));
58224 					*e_idx = (duk_int_t) t;
58225 					*h_idx = (duk_int_t) i;
58226 					return 1;
58227 				}
58228 				DUK_DDD(DUK_DDDPRINT("lookup miss i=%ld, t=%ld",
58229 				                     (long) i, (long) t));
58230 			}
58231 			i = (i + step) & mask;
58232 
58233 			/* Guaranteed to finish (hash is larger than #props). */
58234 		}
58235 	}
58236 #endif  /* DUK_USE_HOBJECT_HASH_PART */
58237 
58238 	/* Not found, leave e_idx and h_idx unset. */
58239 	return 0;
58240 }
58241 
58242 /* For internal use: get non-accessor entry value */
58243 DUK_INTERNAL duk_tval *duk_hobject_find_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key) {
58244 	duk_int_t e_idx;
58245 	duk_int_t h_idx;
58246 
58247 	DUK_ASSERT(obj != NULL);
58248 	DUK_ASSERT(key != NULL);
58249 	DUK_UNREF(heap);
58250 
58251 	if (duk_hobject_find_entry(heap, obj, key, &e_idx, &h_idx)) {
58252 		DUK_ASSERT(e_idx >= 0);
58253 		if (!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {
58254 			return DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx);
58255 		}
58256 	}
58257 	return NULL;
58258 }
58259 
58260 DUK_INTERNAL duk_tval *duk_hobject_find_entry_tval_ptr_stridx(duk_heap *heap, duk_hobject *obj, duk_small_uint_t stridx) {
58261 	return duk_hobject_find_entry_tval_ptr(heap, obj, DUK_HEAP_GET_STRING(heap, stridx));
58262 }
58263 
58264 /* For internal use: get non-accessor entry value and attributes */
58265 DUK_INTERNAL duk_tval *duk_hobject_find_entry_tval_ptr_and_attrs(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_uint_t *out_attrs) {
58266 	duk_int_t e_idx;
58267 	duk_int_t h_idx;
58268 
58269 	DUK_ASSERT(obj != NULL);
58270 	DUK_ASSERT(key != NULL);
58271 	DUK_ASSERT(out_attrs != NULL);
58272 	DUK_UNREF(heap);
58273 
58274 	if (duk_hobject_find_entry(heap, obj, key, &e_idx, &h_idx)) {
58275 		DUK_ASSERT(e_idx >= 0);
58276 		if (!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {
58277 			*out_attrs = DUK_HOBJECT_E_GET_FLAGS(heap, obj, e_idx);
58278 			return DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx);
58279 		}
58280 	}
58281 	/* If not found, out_attrs is left unset. */
58282 	return NULL;
58283 }
58284 
58285 /* For internal use: get array part value */
58286 DUK_INTERNAL duk_tval *duk_hobject_find_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i) {
58287 	duk_tval *tv;
58288 
58289 	DUK_ASSERT(obj != NULL);
58290 	DUK_UNREF(heap);
58291 
58292 	if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
58293 		return NULL;
58294 	}
58295 	if (i >= DUK_HOBJECT_GET_ASIZE(obj)) {
58296 		return NULL;
58297 	}
58298 	tv = DUK_HOBJECT_A_GET_VALUE_PTR(heap, obj, i);
58299 	return tv;
58300 }
58301 
58302 /*
58303  *  Allocate and initialize a new entry, resizing the properties allocation
58304  *  if necessary.  Returns entry index (e_idx) or throws an error if alloc fails.
58305  *
58306  *  Sets the key of the entry (increasing the key's refcount), and updates
58307  *  the hash part if it exists.  Caller must set value and flags, and update
58308  *  the entry value refcount.  A decref for the previous value is not necessary.
58309  */
58310 
58311 DUK_LOCAL duk_int_t duk__hobject_alloc_entry_checked(duk_hthread *thr, duk_hobject *obj, duk_hstring *key) {
58312 	duk_uint32_t idx;
58313 
58314 	DUK_ASSERT(thr != NULL);
58315 	DUK_ASSERT(obj != NULL);
58316 	DUK_ASSERT(key != NULL);
58317 	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(obj) <= DUK_HOBJECT_GET_ESIZE(obj));
58318 
58319 #if defined(DUK_USE_ASSERTIONS)
58320 	/* key must not already exist in entry part */
58321 	{
58322 		duk_uint_fast32_t i;
58323 		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
58324 			DUK_ASSERT(DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i) != key);
58325 		}
58326 	}
58327 #endif
58328 
58329 	if (DUK_HOBJECT_GET_ENEXT(obj) >= DUK_HOBJECT_GET_ESIZE(obj)) {
58330 		/* only need to guarantee 1 more slot, but allocation growth is in chunks */
58331 		DUK_DDD(DUK_DDDPRINT("entry part full, allocate space for one more entry"));
58332 		duk__grow_props_for_new_entry_item(thr, obj);
58333 	}
58334 	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(obj) < DUK_HOBJECT_GET_ESIZE(obj));
58335 	idx = DUK_HOBJECT_POSTINC_ENEXT(obj);
58336 
58337 	/* previous value is assumed to be garbage, so don't touch it */
58338 	DUK_HOBJECT_E_SET_KEY(thr->heap, obj, idx, key);
58339 	DUK_HSTRING_INCREF(thr, key);
58340 
58341 #if defined(DUK_USE_HOBJECT_HASH_PART)
58342 	if (DUK_UNLIKELY(DUK_HOBJECT_GET_HSIZE(obj) > 0)) {
58343 		duk_uint32_t n, mask;
58344 		duk_uint32_t i, step;
58345 		duk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(thr->heap, obj);
58346 
58347 		n = DUK_HOBJECT_GET_HSIZE(obj);
58348 		mask = n - 1;
58349 		i = DUK_HSTRING_GET_HASH(key) & mask;
58350 		step = 1;  /* Cache friendly but clustering prone. */
58351 
58352 		for (;;) {
58353 			duk_uint32_t t = h_base[i];
58354 			if (t == DUK__HASH_UNUSED || t == DUK__HASH_DELETED) {
58355 				DUK_DDD(DUK_DDDPRINT("duk__hobject_alloc_entry_checked() inserted key into hash part, %ld -> %ld",
58356 				                     (long) i, (long) idx));
58357 				DUK_ASSERT_DISABLE(i >= 0);  /* unsigned */
58358 				DUK_ASSERT(i < DUK_HOBJECT_GET_HSIZE(obj));
58359 				DUK_ASSERT_DISABLE(idx >= 0);
58360 				DUK_ASSERT(idx < DUK_HOBJECT_GET_ESIZE(obj));
58361 				h_base[i] = idx;
58362 				break;
58363 			}
58364 			DUK_DDD(DUK_DDDPRINT("duk__hobject_alloc_entry_checked() miss %ld", (long) i));
58365 			i = (i + step) & mask;
58366 
58367 			/* Guaranteed to finish (hash is larger than #props). */
58368 		}
58369 	}
58370 #endif  /* DUK_USE_HOBJECT_HASH_PART */
58371 
58372 	/* Note: we could return the hash index here too, but it's not
58373 	 * needed right now.
58374 	 */
58375 
58376 	DUK_ASSERT_DISABLE(idx >= 0);
58377 	DUK_ASSERT(idx < DUK_HOBJECT_GET_ESIZE(obj));
58378 	DUK_ASSERT(idx < DUK_HOBJECT_GET_ENEXT(obj));
58379 	return (duk_int_t) idx;
58380 }
58381 
58382 /*
58383  *  Object internal value
58384  *
58385  *  Returned value is guaranteed to be reachable / incref'd, caller does not need
58386  *  to incref OR decref.  No proxies or accessors are invoked, no prototype walk.
58387  */
58388 
58389 DUK_INTERNAL duk_tval *duk_hobject_get_internal_value_tval_ptr(duk_heap *heap, duk_hobject *obj) {
58390 	return duk_hobject_find_entry_tval_ptr_stridx(heap, obj, DUK_STRIDX_INT_VALUE);
58391 }
58392 
58393 DUK_LOCAL duk_heaphdr *duk_hobject_get_internal_value_heaphdr(duk_heap *heap, duk_hobject *obj) {
58394 	duk_tval *tv;
58395 
58396 	DUK_ASSERT(heap != NULL);
58397 	DUK_ASSERT(obj != NULL);
58398 
58399 	tv = duk_hobject_get_internal_value_tval_ptr(heap, obj);
58400 	if (tv != NULL) {
58401 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
58402 		DUK_ASSERT(h != NULL);
58403 		return h;
58404 	}
58405 
58406 	return NULL;
58407 }
58408 
58409 DUK_INTERNAL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj) {
58410 	duk_hstring *h;
58411 
58412 	h = (duk_hstring *) duk_hobject_get_internal_value_heaphdr(heap, obj);
58413 	if (h != NULL) {
58414 		DUK_ASSERT(DUK_HEAPHDR_IS_STRING((duk_heaphdr *) h));
58415 	}
58416 	return h;
58417 }
58418 
58419 DUK_LOCAL duk_hobject *duk__hobject_get_entry_object_stridx(duk_heap *heap, duk_hobject *obj, duk_small_uint_t stridx) {
58420 	duk_tval *tv;
58421 	duk_hobject *h;
58422 
58423 	tv = duk_hobject_find_entry_tval_ptr_stridx(heap, obj, stridx);
58424 	if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
58425 		h = DUK_TVAL_GET_OBJECT(tv);
58426 		DUK_ASSERT(h != NULL);
58427 		return h;
58428 	}
58429 	return NULL;
58430 }
58431 
58432 DUK_INTERNAL duk_harray *duk_hobject_get_formals(duk_hthread *thr, duk_hobject *obj) {
58433 	duk_harray *h;
58434 
58435 	h = (duk_harray *) duk__hobject_get_entry_object_stridx(thr->heap, obj, DUK_STRIDX_INT_FORMALS);
58436 	if (h != NULL) {
58437 		DUK_ASSERT(DUK_HOBJECT_IS_ARRAY((duk_hobject *) h));
58438 		DUK_ASSERT(h->length <= DUK_HOBJECT_GET_ASIZE((duk_hobject *) h));
58439 	}
58440 	return h;
58441 }
58442 
58443 DUK_INTERNAL duk_hobject *duk_hobject_get_varmap(duk_hthread *thr, duk_hobject *obj) {
58444 	duk_hobject *h;
58445 
58446 	h = duk__hobject_get_entry_object_stridx(thr->heap, obj, DUK_STRIDX_INT_VARMAP);
58447 	return h;
58448 }
58449 
58450 /*
58451  *  Arguments handling helpers (argument map mainly).
58452  *
58453  *  An arguments object has exotic behavior for some numeric indices.
58454  *  Accesses may translate to identifier operations which may have
58455  *  arbitrary side effects (potentially invalidating any duk_tval
58456  *  pointers).
58457  */
58458 
58459 /* Lookup 'key' from arguments internal 'map', perform a variable lookup
58460  * if mapped, and leave the result on top of stack (and return non-zero).
58461  * Used in E5 Section 10.6 algorithms [[Get]] and [[GetOwnProperty]].
58462  */
58463 DUK_LOCAL
58464 duk_bool_t duk__lookup_arguments_map(duk_hthread *thr,
58465                                      duk_hobject *obj,
58466                                      duk_hstring *key,
58467                                      duk_propdesc *temp_desc,
58468                                      duk_hobject **out_map,
58469                                      duk_hobject **out_varenv) {
58470 	duk_hobject *map;
58471 	duk_hobject *varenv;
58472 	duk_bool_t rc;
58473 
58474 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
58475 
58476 	DUK_DDD(DUK_DDDPRINT("arguments map lookup: thr=%p, obj=%p, key=%p, temp_desc=%p "
58477 	                     "(obj -> %!O, key -> %!O)",
58478 	                     (void *) thr, (void *) obj, (void *) key, (void *) temp_desc,
58479 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
58480 
58481 	if (!duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_MAP(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
58482 		DUK_DDD(DUK_DDDPRINT("-> no 'map'"));
58483 		return 0;
58484 	}
58485 
58486 	map = duk_require_hobject(thr, -1);
58487 	DUK_ASSERT(map != NULL);
58488 	duk_pop_unsafe(thr);  /* map is reachable through obj */
58489 
58490 	if (!duk_hobject_get_own_propdesc(thr, map, key, temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
58491 		DUK_DDD(DUK_DDDPRINT("-> 'map' exists, but key not in map"));
58492 		return 0;
58493 	}
58494 
58495 	/* [... varname] */
58496 	DUK_DDD(DUK_DDDPRINT("-> 'map' exists, and contains key, key is mapped to argument/variable binding %!T",
58497 	                     (duk_tval *) duk_get_tval(thr, -1)));
58498 	DUK_ASSERT(duk_is_string(thr, -1));  /* guaranteed when building arguments */
58499 
58500 	/* get varenv for varname (callee's declarative lexical environment) */
58501 	rc = duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_VARENV(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE);
58502 	DUK_UNREF(rc);
58503 	DUK_ASSERT(rc != 0);  /* arguments MUST have an initialized lexical environment reference */
58504 	varenv = duk_require_hobject(thr, -1);
58505 	DUK_ASSERT(varenv != NULL);
58506 	duk_pop_unsafe(thr);  /* varenv remains reachable through 'obj' */
58507 
58508 	DUK_DDD(DUK_DDDPRINT("arguments varenv is: %!dO", (duk_heaphdr *) varenv));
58509 
58510 	/* success: leave varname in stack */
58511 	*out_map = map;
58512 	*out_varenv = varenv;
58513 	return 1;  /* [... varname] */
58514 }
58515 
58516 /* Lookup 'key' from arguments internal 'map', and leave replacement value
58517  * on stack top if mapped (and return non-zero).
58518  * Used in E5 Section 10.6 algorithm for [[GetOwnProperty]] (used by [[Get]]).
58519  */
58520 DUK_LOCAL duk_bool_t duk__check_arguments_map_for_get(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc) {
58521 	duk_hobject *map;
58522 	duk_hobject *varenv;
58523 	duk_hstring *varname;
58524 
58525 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
58526 
58527 	if (!duk__lookup_arguments_map(thr, obj, key, temp_desc, &map, &varenv)) {
58528 		DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic get behavior"));
58529 		return 0;
58530 	}
58531 
58532 	/* [... varname] */
58533 
58534 	varname = duk_require_hstring(thr, -1);
58535 	DUK_ASSERT(varname != NULL);
58536 	duk_pop_unsafe(thr);  /* varname is still reachable */
58537 
58538 	DUK_DDD(DUK_DDDPRINT("arguments object automatic getvar for a bound variable; "
58539 	                     "key=%!O, varname=%!O",
58540 	                     (duk_heaphdr *) key,
58541 	                     (duk_heaphdr *) varname));
58542 
58543 	(void) duk_js_getvar_envrec(thr, varenv, varname, 1 /*throw*/);
58544 
58545 	/* [... value this_binding] */
58546 
58547 	duk_pop_unsafe(thr);
58548 
58549 	/* leave result on stack top */
58550 	return 1;
58551 }
58552 
58553 /* Lookup 'key' from arguments internal 'map', perform a variable write if mapped.
58554  * Used in E5 Section 10.6 algorithm for [[DefineOwnProperty]] (used by [[Put]]).
58555  * Assumes stack top contains 'put' value (which is NOT popped).
58556  */
58557 DUK_LOCAL void duk__check_arguments_map_for_put(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc, duk_bool_t throw_flag) {
58558 	duk_hobject *map;
58559 	duk_hobject *varenv;
58560 	duk_hstring *varname;
58561 
58562 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
58563 
58564 	if (!duk__lookup_arguments_map(thr, obj, key, temp_desc, &map, &varenv)) {
58565 		DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic put behavior"));
58566 		return;
58567 	}
58568 
58569 	/* [... put_value varname] */
58570 
58571 	varname = duk_require_hstring(thr, -1);
58572 	DUK_ASSERT(varname != NULL);
58573 	duk_pop_unsafe(thr);  /* varname is still reachable */
58574 
58575 	DUK_DDD(DUK_DDDPRINT("arguments object automatic putvar for a bound variable; "
58576 	                     "key=%!O, varname=%!O, value=%!T",
58577 	                     (duk_heaphdr *) key,
58578 	                     (duk_heaphdr *) varname,
58579 	                     (duk_tval *) duk_require_tval(thr, -1)));
58580 
58581 	/* [... put_value] */
58582 
58583 	/*
58584 	 *  Note: although arguments object variable mappings are only established
58585 	 *  for non-strict functions (and a call to a non-strict function created
58586 	 *  the arguments object in question), an inner strict function may be doing
58587 	 *  the actual property write.  Hence the throw_flag applied here comes from
58588 	 *  the property write call.
58589 	 */
58590 
58591 	duk_js_putvar_envrec(thr, varenv, varname, duk_require_tval(thr, -1), throw_flag);
58592 
58593 	/* [... put_value] */
58594 }
58595 
58596 /* Lookup 'key' from arguments internal 'map', delete mapping if found.
58597  * Used in E5 Section 10.6 algorithm for [[Delete]].  Note that the
58598  * variable/argument itself (where the map points) is not deleted.
58599  */
58600 DUK_LOCAL void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc) {
58601 	duk_hobject *map;
58602 
58603 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
58604 
58605 	if (!duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_MAP(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
58606 		DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic delete behavior"));
58607 		return;
58608 	}
58609 
58610 	map = duk_require_hobject(thr, -1);
58611 	DUK_ASSERT(map != NULL);
58612 	duk_pop_unsafe(thr);  /* map is reachable through obj */
58613 
58614 	DUK_DDD(DUK_DDDPRINT("-> have 'map', delete key %!O from map (if exists)); ignore result",
58615 	                     (duk_heaphdr *) key));
58616 
58617 	/* Note: no recursion issue, we can trust 'map' to behave */
58618 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(map));
58619 	DUK_DDD(DUK_DDDPRINT("map before deletion: %!O", (duk_heaphdr *) map));
58620 	(void) duk_hobject_delprop_raw(thr, map, key, 0);  /* ignore result */
58621 	DUK_DDD(DUK_DDDPRINT("map after deletion: %!O", (duk_heaphdr *) map));
58622 }
58623 
58624 /*
58625  *  ECMAScript compliant [[GetOwnProperty]](P), for internal use only.
58626  *
58627  *  If property is found:
58628  *    - Fills descriptor fields to 'out_desc'
58629  *    - If DUK_GETDESC_FLAG_PUSH_VALUE is set, pushes a value related to the
58630  *      property onto the stack ('undefined' for accessor properties).
58631  *    - Returns non-zero
58632  *
58633  *  If property is not found:
58634  *    - 'out_desc' is left in untouched state (possibly garbage)
58635  *    - Nothing is pushed onto the stack (not even with DUK_GETDESC_FLAG_PUSH_VALUE
58636  *      set)
58637  *    - Returns zero
58638  *
58639  *  Notes:
58640  *
58641  *    - Getting a property descriptor may cause an allocation (and hence
58642  *      GC) to take place, hence reachability and refcount of all related
58643  *      values matter.  Reallocation of value stack, properties, etc may
58644  *      invalidate many duk_tval pointers (concretely, those which reside
58645  *      in memory areas subject to reallocation).  However, heap object
58646  *      pointers are never affected (heap objects have stable pointers).
58647  *
58648  *    - The value of a plain property is always reachable and has a non-zero
58649  *      reference count.
58650  *
58651  *    - The value of a virtual property is not necessarily reachable from
58652  *      elsewhere and may have a refcount of zero.  Hence we push it onto
58653  *      the valstack for the caller, which ensures it remains reachable
58654  *      while it is needed.
58655  *
58656  *    - There are no virtual accessor properties.  Hence, all getters and
58657  *      setters are always related to concretely stored properties, which
58658  *      ensures that the get/set functions in the resulting descriptor are
58659  *      reachable and have non-zero refcounts.  Should there be virtual
58660  *      accessor properties later, this would need to change.
58661  */
58662 
58663 DUK_LOCAL duk_bool_t duk__get_own_propdesc_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_uint32_t arr_idx, duk_propdesc *out_desc, duk_small_uint_t flags) {
58664 	duk_tval *tv;
58665 
58666 	DUK_DDD(DUK_DDDPRINT("duk_hobject_get_own_propdesc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, "
58667 	                     "arr_idx=%ld (obj -> %!O, key -> %!O)",
58668 	                     (void *) thr, (void *) obj, (void *) key, (void *) out_desc,
58669 	                     (long) flags, (long) arr_idx,
58670 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
58671 
58672 	DUK_ASSERT(thr != NULL);
58673 	DUK_ASSERT(thr->heap != NULL);
58674 	DUK_ASSERT(obj != NULL);
58675 	DUK_ASSERT(key != NULL);
58676 	DUK_ASSERT(out_desc != NULL);
58677 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
58678 
58679 	DUK_STATS_INC(thr->heap, stats_getownpropdesc_count);
58680 
58681 	/* Each code path returning 1 (= found) must fill in all the output
58682 	 * descriptor fields.  We don't do it beforehand because it'd be
58683 	 * unnecessary work if the property isn't found and would happen
58684 	 * multiple times for an inheritance chain.
58685 	 */
58686 	DUK_ASSERT_SET_GARBAGE(out_desc, sizeof(*out_desc));
58687 #if 0
58688 	out_desc->flags = 0;
58689 	out_desc->get = NULL;
58690 	out_desc->set = NULL;
58691 	out_desc->e_idx = -1;
58692 	out_desc->h_idx = -1;
58693 	out_desc->a_idx = -1;
58694 #endif
58695 
58696 	/*
58697 	 *  Try entries part first because it's the common case.
58698 	 *
58699 	 *  Array part lookups are usually handled by the array fast path, and
58700 	 *  are not usually inherited.  Array and entry parts never contain the
58701 	 *  same keys so the entry part vs. array part order doesn't matter.
58702 	 */
58703 
58704 	if (duk_hobject_find_entry(thr->heap, obj, key, &out_desc->e_idx, &out_desc->h_idx)) {
58705 		duk_int_t e_idx = out_desc->e_idx;
58706 		DUK_ASSERT(out_desc->e_idx >= 0);
58707 		out_desc->a_idx = -1;
58708 		out_desc->flags = DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, e_idx);
58709 		out_desc->get = NULL;
58710 		out_desc->set = NULL;
58711 		if (DUK_UNLIKELY(out_desc->flags & DUK_PROPDESC_FLAG_ACCESSOR)) {
58712 			DUK_DDD(DUK_DDDPRINT("-> found accessor property in entry part"));
58713 			out_desc->get = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, e_idx);
58714 			out_desc->set = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, e_idx);
58715 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
58716 				/* a dummy undefined value is pushed to make valstack
58717 				 * behavior uniform for caller
58718 				 */
58719 				duk_push_undefined(thr);
58720 			}
58721 		} else {
58722 			DUK_DDD(DUK_DDDPRINT("-> found plain property in entry part"));
58723 			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
58724 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
58725 				duk_push_tval(thr, tv);
58726 			}
58727 		}
58728 		goto prop_found;
58729 	}
58730 
58731 	/*
58732 	 *  Try array part.
58733 	 */
58734 
58735 	if (DUK_HOBJECT_HAS_ARRAY_PART(obj) && arr_idx != DUK__NO_ARRAY_INDEX) {
58736 		if (arr_idx < DUK_HOBJECT_GET_ASIZE(obj)) {
58737 			tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
58738 			if (!DUK_TVAL_IS_UNUSED(tv)) {
58739 				DUK_DDD(DUK_DDDPRINT("-> found in array part"));
58740 				if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
58741 					duk_push_tval(thr, tv);
58742 				}
58743 				/* implicit attributes */
58744 				out_desc->flags = DUK_PROPDESC_FLAG_WRITABLE |
58745 				                  DUK_PROPDESC_FLAG_CONFIGURABLE |
58746 				                  DUK_PROPDESC_FLAG_ENUMERABLE;
58747 				out_desc->get = NULL;
58748 				out_desc->set = NULL;
58749 				out_desc->e_idx = -1;
58750 				out_desc->h_idx = -1;
58751 				out_desc->a_idx = (duk_int_t) arr_idx;  /* XXX: limit 2G due to being signed */
58752 				goto prop_found;
58753 			}
58754 		}
58755 	}
58756 
58757 	DUK_DDD(DUK_DDDPRINT("-> not found as a concrete property"));
58758 
58759 	/*
58760 	 *  Not found as a concrete property, check for virtual properties.
58761 	 */
58762 
58763 	if (!DUK_HOBJECT_HAS_VIRTUAL_PROPERTIES(obj)) {
58764 		/* Quick skip. */
58765 		goto prop_not_found;
58766 	}
58767 
58768 	if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
58769 		duk_harray *a;
58770 
58771 		DUK_DDD(DUK_DDDPRINT("array object exotic property get for key: %!O, arr_idx: %ld",
58772 		                     (duk_heaphdr *) key, (long) arr_idx));
58773 
58774 		a = (duk_harray *) obj;
58775 		DUK_HARRAY_ASSERT_VALID(a);
58776 
58777 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
58778 			DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
58779 
58780 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
58781 				duk_push_uint(thr, (duk_uint_t) a->length);
58782 			}
58783 			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
58784 			if (DUK_HARRAY_LENGTH_WRITABLE(a)) {
58785 				out_desc->flags |= DUK_PROPDESC_FLAG_WRITABLE;
58786 			}
58787 			out_desc->get = NULL;
58788 			out_desc->set = NULL;
58789 			out_desc->e_idx = -1;
58790 			out_desc->h_idx = -1;
58791 			out_desc->a_idx = -1;
58792 
58793 			DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
58794 			goto prop_found_noexotic;  /* cannot be arguments exotic */
58795 		}
58796 	} else if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj)) {
58797 		DUK_DDD(DUK_DDDPRINT("string object exotic property get for key: %!O, arr_idx: %ld",
58798 		                     (duk_heaphdr *) key, (long) arr_idx));
58799 
58800 		/* XXX: charlen; avoid multiple lookups? */
58801 
58802 		if (arr_idx != DUK__NO_ARRAY_INDEX) {
58803 			duk_hstring *h_val;
58804 
58805 			DUK_DDD(DUK_DDDPRINT("array index exists"));
58806 
58807 			h_val = duk_hobject_get_internal_value_string(thr->heap, obj);
58808 			DUK_ASSERT(h_val);
58809 			if (arr_idx < DUK_HSTRING_GET_CHARLEN(h_val)) {
58810 				DUK_DDD(DUK_DDDPRINT("-> found, array index inside string"));
58811 				if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
58812 					duk_push_hstring(thr, h_val);
58813 					duk_substring(thr, -1, arr_idx, arr_idx + 1);  /* [str] -> [substr] */
58814 				}
58815 				out_desc->flags = DUK_PROPDESC_FLAG_ENUMERABLE |  /* E5 Section 15.5.5.2 */
58816 				                  DUK_PROPDESC_FLAG_VIRTUAL;
58817 				out_desc->get = NULL;
58818 				out_desc->set = NULL;
58819 				out_desc->e_idx = -1;
58820 				out_desc->h_idx = -1;
58821 				out_desc->a_idx = -1;
58822 
58823 				DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
58824 				goto prop_found_noexotic;  /* cannot be arguments exotic */
58825 			} else {
58826 				/* index is above internal string length -> property is fully normal */
58827 				DUK_DDD(DUK_DDDPRINT("array index outside string -> normal property"));
58828 			}
58829 		} else if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
58830 			duk_hstring *h_val;
58831 
58832 			DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
58833 
58834 			h_val = duk_hobject_get_internal_value_string(thr->heap, obj);
58835 			DUK_ASSERT(h_val != NULL);
58836 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
58837 				duk_push_uint(thr, (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h_val));
58838 			}
58839 			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;  /* E5 Section 15.5.5.1 */
58840 			out_desc->get = NULL;
58841 			out_desc->set = NULL;
58842 			out_desc->e_idx = -1;
58843 			out_desc->h_idx = -1;
58844 			out_desc->a_idx = -1;
58845 
58846 			DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
58847 			goto prop_found_noexotic;  /* cannot be arguments exotic */
58848 		}
58849 	}
58850 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
58851 	else if (DUK_HOBJECT_IS_BUFOBJ(obj)) {
58852 		duk_hbufobj *h_bufobj;
58853 		duk_uint_t byte_off;
58854 		duk_small_uint_t elem_size;
58855 
58856 		h_bufobj = (duk_hbufobj *) obj;
58857 		DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
58858 		DUK_DDD(DUK_DDDPRINT("bufobj property get for key: %!O, arr_idx: %ld",
58859 		                     (duk_heaphdr *) key, (long) arr_idx));
58860 
58861 		if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
58862 			DUK_DDD(DUK_DDDPRINT("array index exists"));
58863 
58864 			/* Careful with wrapping: arr_idx upshift may easily wrap, whereas
58865 			 * length downshift won't.
58866 			 */
58867 			if (arr_idx < (h_bufobj->length >> h_bufobj->shift)) {
58868 				byte_off = arr_idx << h_bufobj->shift;  /* no wrap assuming h_bufobj->length is valid */
58869 				elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
58870 				if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
58871 					duk_uint8_t *data;
58872 
58873 					if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
58874 						data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
58875 						duk_hbufobj_push_validated_read(thr, h_bufobj, data, elem_size);
58876 					} else {
58877 						DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (read zero)"));
58878 						duk_push_uint(thr, 0);
58879 					}
58880 				}
58881 				out_desc->flags = DUK_PROPDESC_FLAG_WRITABLE |
58882 				                  DUK_PROPDESC_FLAG_VIRTUAL;
58883 				if (DUK_HOBJECT_GET_CLASS_NUMBER(obj) != DUK_HOBJECT_CLASS_ARRAYBUFFER) {
58884 					/* ArrayBuffer indices are non-standard and are
58885 					 * non-enumerable to avoid their serialization.
58886 					 */
58887 					out_desc->flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
58888 				}
58889 				out_desc->get = NULL;
58890 				out_desc->set = NULL;
58891 				out_desc->e_idx = -1;
58892 				out_desc->h_idx = -1;
58893 				out_desc->a_idx = -1;
58894 
58895 				DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
58896 				goto prop_found_noexotic;  /* cannot be e.g. arguments exotic, since exotic 'traits' are mutually exclusive */
58897 			} else {
58898 				/* index is above internal buffer length -> property is fully normal */
58899 				DUK_DDD(DUK_DDDPRINT("array index outside buffer -> normal property"));
58900 			}
58901 		} else if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
58902 			DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
58903 
58904 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
58905 				/* Length in elements: take into account shift, but
58906 				 * intentionally don't check the underlying buffer here.
58907 				 */
58908 				duk_push_uint(thr, h_bufobj->length >> h_bufobj->shift);
58909 			}
58910 			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
58911 			out_desc->get = NULL;
58912 			out_desc->set = NULL;
58913 			out_desc->e_idx = -1;
58914 			out_desc->h_idx = -1;
58915 			out_desc->a_idx = -1;
58916 
58917 			DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
58918 			goto prop_found_noexotic;  /* cannot be arguments exotic */
58919 		}
58920 	}
58921 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
58922 
58923 	/* Array properties have exotic behavior but they are concrete,
58924 	 * so no special handling here.
58925 	 *
58926 	 * Arguments exotic behavior (E5 Section 10.6, [[GetOwnProperty]]
58927 	 * is only relevant as a post-check implemented below; hence no
58928 	 * check here.
58929 	 */
58930 
58931 	/*
58932 	 *  Not found as concrete or virtual.
58933 	 */
58934 
58935  prop_not_found:
58936 	DUK_DDD(DUK_DDDPRINT("-> not found (virtual, entry part, or array part)"));
58937 	DUK_STATS_INC(thr->heap, stats_getownpropdesc_miss);
58938 	return 0;
58939 
58940 	/*
58941 	 *  Found.
58942 	 *
58943 	 *  Arguments object has exotic post-processing, see E5 Section 10.6,
58944 	 *  description of [[GetOwnProperty]] variant for arguments.
58945 	 */
58946 
58947  prop_found:
58948 	DUK_DDD(DUK_DDDPRINT("-> property found, checking for arguments exotic post-behavior"));
58949 
58950 	/* Notes:
58951 	 *  - Only numbered indices are relevant, so arr_idx fast reject is good
58952 	 *    (this is valid unless there are more than 4**32-1 arguments).
58953 	 *  - Since variable lookup has no side effects, this can be skipped if
58954 	 *    DUK_GETDESC_FLAG_PUSH_VALUE is not set.
58955 	 */
58956 
58957 	if (DUK_UNLIKELY(DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj) &&
58958 	                 arr_idx != DUK__NO_ARRAY_INDEX &&
58959 	                 (flags & DUK_GETDESC_FLAG_PUSH_VALUE))) {
58960 		duk_propdesc temp_desc;
58961 
58962 		/* Magically bound variable cannot be an accessor.  However,
58963 		 * there may be an accessor property (or a plain property) in
58964 		 * place with magic behavior removed.  This happens e.g. when
58965 		 * a magic property is redefined with defineProperty().
58966 		 * Cannot assert for "not accessor" here.
58967 		 */
58968 
58969 		/* replaces top of stack with new value if necessary */
58970 		DUK_ASSERT((flags & DUK_GETDESC_FLAG_PUSH_VALUE) != 0);
58971 
58972 		/* This can perform a variable lookup but only into a declarative
58973 		 * environment which has no side effects.
58974 		 */
58975 		if (duk__check_arguments_map_for_get(thr, obj, key, &temp_desc)) {
58976 			DUK_DDD(DUK_DDDPRINT("-> arguments exotic behavior overrides result: %!T -> %!T",
58977 			                     (duk_tval *) duk_get_tval(thr, -2),
58978 			                     (duk_tval *) duk_get_tval(thr, -1)));
58979 			/* [... old_result result] -> [... result] */
58980 			duk_remove_m2(thr);
58981 		}
58982 	}
58983 
58984  prop_found_noexotic:
58985 	DUK_STATS_INC(thr->heap, stats_getownpropdesc_hit);
58986 	return 1;
58987 }
58988 
58989 DUK_INTERNAL duk_bool_t duk_hobject_get_own_propdesc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags) {
58990 	DUK_ASSERT(thr != NULL);
58991 	DUK_ASSERT(obj != NULL);
58992 	DUK_ASSERT(key != NULL);
58993 	DUK_ASSERT(out_desc != NULL);
58994 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
58995 
58996 	return duk__get_own_propdesc_raw(thr, obj, key, DUK_HSTRING_GET_ARRIDX_SLOW(key), out_desc, flags);
58997 }
58998 
58999 /*
59000  *  ECMAScript compliant [[GetProperty]](P), for internal use only.
59001  *
59002  *  If property is found:
59003  *    - Fills descriptor fields to 'out_desc'
59004  *    - If DUK_GETDESC_FLAG_PUSH_VALUE is set, pushes a value related to the
59005  *      property onto the stack ('undefined' for accessor properties).
59006  *    - Returns non-zero
59007  *
59008  *  If property is not found:
59009  *    - 'out_desc' is left in untouched state (possibly garbage)
59010  *    - Nothing is pushed onto the stack (not even with DUK_GETDESC_FLAG_PUSH_VALUE
59011  *      set)
59012  *    - Returns zero
59013  *
59014  *  May cause arbitrary side effects and invalidate (most) duk_tval
59015  *  pointers.
59016  */
59017 
59018 DUK_LOCAL duk_bool_t duk__get_propdesc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags) {
59019 	duk_hobject *curr;
59020 	duk_uint32_t arr_idx;
59021 	duk_uint_t sanity;
59022 
59023 	DUK_ASSERT(thr != NULL);
59024 	DUK_ASSERT(thr->heap != NULL);
59025 	DUK_ASSERT(obj != NULL);
59026 	DUK_ASSERT(key != NULL);
59027 	DUK_ASSERT(out_desc != NULL);
59028 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
59029 
59030 	DUK_STATS_INC(thr->heap, stats_getpropdesc_count);
59031 
59032 	arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
59033 
59034 	DUK_DDD(DUK_DDDPRINT("duk__get_propdesc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, "
59035 	                     "arr_idx=%ld (obj -> %!O, key -> %!O)",
59036 	                     (void *) thr, (void *) obj, (void *) key, (void *) out_desc,
59037 	                     (long) flags, (long) arr_idx,
59038 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
59039 
59040 	curr = obj;
59041 	DUK_ASSERT(curr != NULL);
59042 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
59043 	do {
59044 		if (duk__get_own_propdesc_raw(thr, curr, key, arr_idx, out_desc, flags)) {
59045 			/* stack contains value (if requested), 'out_desc' is set */
59046 			DUK_STATS_INC(thr->heap, stats_getpropdesc_hit);
59047 			return 1;
59048 		}
59049 
59050 		/* not found in 'curr', next in prototype chain; impose max depth */
59051 		if (DUK_UNLIKELY(sanity-- == 0)) {
59052 			if (flags & DUK_GETDESC_FLAG_IGNORE_PROTOLOOP) {
59053 				/* treat like property not found */
59054 				break;
59055 			} else {
59056 				DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
59057 				DUK_WO_NORETURN(return 0;);
59058 			}
59059 		}
59060 		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
59061 	} while (curr != NULL);
59062 
59063 	/* out_desc is left untouched (possibly garbage), caller must use return
59064 	 * value to determine whether out_desc can be looked up
59065 	 */
59066 
59067 	DUK_STATS_INC(thr->heap, stats_getpropdesc_miss);
59068 	return 0;
59069 }
59070 
59071 /*
59072  *  Shallow fast path checks for accessing array elements with numeric
59073  *  indices.  The goal is to try to avoid coercing an array index to an
59074  *  (interned) string for the most common lookups, in particular, for
59075  *  standard Array objects.
59076  *
59077  *  Interning is avoided but only for a very narrow set of cases:
59078  *    - Object has array part, index is within array allocation, and
59079  *      value is not unused (= key exists)
59080  *    - Object has no interfering exotic behavior (e.g. arguments or
59081  *      string object exotic behaviors interfere, array exotic
59082  *      behavior does not).
59083  *
59084  *  Current shortcoming: if key does not exist (even if it is within
59085  *  the array allocation range) a slow path lookup with interning is
59086  *  always required.  This can probably be fixed so that there is a
59087  *  quick fast path for non-existent elements as well, at least for
59088  *  standard Array objects.
59089  */
59090 
59091 #if defined(DUK_USE_ARRAY_PROP_FASTPATH)
59092 DUK_LOCAL duk_tval *duk__getprop_shallow_fastpath_array_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key) {
59093 	duk_tval *tv;
59094 	duk_uint32_t idx;
59095 
59096 	DUK_UNREF(thr);
59097 
59098 	if (!(DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
59099 	     !DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj) &&
59100 	     !DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj) &&
59101 	     !DUK_HOBJECT_IS_BUFOBJ(obj) &&
59102 	     !DUK_HOBJECT_IS_PROXY(obj))) {
59103 		/* Must have array part and no conflicting exotic behaviors.
59104 		 * Doesn't need to have array special behavior, e.g. Arguments
59105 		 * object has array part.
59106 		 */
59107 		return NULL;
59108 	}
59109 
59110 	/* Arrays never have other exotic behaviors. */
59111 
59112 	DUK_DDD(DUK_DDDPRINT("fast path attempt (no exotic string/arguments/buffer "
59113 	                     "behavior, object has array part)"));
59114 
59115 #if defined(DUK_USE_FASTINT)
59116 	if (DUK_TVAL_IS_FASTINT(tv_key)) {
59117 		idx = duk__tval_fastint_to_arr_idx(tv_key);
59118 	} else
59119 #endif
59120 	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
59121 		idx = duk__tval_number_to_arr_idx(tv_key);
59122 	} else {
59123 		DUK_DDD(DUK_DDDPRINT("key is not a number"));
59124 		return NULL;
59125 	}
59126 
59127 	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
59128 	 * is 0xffffffffUL.  We don't need to check for that explicitly
59129 	 * because 0xffffffffUL will never be inside object 'a_size'.
59130 	 */
59131 
59132 	if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
59133 		DUK_DDD(DUK_DDDPRINT("key is not an array index or outside array part"));
59134 		return NULL;
59135 	}
59136 	DUK_ASSERT(idx != 0xffffffffUL);
59137 	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
59138 
59139 	/* XXX: for array instances we could take a shortcut here and assume
59140 	 * Array.prototype doesn't contain an array index property.
59141 	 */
59142 
59143 	DUK_DDD(DUK_DDDPRINT("key is a valid array index and inside array part"));
59144 	tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx);
59145 	if (!DUK_TVAL_IS_UNUSED(tv)) {
59146 		DUK_DDD(DUK_DDDPRINT("-> fast path successful"));
59147 		return tv;
59148 	}
59149 
59150 	DUK_DDD(DUK_DDDPRINT("fast path attempt failed, fall back to slow path"));
59151 	return NULL;
59152 }
59153 
59154 DUK_LOCAL duk_bool_t duk__putprop_shallow_fastpath_array_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key, duk_tval *tv_val) {
59155 	duk_tval *tv;
59156 	duk_harray *a;
59157 	duk_uint32_t idx;
59158 	duk_uint32_t old_len, new_len;
59159 
59160 	if (!(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj) &&
59161 	      DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
59162 	      DUK_HOBJECT_HAS_EXTENSIBLE(obj))) {
59163 		return 0;
59164 	}
59165 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));  /* caller ensures */
59166 
59167 	a = (duk_harray *) obj;
59168 	DUK_HARRAY_ASSERT_VALID(a);
59169 
59170 #if defined(DUK_USE_FASTINT)
59171 	if (DUK_TVAL_IS_FASTINT(tv_key)) {
59172 		idx = duk__tval_fastint_to_arr_idx(tv_key);
59173 	} else
59174 #endif
59175 	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
59176 		idx = duk__tval_number_to_arr_idx(tv_key);
59177 	} else {
59178 		DUK_DDD(DUK_DDDPRINT("key is not a number"));
59179 		return 0;
59180 	}
59181 
59182 	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
59183 	 * is 0xffffffffUL.  We don't need to check for that explicitly
59184 	 * because 0xffffffffUL will never be inside object 'a_size'.
59185 	 */
59186 
59187 	if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) {  /* for resizing of array part, use slow path */
59188 		return 0;
59189 	}
59190 	DUK_ASSERT(idx != 0xffffffffUL);
59191 	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
59192 
59193 	old_len = a->length;
59194 
59195 	if (idx >= old_len) {
59196 		DUK_DDD(DUK_DDDPRINT("write new array entry requires length update "
59197 		                     "(arr_idx=%ld, old_len=%ld)",
59198 		                     (long) idx, (long) old_len));
59199 		if (DUK_HARRAY_LENGTH_NONWRITABLE(a)) {
59200 			/* The correct behavior here is either a silent error
59201 			 * or a TypeError, depending on strictness.  Fall back
59202 			 * to the slow path to handle the situation.
59203 			 */
59204 			return 0;
59205 		}
59206 		new_len = idx + 1;
59207 
59208 		((duk_harray *) obj)->length = new_len;
59209 	}
59210 
59211 	tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx);
59212 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val);  /* side effects */
59213 
59214 	DUK_DDD(DUK_DDDPRINT("array fast path success for index %ld", (long) idx));
59215 	return 1;
59216 }
59217 #endif  /* DUK_USE_ARRAY_PROP_FASTPATH */
59218 
59219 /*
59220  *  Fast path for bufobj getprop/putprop
59221  */
59222 
59223 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
59224 DUK_LOCAL duk_bool_t duk__getprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key) {
59225 	duk_uint32_t idx;
59226 	duk_hbufobj *h_bufobj;
59227 	duk_uint_t byte_off;
59228 	duk_small_uint_t elem_size;
59229 	duk_uint8_t *data;
59230 
59231 	if (!DUK_HOBJECT_IS_BUFOBJ(obj)) {
59232 		return 0;
59233 	}
59234 	h_bufobj = (duk_hbufobj *) obj;
59235 	if (!DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
59236 		return 0;
59237 	}
59238 
59239 #if defined(DUK_USE_FASTINT)
59240 	if (DUK_TVAL_IS_FASTINT(tv_key)) {
59241 		idx = duk__tval_fastint_to_arr_idx(tv_key);
59242 	} else
59243 #endif
59244 	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
59245 		idx = duk__tval_number_to_arr_idx(tv_key);
59246 	} else {
59247 		return 0;
59248 	}
59249 
59250 	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
59251 	 * is 0xffffffffUL.  We don't need to check for that explicitly
59252 	 * because 0xffffffffUL will never be inside bufobj length.
59253 	 */
59254 
59255 	/* Careful with wrapping (left shifting idx would be unsafe). */
59256 	if (idx >= (h_bufobj->length >> h_bufobj->shift)) {
59257 		return 0;
59258 	}
59259 	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
59260 
59261 	byte_off = idx << h_bufobj->shift;  /* no wrap assuming h_bufobj->length is valid */
59262 	elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
59263 
59264 	if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
59265 		data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
59266 		duk_hbufobj_push_validated_read(thr, h_bufobj, data, elem_size);
59267 	} else {
59268 		DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (read zero)"));
59269 		duk_push_uint(thr, 0);
59270 	}
59271 
59272 	return 1;
59273 }
59274 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
59275 
59276 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
59277 DUK_LOCAL duk_bool_t duk__putprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key, duk_tval *tv_val) {
59278 	duk_uint32_t idx;
59279 	duk_hbufobj *h_bufobj;
59280 	duk_uint_t byte_off;
59281 	duk_small_uint_t elem_size;
59282 	duk_uint8_t *data;
59283 
59284 	if (!(DUK_HOBJECT_IS_BUFOBJ(obj) &&
59285 	      DUK_TVAL_IS_NUMBER(tv_val))) {
59286 		return 0;
59287 	}
59288 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));  /* caller ensures; rom objects are never bufobjs now */
59289 
59290 	h_bufobj = (duk_hbufobj *) obj;
59291 	if (!DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
59292 		return 0;
59293 	}
59294 
59295 #if defined(DUK_USE_FASTINT)
59296 	if (DUK_TVAL_IS_FASTINT(tv_key)) {
59297 		idx = duk__tval_fastint_to_arr_idx(tv_key);
59298 	} else
59299 #endif
59300 	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
59301 		idx = duk__tval_number_to_arr_idx(tv_key);
59302 	} else {
59303 		return 0;
59304 	}
59305 
59306 	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
59307 	 * is 0xffffffffUL.  We don't need to check for that explicitly
59308 	 * because 0xffffffffUL will never be inside bufobj length.
59309 	 */
59310 
59311 	/* Careful with wrapping (left shifting idx would be unsafe). */
59312 	if (idx >= (h_bufobj->length >> h_bufobj->shift)) {
59313 		return 0;
59314 	}
59315 	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
59316 
59317 	byte_off = idx << h_bufobj->shift;  /* no wrap assuming h_bufobj->length is valid */
59318 	elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
59319 
59320 	/* Value is required to be a number in the fast path so there
59321 	 * are no side effects in write coercion.
59322 	 */
59323 	duk_push_tval(thr, tv_val);
59324 	DUK_ASSERT(duk_is_number(thr, -1));
59325 
59326 	if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
59327 		data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
59328 		duk_hbufobj_validated_write(thr, h_bufobj, data, elem_size);
59329 	} else {
59330 		DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (write skipped)"));
59331 	}
59332 
59333 	duk_pop_unsafe(thr);
59334 	return 1;
59335 }
59336 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
59337 
59338 /*
59339  *  GETPROP: ECMAScript property read.
59340  */
59341 
59342 DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) {
59343 	duk_tval tv_obj_copy;
59344 	duk_tval tv_key_copy;
59345 	duk_hobject *curr = NULL;
59346 	duk_hstring *key = NULL;
59347 	duk_uint32_t arr_idx = DUK__NO_ARRAY_INDEX;
59348 	duk_propdesc desc;
59349 	duk_uint_t sanity;
59350 
59351 	DUK_DDD(DUK_DDDPRINT("getprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
59352 	                     (void *) thr, (void *) tv_obj, (void *) tv_key,
59353 	                     (duk_tval *) tv_obj, (duk_tval *) tv_key));
59354 
59355 	DUK_ASSERT(thr != NULL);
59356 	DUK_ASSERT(thr->heap != NULL);
59357 	DUK_ASSERT(tv_obj != NULL);
59358 	DUK_ASSERT(tv_key != NULL);
59359 
59360 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
59361 
59362 	DUK_STATS_INC(thr->heap, stats_getprop_all);
59363 
59364 	/*
59365 	 *  Make a copy of tv_obj, tv_key, and tv_val to avoid any issues of
59366 	 *  them being invalidated by a valstack resize.
59367 	 *
59368 	 *  XXX: this is now an overkill for many fast paths.  Rework this
59369 	 *  to be faster (although switching to a valstack discipline might
59370 	 *  be a better solution overall).
59371 	 */
59372 
59373 	DUK_TVAL_SET_TVAL(&tv_obj_copy, tv_obj);
59374 	DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
59375 	tv_obj = &tv_obj_copy;
59376 	tv_key = &tv_key_copy;
59377 
59378 	/*
59379 	 *  Coercion and fast path processing
59380 	 */
59381 
59382 	switch (DUK_TVAL_GET_TAG(tv_obj)) {
59383 	case DUK_TAG_UNDEFINED:
59384 	case DUK_TAG_NULL: {
59385 		/* Note: unconditional throw */
59386 		DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject"));
59387 #if defined(DUK_USE_PARANOID_ERRORS)
59388 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
59389 #else
59390 		DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot read property %s of %s",
59391 		               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
59392 #endif
59393 		DUK_WO_NORETURN(return 0;);
59394 		break;
59395 	}
59396 
59397 	case DUK_TAG_BOOLEAN: {
59398 		DUK_DDD(DUK_DDDPRINT("base object is a boolean, start lookup from boolean prototype"));
59399 		curr = thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE];
59400 		break;
59401 	}
59402 
59403 	case DUK_TAG_STRING: {
59404 		duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
59405 		duk_int_t pop_count;
59406 
59407 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
59408 			/* Symbols (ES2015 or hidden) don't have virtual properties. */
59409 			DUK_DDD(DUK_DDDPRINT("base object is a symbol, start lookup from symbol prototype"));
59410 			curr = thr->builtins[DUK_BIDX_SYMBOL_PROTOTYPE];
59411 			break;
59412 		}
59413 
59414 #if defined(DUK_USE_FASTINT)
59415 		if (DUK_TVAL_IS_FASTINT(tv_key)) {
59416 			arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
59417 			DUK_DDD(DUK_DDDPRINT("base object string, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
59418 			pop_count = 0;
59419 		} else
59420 #endif
59421 		if (DUK_TVAL_IS_NUMBER(tv_key)) {
59422 			arr_idx = duk__tval_number_to_arr_idx(tv_key);
59423 			DUK_DDD(DUK_DDDPRINT("base object string, key is a fast-path number; arr_idx %ld", (long) arr_idx));
59424 			pop_count = 0;
59425 		} else {
59426 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
59427 			DUK_ASSERT(key != NULL);
59428 			DUK_DDD(DUK_DDDPRINT("base object string, key is a non-fast-path number; after "
59429 			                     "coercion key is %!T, arr_idx %ld",
59430 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
59431 			pop_count = 1;
59432 		}
59433 
59434 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
59435 		    arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
59436 			duk_pop_n_unsafe(thr, pop_count);
59437 			duk_push_hstring(thr, h);
59438 			duk_substring(thr, -1, arr_idx, arr_idx + 1);  /* [str] -> [substr] */
59439 
59440 			DUK_STATS_INC(thr->heap, stats_getprop_stringidx);
59441 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is string, key is an index inside string length "
59442 			                     "after coercion -> return char)",
59443 			                     (duk_tval *) duk_get_tval(thr, -1)));
59444 			return 1;
59445 		}
59446 
59447 		if (pop_count == 0) {
59448 			/* This is a pretty awkward control flow, but we need to recheck the
59449 			 * key coercion here.
59450 			 */
59451 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
59452 			DUK_ASSERT(key != NULL);
59453 			DUK_DDD(DUK_DDDPRINT("base object string, key is a non-fast-path number; after "
59454 			                     "coercion key is %!T, arr_idx %ld",
59455 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
59456 		}
59457 
59458 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
59459 			duk_pop_unsafe(thr);  /* [key] -> [] */
59460 			duk_push_uint(thr, (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h));  /* [] -> [res] */
59461 
59462 			DUK_STATS_INC(thr->heap, stats_getprop_stringlen);
59463 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is string, key is 'length' after coercion -> "
59464 			                     "return string length)",
59465 			                     (duk_tval *) duk_get_tval(thr, -1)));
59466 			return 1;
59467 		}
59468 
59469 		DUK_DDD(DUK_DDDPRINT("base object is a string, start lookup from string prototype"));
59470 		curr = thr->builtins[DUK_BIDX_STRING_PROTOTYPE];
59471 		goto lookup;  /* avoid double coercion */
59472 	}
59473 
59474 	case DUK_TAG_OBJECT: {
59475 #if defined(DUK_USE_ARRAY_PROP_FASTPATH)
59476 		duk_tval *tmp;
59477 #endif
59478 
59479 		curr = DUK_TVAL_GET_OBJECT(tv_obj);
59480 		DUK_ASSERT(curr != NULL);
59481 
59482 		/* XXX: array .length fast path (important in e.g. loops)? */
59483 
59484 #if defined(DUK_USE_ARRAY_PROP_FASTPATH)
59485 		tmp = duk__getprop_shallow_fastpath_array_tval(thr, curr, tv_key);
59486 		if (tmp) {
59487 			duk_push_tval(thr, tmp);
59488 
59489 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is object, key is a number, array part "
59490 			                     "fast path)",
59491 			                     (duk_tval *) duk_get_tval(thr, -1)));
59492 			DUK_STATS_INC(thr->heap, stats_getprop_arrayidx);
59493 			return 1;
59494 		}
59495 #endif
59496 
59497 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
59498 		if (duk__getprop_fastpath_bufobj_tval(thr, curr, tv_key) != 0) {
59499 			/* Read value pushed on stack. */
59500 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is bufobj, key is a number, bufobj "
59501 			                     "fast path)",
59502 			                     (duk_tval *) duk_get_tval(thr, -1)));
59503 			DUK_STATS_INC(thr->heap, stats_getprop_bufobjidx);
59504 			return 1;
59505 		}
59506 #endif
59507 
59508 #if defined(DUK_USE_ES6_PROXY)
59509 		if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(curr))) {
59510 			duk_hobject *h_target;
59511 
59512 			if (duk__proxy_check_prop(thr, curr, DUK_STRIDX_GET, tv_key, &h_target)) {
59513 				/* -> [ ... trap handler ] */
59514 				DUK_DDD(DUK_DDDPRINT("-> proxy object 'get' for key %!T", (duk_tval *) tv_key));
59515 				DUK_STATS_INC(thr->heap, stats_getprop_proxy);
59516 				duk_push_hobject(thr, h_target);  /* target */
59517 				duk_push_tval(thr, tv_key);       /* P */
59518 				duk_push_tval(thr, tv_obj);       /* Receiver: Proxy object */
59519 				duk_call_method(thr, 3 /*nargs*/);
59520 
59521 				/* Target object must be checked for a conflicting
59522 				 * non-configurable property.
59523 				 */
59524 				arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
59525 				DUK_ASSERT(key != NULL);
59526 
59527 				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
59528 					duk_tval *tv_hook = duk_require_tval(thr, -3);  /* value from hook */
59529 					duk_tval *tv_targ = duk_require_tval(thr, -1);  /* value from target */
59530 					duk_bool_t datadesc_reject;
59531 					duk_bool_t accdesc_reject;
59532 
59533 					DUK_DDD(DUK_DDDPRINT("proxy 'get': target has matching property %!O, check for "
59534 					                     "conflicting property; tv_hook=%!T, tv_targ=%!T, desc.flags=0x%08lx, "
59535 					                     "desc.get=%p, desc.set=%p",
59536 					                     (duk_heaphdr *) key, (duk_tval *) tv_hook, (duk_tval *) tv_targ,
59537 					                     (unsigned long) desc.flags,
59538 					                     (void *) desc.get, (void *) desc.set));
59539 
59540 					datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
59541 					                  !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
59542 					                  !(desc.flags & DUK_PROPDESC_FLAG_WRITABLE) &&
59543 					                  !duk_js_samevalue(tv_hook, tv_targ);
59544 					accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
59545 					                 !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
59546 					                 (desc.get == NULL) &&
59547 					                 !DUK_TVAL_IS_UNDEFINED(tv_hook);
59548 					if (datadesc_reject || accdesc_reject) {
59549 						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
59550 						DUK_WO_NORETURN(return 0;);
59551 					}
59552 
59553 					duk_pop_2_unsafe(thr);
59554 				} else {
59555 					duk_pop_unsafe(thr);
59556 				}
59557 				return 1;  /* return value */
59558 			}
59559 
59560 			curr = h_target;  /* resume lookup from target */
59561 			DUK_TVAL_SET_OBJECT(tv_obj, curr);
59562 		}
59563 #endif  /* DUK_USE_ES6_PROXY */
59564 
59565 		if (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(curr)) {
59566 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
59567 			DUK_ASSERT(key != NULL);
59568 
59569 			DUK_STATS_INC(thr->heap, stats_getprop_arguments);
59570 			if (duk__check_arguments_map_for_get(thr, curr, key, &desc)) {
59571 				DUK_DDD(DUK_DDDPRINT("-> %!T (base is object with arguments exotic behavior, "
59572 				                     "key matches magically bound property -> skip standard "
59573 				                     "Get with replacement value)",
59574 				                     (duk_tval *) duk_get_tval(thr, -1)));
59575 
59576 				/* no need for 'caller' post-check, because 'key' must be an array index */
59577 
59578 				duk_remove_m2(thr);  /* [key result] -> [result] */
59579 				return 1;
59580 			}
59581 
59582 			goto lookup;  /* avoid double coercion */
59583 		}
59584 		break;
59585 	}
59586 
59587 	/* Buffer has virtual properties similar to string, but indexed values
59588 	 * are numbers, not 1-byte buffers/strings which would perform badly.
59589 	 */
59590 	case DUK_TAG_BUFFER: {
59591 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
59592 		duk_int_t pop_count;
59593 
59594 		/*
59595 		 *  Because buffer values are often looped over, a number fast path
59596 		 *  is important.
59597 		 */
59598 
59599 #if defined(DUK_USE_FASTINT)
59600 		if (DUK_TVAL_IS_FASTINT(tv_key)) {
59601 			arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
59602 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
59603 			pop_count = 0;
59604 		}
59605 		else
59606 #endif
59607 		if (DUK_TVAL_IS_NUMBER(tv_key)) {
59608 			arr_idx = duk__tval_number_to_arr_idx(tv_key);
59609 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path number; arr_idx %ld", (long) arr_idx));
59610 			pop_count = 0;
59611 		} else {
59612 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
59613 			DUK_ASSERT(key != NULL);
59614 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
59615 			                     "coercion key is %!T, arr_idx %ld",
59616 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
59617 			pop_count = 1;
59618 		}
59619 
59620 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
59621 		    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
59622 			duk_pop_n_unsafe(thr, pop_count);
59623 			duk_push_uint(thr, ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h))[arr_idx]);
59624 			DUK_STATS_INC(thr->heap, stats_getprop_bufferidx);
59625 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is an index inside buffer length "
59626 			                     "after coercion -> return byte as number)",
59627 			                     (duk_tval *) duk_get_tval(thr, -1)));
59628 			return 1;
59629 		}
59630 
59631 		if (pop_count == 0) {
59632 			/* This is a pretty awkward control flow, but we need to recheck the
59633 			 * key coercion here.
59634 			 */
59635 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
59636 			DUK_ASSERT(key != NULL);
59637 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
59638 			                     "coercion key is %!T, arr_idx %ld",
59639 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
59640 		}
59641 
59642 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
59643 			duk_pop_unsafe(thr);  /* [key] -> [] */
59644 			duk_push_uint(thr, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h));  /* [] -> [res] */
59645 			DUK_STATS_INC(thr->heap, stats_getprop_bufferlen);
59646 
59647 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is 'length' "
59648 			                     "after coercion -> return buffer length)",
59649 			                     (duk_tval *) duk_get_tval(thr, -1)));
59650 			return 1;
59651 		}
59652 
59653 		DUK_DDD(DUK_DDDPRINT("base object is a buffer, start lookup from Uint8Array prototype"));
59654 		curr = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
59655 		goto lookup;  /* avoid double coercion */
59656 	}
59657 
59658 	case DUK_TAG_POINTER: {
59659 		DUK_DDD(DUK_DDDPRINT("base object is a pointer, start lookup from pointer prototype"));
59660 		curr = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];
59661 		break;
59662 	}
59663 
59664 	case DUK_TAG_LIGHTFUNC: {
59665 		/* Lightfuncs inherit getter .name and .length from %NativeFunctionPrototype%. */
59666 		DUK_DDD(DUK_DDDPRINT("base object is a lightfunc, start lookup from function prototype"));
59667 		curr = thr->builtins[DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE];
59668 		break;
59669 	}
59670 
59671 #if defined(DUK_USE_FASTINT)
59672 	case DUK_TAG_FASTINT:
59673 #endif
59674 	default: {
59675 		/* number */
59676 		DUK_DDD(DUK_DDDPRINT("base object is a number, start lookup from number prototype"));
59677 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_obj));
59678 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_obj));
59679 		curr = thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE];
59680 		break;
59681 	}
59682 	}
59683 
59684 	/* key coercion (unless already coerced above) */
59685 	DUK_ASSERT(key == NULL);
59686 	arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
59687 	DUK_ASSERT(key != NULL);
59688 	/*
59689 	 *  Property lookup
59690 	 */
59691 
59692  lookup:
59693 	/* [key] (coerced) */
59694 	DUK_ASSERT(curr != NULL);
59695 	DUK_ASSERT(key != NULL);
59696 
59697 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
59698 	do {
59699 		if (!duk__get_own_propdesc_raw(thr, curr, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
59700 			goto next_in_chain;
59701 		}
59702 
59703 		if (desc.get != NULL) {
59704 			/* accessor with defined getter */
59705 			DUK_ASSERT((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) != 0);
59706 
59707 			duk_pop_unsafe(thr);              /* [key undefined] -> [key] */
59708 			duk_push_hobject(thr, desc.get);
59709 			duk_push_tval(thr, tv_obj);       /* note: original, uncoerced base */
59710 #if defined(DUK_USE_NONSTD_GETTER_KEY_ARGUMENT)
59711 			duk_dup_m3(thr);
59712 			duk_call_method(thr, 1);          /* [key getter this key] -> [key retval] */
59713 #else
59714 			duk_call_method(thr, 0);          /* [key getter this] -> [key retval] */
59715 #endif
59716 		} else {
59717 			/* [key value] or [key undefined] */
59718 
59719 			/* data property or accessor without getter */
59720 			DUK_ASSERT(((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0) ||
59721 			           (desc.get == NULL));
59722 
59723 			/* if accessor without getter, return value is undefined */
59724 			DUK_ASSERT(((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0) ||
59725 			           duk_is_undefined(thr, -1));
59726 
59727 			/* Note: for an accessor without getter, falling through to
59728 			 * check for "caller" exotic behavior is unnecessary as
59729 			 * "undefined" will never activate the behavior.  But it does
59730 			 * no harm, so we'll do it anyway.
59731 			 */
59732 		}
59733 
59734 		goto found;  /* [key result] */
59735 
59736 	 next_in_chain:
59737 		/* XXX: option to pretend property doesn't exist if sanity limit is
59738 		 * hit might be useful.
59739 		 */
59740 		if (DUK_UNLIKELY(sanity-- == 0)) {
59741 			DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
59742 			DUK_WO_NORETURN(return 0;);
59743 		}
59744 		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
59745 	} while (curr != NULL);
59746 
59747 	/*
59748 	 *  Not found
59749 	 */
59750 
59751 	duk_to_undefined(thr, -1);  /* [key] -> [undefined] (default value) */
59752 
59753 	DUK_DDD(DUK_DDDPRINT("-> %!T (not found)", (duk_tval *) duk_get_tval(thr, -1)));
59754 	return 0;
59755 
59756 	/*
59757 	 *  Found; post-processing (Function and arguments objects)
59758 	 */
59759 
59760  found:
59761 	/* [key result] */
59762 
59763 #if !defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
59764 	/* Special behavior for 'caller' property of (non-bound) function objects
59765 	 * and non-strict Arguments objects: if 'caller' -value- (!) is a strict
59766 	 * mode function, throw a TypeError (E5 Sections 15.3.5.4, 10.6).
59767 	 * Quite interestingly, a non-strict function with no formal arguments
59768 	 * will get an arguments object -without- special 'caller' behavior!
59769 	 *
59770 	 * The E5.1 spec is a bit ambiguous if this special behavior applies when
59771 	 * a bound function is the base value (not the 'caller' value): Section
59772 	 * 15.3.4.5 (describing bind()) states that [[Get]] for bound functions
59773 	 * matches that of Section 15.3.5.4 ([[Get]] for Function instances).
59774 	 * However, Section 13.3.5.4 has "NOTE: Function objects created using
59775 	 * Function.prototype.bind use the default [[Get]] internal method."
59776 	 * The current implementation assumes this means that bound functions
59777 	 * should not have the special [[Get]] behavior.
59778 	 *
59779 	 * The E5.1 spec is also a bit unclear if the TypeError throwing is
59780 	 * applied if the 'caller' value is a strict bound function.  The
59781 	 * current implementation will throw even for both strict non-bound
59782 	 * and strict bound functions.
59783 	 *
59784 	 * See test-dev-strict-func-as-caller-prop-value.js for quite extensive
59785 	 * tests.
59786 	 *
59787 	 * This exotic behavior is disabled when the non-standard 'caller' property
59788 	 * is enabled, as it conflicts with the free use of 'caller'.
59789 	 */
59790 	if (key == DUK_HTHREAD_STRING_CALLER(thr) &&
59791 	    DUK_TVAL_IS_OBJECT(tv_obj)) {
59792 		duk_hobject *orig = DUK_TVAL_GET_OBJECT(tv_obj);
59793 		DUK_ASSERT(orig != NULL);
59794 
59795 		if (DUK_HOBJECT_IS_NONBOUND_FUNCTION(orig) ||
59796 		    DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(orig)) {
59797 			duk_hobject *h;
59798 
59799 			/* XXX: The TypeError is currently not applied to bound
59800 			 * functions because the 'strict' flag is not copied by
59801 			 * bind().  This may or may not be correct, the specification
59802 			 * only refers to the value being a "strict mode Function
59803 			 * object" which is ambiguous.
59804 			 */
59805 			DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(orig));
59806 
59807 			h = duk_get_hobject(thr, -1);  /* NULL if not an object */
59808 			if (h &&
59809 			    DUK_HOBJECT_IS_FUNCTION(h) &&
59810 			    DUK_HOBJECT_HAS_STRICT(h)) {
59811 				/* XXX: sufficient to check 'strict', assert for 'is function' */
59812 				DUK_ERROR_TYPE(thr, DUK_STR_STRICT_CALLER_READ);
59813 				DUK_WO_NORETURN(return 0;);
59814 			}
59815 		}
59816 	}
59817 #endif   /* !DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */
59818 
59819 	duk_remove_m2(thr);  /* [key result] -> [result] */
59820 
59821 	DUK_DDD(DUK_DDDPRINT("-> %!T (found)", (duk_tval *) duk_get_tval(thr, -1)));
59822 	return 1;
59823 }
59824 
59825 /*
59826  *  HASPROP: ECMAScript property existence check ("in" operator).
59827  *
59828  *  Interestingly, the 'in' operator does not do any coercion of
59829  *  the target object.
59830  */
59831 
59832 DUK_INTERNAL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) {
59833 	duk_tval tv_key_copy;
59834 	duk_hobject *obj;
59835 	duk_hstring *key;
59836 	duk_uint32_t arr_idx;
59837 	duk_bool_t rc;
59838 	duk_propdesc desc;
59839 
59840 	DUK_DDD(DUK_DDDPRINT("hasprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
59841 	                     (void *) thr, (void *) tv_obj, (void *) tv_key,
59842 	                     (duk_tval *) tv_obj, (duk_tval *) tv_key));
59843 
59844 	DUK_ASSERT(thr != NULL);
59845 	DUK_ASSERT(thr->heap != NULL);
59846 	DUK_ASSERT(tv_obj != NULL);
59847 	DUK_ASSERT(tv_key != NULL);
59848 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
59849 
59850 	DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
59851 	tv_key = &tv_key_copy;
59852 
59853 	/*
59854 	 *  The 'in' operator requires an object as its right hand side,
59855 	 *  throwing a TypeError unconditionally if this is not the case.
59856 	 *
59857 	 *  However, lightfuncs need to behave like fully fledged objects
59858 	 *  here to be maximally transparent, so we need to handle them
59859 	 *  here.  Same goes for plain buffers which behave like ArrayBuffers.
59860 	 */
59861 
59862 	/* XXX: Refactor key coercion so that it's only called once.  It can't
59863 	 * be trivially lifted here because the object must be type checked
59864 	 * first.
59865 	 */
59866 
59867 	if (DUK_TVAL_IS_OBJECT(tv_obj)) {
59868 		obj = DUK_TVAL_GET_OBJECT(tv_obj);
59869 		DUK_ASSERT(obj != NULL);
59870 
59871 		arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
59872 	} else if (DUK_TVAL_IS_BUFFER(tv_obj)) {
59873 		arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
59874 		if (duk__key_is_plain_buf_ownprop(thr, DUK_TVAL_GET_BUFFER(tv_obj), key, arr_idx)) {
59875 			rc = 1;
59876 			goto pop_and_return;
59877 		}
59878 		obj = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
59879 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_obj)) {
59880 		arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
59881 
59882 		/* If not found, resume existence check from %NativeFunctionPrototype%.
59883 		 * We can just substitute the value in this case; nothing will
59884 		 * need the original base value (as would be the case with e.g.
59885 		 * setters/getters.
59886 		 */
59887 		obj = thr->builtins[DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE];
59888 	} else {
59889 		/* Note: unconditional throw */
59890 		DUK_DDD(DUK_DDDPRINT("base object is not an object -> reject"));
59891 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
59892 		DUK_WO_NORETURN(return 0;);
59893 	}
59894 
59895 	/* XXX: fast path for arrays? */
59896 
59897 	DUK_ASSERT(key != NULL);
59898 	DUK_ASSERT(obj != NULL);
59899 	DUK_UNREF(arr_idx);
59900 
59901 #if defined(DUK_USE_ES6_PROXY)
59902 	if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(obj))) {
59903 		duk_hobject *h_target;
59904 		duk_bool_t tmp_bool;
59905 
59906 		/* XXX: the key in 'key in obj' is string coerced before we're called
59907 		 * (which is the required behavior in E5/E5.1/E6) so the key is a string
59908 		 * here already.
59909 		 */
59910 
59911 		if (duk__proxy_check_prop(thr, obj, DUK_STRIDX_HAS, tv_key, &h_target)) {
59912 			/* [ ... key trap handler ] */
59913 			DUK_DDD(DUK_DDDPRINT("-> proxy object 'has' for key %!T", (duk_tval *) tv_key));
59914 			duk_push_hobject(thr, h_target);  /* target */
59915 			duk_push_tval(thr, tv_key);       /* P */
59916 			duk_call_method(thr, 2 /*nargs*/);
59917 			tmp_bool = duk_to_boolean_top_pop(thr);
59918 			if (!tmp_bool) {
59919 				/* Target object must be checked for a conflicting
59920 				 * non-configurable property.
59921 				 */
59922 
59923 				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
59924 					DUK_DDD(DUK_DDDPRINT("proxy 'has': target has matching property %!O, check for "
59925 					                     "conflicting property; desc.flags=0x%08lx, "
59926 					                     "desc.get=%p, desc.set=%p",
59927 					                     (duk_heaphdr *) key, (unsigned long) desc.flags,
59928 					                     (void *) desc.get, (void *) desc.set));
59929 					/* XXX: Extensibility check for target uses IsExtensible().  If we
59930 					 * implemented the isExtensible trap and didn't reject proxies as
59931 					 * proxy targets, it should be respected here.
59932 					 */
59933 					if (!((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&  /* property is configurable and */
59934 					      DUK_HOBJECT_HAS_EXTENSIBLE(h_target))) {          /* ... target is extensible */
59935 						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
59936 						DUK_WO_NORETURN(return 0;);
59937 					}
59938 				}
59939 			}
59940 
59941 			duk_pop_unsafe(thr);  /* [ key ] -> [] */
59942 			return tmp_bool;
59943 		}
59944 
59945 		obj = h_target;  /* resume check from proxy target */
59946 	}
59947 #endif  /* DUK_USE_ES6_PROXY */
59948 
59949 	/* XXX: inline into a prototype walking loop? */
59950 
59951 	rc = duk__get_propdesc(thr, obj, key, &desc, 0 /*flags*/);  /* don't push value */
59952 	/* fall through */
59953 
59954  pop_and_return:
59955 	duk_pop_unsafe(thr);  /* [ key ] -> [] */
59956 	return rc;
59957 }
59958 
59959 /*
59960  *  HASPROP variant used internally.
59961  *
59962  *  This primitive must never throw an error, callers rely on this.
59963  *  In particular, don't throw an error for prototype loops; instead,
59964  *  pretend like the property doesn't exist if a prototype sanity limit
59965  *  is reached.
59966  *
59967  *  Does not implement proxy behavior: if applied to a proxy object,
59968  *  returns key existence on the proxy object itself.
59969  */
59970 
59971 DUK_INTERNAL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key) {
59972 	duk_propdesc dummy;
59973 
59974 	DUK_ASSERT(thr != NULL);
59975 	DUK_ASSERT(thr->heap != NULL);
59976 	DUK_ASSERT(obj != NULL);
59977 	DUK_ASSERT(key != NULL);
59978 
59979 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
59980 
59981 	return duk__get_propdesc(thr, obj, key, &dummy, DUK_GETDESC_FLAG_IGNORE_PROTOLOOP);  /* don't push value */
59982 }
59983 
59984 /*
59985  *  Helper: handle Array object 'length' write which automatically
59986  *  deletes properties, see E5 Section 15.4.5.1, step 3.  This is
59987  *  quite tricky to get right.
59988  *
59989  *  Used by duk_hobject_putprop().
59990  */
59991 
59992 /* Coerce a new .length candidate to a number and check that it's a valid
59993  * .length.
59994  */
59995 DUK_LOCAL duk_uint32_t duk__to_new_array_length_checked(duk_hthread *thr, duk_tval *tv) {
59996 	duk_uint32_t res;
59997 	duk_double_t d;
59998 
59999 #if !defined(DUK_USE_PREFER_SIZE)
60000 #if defined(DUK_USE_FASTINT)
60001 	/* When fastints are enabled, the most interesting case is assigning
60002 	 * a fastint to .length (e.g. arr.length = 0).
60003 	 */
60004 	if (DUK_TVAL_IS_FASTINT(tv)) {
60005 		/* Very common case. */
60006 		duk_int64_t fi;
60007 		fi = DUK_TVAL_GET_FASTINT(tv);
60008 		if (fi < 0 || fi > DUK_I64_CONSTANT(0xffffffff)) {
60009 			goto fail_range;
60010 		}
60011 		return (duk_uint32_t) fi;
60012 	}
60013 #else  /* DUK_USE_FASTINT */
60014 	/* When fastints are not enabled, the most interesting case is any
60015 	 * number.
60016 	 */
60017 	if (DUK_TVAL_IS_DOUBLE(tv)) {
60018 		d = DUK_TVAL_GET_NUMBER(tv);
60019 	}
60020 #endif  /* DUK_USE_FASTINT */
60021 	else
60022 #endif  /* !DUK_USE_PREFER_SIZE */
60023 	{
60024 		/* In all other cases, and when doing a size optimized build,
60025 		 * fall back to the comprehensive handler.
60026 		 */
60027 		d = duk_js_tonumber(thr, tv);
60028 	}
60029 
60030 	/* Refuse to update an Array's 'length' to a value outside the
60031 	 * 32-bit range.  Negative zero is accepted as zero.
60032 	 */
60033 	res = duk_double_to_uint32_t(d);
60034 	if (!duk_double_equals((duk_double_t) res, d)) {
60035 		goto fail_range;
60036 	}
60037 
60038 	return res;
60039 
60040  fail_range:
60041 	DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARRAY_LENGTH);
60042 	DUK_WO_NORETURN(return 0;);
60043 }
60044 
60045 /* Delete elements required by a smaller length, taking into account
60046  * potentially non-configurable elements.  Returns non-zero if all
60047  * elements could be deleted, and zero if all or some elements could
60048  * not be deleted.  Also writes final "target length" to 'out_result_len'.
60049  * This is the length value that should go into the 'length' property
60050  * (must be set by the caller).  Never throws an error.
60051  */
60052 DUK_LOCAL
60053 duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr,
60054                                                 duk_hobject *obj,
60055                                                 duk_uint32_t old_len,
60056                                                 duk_uint32_t new_len,
60057                                                 duk_bool_t force_flag,
60058                                                 duk_uint32_t *out_result_len) {
60059 	duk_uint32_t target_len;
60060 	duk_uint_fast32_t i;
60061 	duk_uint32_t arr_idx;
60062 	duk_hstring *key;
60063 	duk_tval *tv;
60064 	duk_bool_t rc;
60065 
60066 	DUK_DDD(DUK_DDDPRINT("new array length smaller than old (%ld -> %ld), "
60067 	                     "probably need to remove elements",
60068 	                     (long) old_len, (long) new_len));
60069 
60070 	/*
60071 	 *  New length is smaller than old length, need to delete properties above
60072 	 *  the new length.
60073 	 *
60074 	 *  If array part exists, this is straightforward: array entries cannot
60075 	 *  be non-configurable so this is guaranteed to work.
60076 	 *
60077 	 *  If array part does not exist, array-indexed values are scattered
60078 	 *  in the entry part, and some may not be configurable (preventing length
60079 	 *  from becoming lower than their index + 1).  To handle the algorithm
60080 	 *  in E5 Section 15.4.5.1, step l correctly, we scan the entire property
60081 	 *  set twice.
60082 	 */
60083 
60084 	DUK_ASSERT(thr != NULL);
60085 	DUK_ASSERT(obj != NULL);
60086 	DUK_ASSERT(new_len < old_len);
60087 	DUK_ASSERT(out_result_len != NULL);
60088 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
60089 
60090 	DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj));
60091 	DUK_ASSERT(DUK_HOBJECT_IS_ARRAY(obj));
60092 
60093 	if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
60094 		/*
60095 		 *  All defined array-indexed properties are in the array part
60096 		 *  (we assume the array part is comprehensive), and all array
60097 		 *  entries are writable, configurable, and enumerable.  Thus,
60098 		 *  nothing can prevent array entries from being deleted.
60099 		 */
60100 
60101 		DUK_DDD(DUK_DDDPRINT("have array part, easy case"));
60102 
60103 		if (old_len < DUK_HOBJECT_GET_ASIZE(obj)) {
60104 			/* XXX: assertion that entries >= old_len are already unused */
60105 			i = old_len;
60106 		} else {
60107 			i = DUK_HOBJECT_GET_ASIZE(obj);
60108 		}
60109 		DUK_ASSERT(i <= DUK_HOBJECT_GET_ASIZE(obj));
60110 
60111 		while (i > new_len) {
60112 			i--;
60113 			tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
60114 			DUK_TVAL_SET_UNUSED_UPDREF(thr, tv);  /* side effects */
60115 		}
60116 
60117 		*out_result_len = new_len;
60118 		return 1;
60119 	} else {
60120 		/*
60121 		 *  Entries part is a bit more complex.
60122 		 */
60123 
60124 		/* Stage 1: find highest preventing non-configurable entry (if any).
60125 		 * When forcing, ignore non-configurability.
60126 		 */
60127 
60128 		DUK_DDD(DUK_DDDPRINT("no array part, slow case"));
60129 
60130 		DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 1: find target_len "
60131 		                     "(highest preventing non-configurable entry (if any))"));
60132 
60133 		target_len = new_len;
60134 		if (force_flag) {
60135 			DUK_DDD(DUK_DDDPRINT("array length write, no array part; force flag -> skip stage 1"));
60136 			goto skip_stage1;
60137 		}
60138 		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
60139 			key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
60140 			if (!key) {
60141 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: null key", (long) i));
60142 				continue;
60143 			}
60144 			if (!DUK_HSTRING_HAS_ARRIDX(key)) {
60145 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key not an array index", (long) i));
60146 				continue;
60147 			}
60148 
60149 			DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(key));  /* XXX: macro checks for array index flag, which is unnecessary here */
60150 			arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
60151 			DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);
60152 			DUK_ASSERT(arr_idx < old_len);  /* consistency requires this */
60153 
60154 			if (arr_idx < new_len) {
60155 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is array index %ld, below new_len",
60156 				                     (long) i, (long) arr_idx));
60157 				continue;
60158 			}
60159 			if (DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i)) {
60160 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is a relevant array index %ld, but configurable",
60161 				                     (long) i, (long) arr_idx));
60162 				continue;
60163 			}
60164 
60165 			/* relevant array index is non-configurable, blocks write */
60166 			if (arr_idx >= target_len) {
60167 				DUK_DDD(DUK_DDDPRINT("entry at index %ld has arr_idx %ld, is not configurable, "
60168 				                     "update target_len %ld -> %ld",
60169 				                     (long) i, (long) arr_idx, (long) target_len,
60170 				                     (long) (arr_idx + 1)));
60171 				target_len = arr_idx + 1;
60172 			}
60173 		}
60174 	 skip_stage1:
60175 
60176 		/* stage 2: delete configurable entries above target length */
60177 
60178 		DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld, target_len=%ld",
60179 		                     (long) old_len, (long) new_len, (long) target_len));
60180 
60181 		DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 2: remove "
60182 		                     "entries >= target_len"));
60183 
60184 		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
60185 			key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
60186 			if (!key) {
60187 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: null key", (long) i));
60188 				continue;
60189 			}
60190 			if (!DUK_HSTRING_HAS_ARRIDX(key)) {
60191 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key not an array index", (long) i));
60192 				continue;
60193 			}
60194 
60195 			DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(key));  /* XXX: macro checks for array index flag, which is unnecessary here */
60196 			arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
60197 			DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);
60198 			DUK_ASSERT(arr_idx < old_len);  /* consistency requires this */
60199 
60200 			if (arr_idx < target_len) {
60201 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is array index %ld, below target_len",
60202 				                     (long) i, (long) arr_idx));
60203 				continue;
60204 			}
60205 			DUK_ASSERT(force_flag || DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i));  /* stage 1 guarantees */
60206 
60207 			DUK_DDD(DUK_DDDPRINT("delete entry index %ld: key is array index %ld",
60208 			                     (long) i, (long) arr_idx));
60209 
60210 			/*
60211 			 *  Slow delete, but we don't care as we're already in a very slow path.
60212 			 *  The delete always succeeds: key has no exotic behavior, property
60213 			 *  is configurable, and no resize occurs.
60214 			 */
60215 			rc = duk_hobject_delprop_raw(thr, obj, key, force_flag ? DUK_DELPROP_FLAG_FORCE : 0);
60216 			DUK_UNREF(rc);
60217 			DUK_ASSERT(rc != 0);
60218 		}
60219 
60220 		/* stage 3: update length (done by caller), decide return code */
60221 
60222 		DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 3: update length (done by caller)"));
60223 
60224 		*out_result_len = target_len;
60225 
60226 		if (target_len == new_len) {
60227 			DUK_DDD(DUK_DDDPRINT("target_len matches new_len, return success"));
60228 			return 1;
60229 		}
60230 		DUK_DDD(DUK_DDDPRINT("target_len does not match new_len (some entry prevented "
60231 		                     "full length adjustment), return error"));
60232 		return 0;
60233 	}
60234 
60235 	DUK_UNREACHABLE();
60236 }
60237 
60238 /* XXX: is valstack top best place for argument? */
60239 DUK_LOCAL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *obj) {
60240 	duk_harray *a;
60241 	duk_uint32_t old_len;
60242 	duk_uint32_t new_len;
60243 	duk_uint32_t result_len;
60244 	duk_bool_t rc;
60245 
60246 	DUK_DDD(DUK_DDDPRINT("handling a put operation to array 'length' exotic property, "
60247 	                     "new val: %!T",
60248 	                     (duk_tval *) duk_get_tval(thr, -1)));
60249 
60250 	DUK_ASSERT(thr != NULL);
60251 	DUK_ASSERT(obj != NULL);
60252 
60253 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
60254 
60255 	DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj));
60256 	DUK_ASSERT(DUK_HOBJECT_IS_ARRAY(obj));
60257 	a = (duk_harray *) obj;
60258 	DUK_HARRAY_ASSERT_VALID(a);
60259 
60260 	DUK_ASSERT(duk_is_valid_index(thr, -1));
60261 
60262 	/*
60263 	 *  Get old and new length
60264 	 */
60265 
60266 	old_len = a->length;
60267 	new_len = duk__to_new_array_length_checked(thr, DUK_GET_TVAL_NEGIDX(thr, -1));
60268 	DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld", (long) old_len, (long) new_len));
60269 
60270 	/*
60271 	 *  Writability check
60272 	 */
60273 
60274 	if (DUK_HARRAY_LENGTH_NONWRITABLE(a)) {
60275 		DUK_DDD(DUK_DDDPRINT("length is not writable, fail"));
60276 		return 0;
60277 	}
60278 
60279 	/*
60280 	 *  New length not lower than old length => no changes needed
60281 	 *  (not even array allocation).
60282 	 */
60283 
60284 	if (new_len >= old_len) {
60285 		DUK_DDD(DUK_DDDPRINT("new length is same or higher than old length, just update length, no deletions"));
60286 		a->length = new_len;
60287 		return 1;
60288 	}
60289 
60290 	DUK_DDD(DUK_DDDPRINT("new length is lower than old length, probably must delete entries"));
60291 
60292 	/*
60293 	 *  New length lower than old length => delete elements, then
60294 	 *  update length.
60295 	 *
60296 	 *  Note: even though a bunch of elements have been deleted, the 'desc' is
60297 	 *  still valid as properties haven't been resized (and entries compacted).
60298 	 */
60299 
60300 	rc = duk__handle_put_array_length_smaller(thr, obj, old_len, new_len, 0 /*force_flag*/, &result_len);
60301 	DUK_ASSERT(result_len >= new_len && result_len <= old_len);
60302 
60303 	a->length = result_len;
60304 
60305 	/* XXX: shrink array allocation or entries compaction here? */
60306 
60307 	return rc;
60308 }
60309 
60310 /*
60311  *  PUTPROP: ECMAScript property write.
60312  *
60313  *  Unlike ECMAScript primitive which returns nothing, returns 1 to indicate
60314  *  success and 0 to indicate failure (assuming throw is not set).
60315  *
60316  *  This is an extremely tricky function.  Some examples:
60317  *
60318  *    * Currently a decref may trigger a GC, which may compact an object's
60319  *      property allocation.  Consequently, any entry indices (e_idx) will
60320  *      be potentially invalidated by a decref.
60321  *
60322  *    * Exotic behaviors (strings, arrays, arguments object) require,
60323  *      among other things:
60324  *
60325  *      - Preprocessing before and postprocessing after an actual property
60326  *        write.  For example, array index write requires pre-checking the
60327  *        array 'length' property for access control, and may require an
60328  *        array 'length' update after the actual write has succeeded (but
60329  *        not if it fails).
60330  *
60331  *      - Deletion of multiple entries, as a result of array 'length' write.
60332  *
60333  *    * Input values are taken as pointers which may point to the valstack.
60334  *      If valstack is resized because of the put (this may happen at least
60335  *      when the array part is abandoned), the pointers can be invalidated.
60336  *      (We currently make a copy of all of the input values to avoid issues.)
60337  */
60338 
60339 DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_tval *tv_val, duk_bool_t throw_flag) {
60340 	duk_tval tv_obj_copy;
60341 	duk_tval tv_key_copy;
60342 	duk_tval tv_val_copy;
60343 	duk_hobject *orig = NULL;  /* NULL if tv_obj is primitive */
60344 	duk_hobject *curr;
60345 	duk_hstring *key = NULL;
60346 	duk_propdesc desc;
60347 	duk_tval *tv;
60348 	duk_uint32_t arr_idx;
60349 	duk_bool_t rc;
60350 	duk_int_t e_idx;
60351 	duk_uint_t sanity;
60352 	duk_uint32_t new_array_length = 0;  /* 0 = no update */
60353 
60354 	DUK_DDD(DUK_DDDPRINT("putprop: thr=%p, obj=%p, key=%p, val=%p, throw=%ld "
60355 	                     "(obj -> %!T, key -> %!T, val -> %!T)",
60356 	                     (void *) thr, (void *) tv_obj, (void *) tv_key, (void *) tv_val,
60357 	                     (long) throw_flag, (duk_tval *) tv_obj, (duk_tval *) tv_key, (duk_tval *) tv_val));
60358 
60359 	DUK_ASSERT(thr != NULL);
60360 	DUK_ASSERT(thr->heap != NULL);
60361 	DUK_ASSERT(tv_obj != NULL);
60362 	DUK_ASSERT(tv_key != NULL);
60363 	DUK_ASSERT(tv_val != NULL);
60364 
60365 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
60366 
60367 	DUK_STATS_INC(thr->heap, stats_putprop_all);
60368 
60369 	/*
60370 	 *  Make a copy of tv_obj, tv_key, and tv_val to avoid any issues of
60371 	 *  them being invalidated by a valstack resize.
60372 	 *
60373 	 *  XXX: this is an overkill for some paths, so optimize this later
60374 	 *  (or maybe switch to a stack arguments model entirely).
60375 	 */
60376 
60377 	DUK_TVAL_SET_TVAL(&tv_obj_copy, tv_obj);
60378 	DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
60379 	DUK_TVAL_SET_TVAL(&tv_val_copy, tv_val);
60380 	tv_obj = &tv_obj_copy;
60381 	tv_key = &tv_key_copy;
60382 	tv_val = &tv_val_copy;
60383 
60384 	/*
60385 	 *  Coercion and fast path processing.
60386 	 */
60387 
60388 	switch (DUK_TVAL_GET_TAG(tv_obj)) {
60389 	case DUK_TAG_UNDEFINED:
60390 	case DUK_TAG_NULL: {
60391 		/* Note: unconditional throw */
60392 		DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject (object=%!iT)",
60393 		                     (duk_tval *) tv_obj));
60394 #if defined(DUK_USE_PARANOID_ERRORS)
60395 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
60396 #else
60397 		DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s",
60398 		               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
60399 #endif
60400 		DUK_WO_NORETURN(return 0;);
60401 		break;
60402 	}
60403 
60404 	case DUK_TAG_BOOLEAN: {
60405 		DUK_DDD(DUK_DDDPRINT("base object is a boolean, start lookup from boolean prototype"));
60406 		curr = thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE];
60407 		break;
60408 	}
60409 
60410 	case DUK_TAG_STRING: {
60411 		duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
60412 
60413 		/*
60414 		 *  Note: currently no fast path for array index writes.
60415 		 *  They won't be possible anyway as strings are immutable.
60416 		 */
60417 
60418 		DUK_ASSERT(key == NULL);
60419 		arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
60420 		DUK_ASSERT(key != NULL);
60421 
60422 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
60423 			/* Symbols (ES2015 or hidden) don't have virtual properties. */
60424 			curr = thr->builtins[DUK_BIDX_SYMBOL_PROTOTYPE];
60425 			goto lookup;
60426 		}
60427 
60428 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
60429 			goto fail_not_writable;
60430 		}
60431 
60432 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
60433 		    arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
60434 			goto fail_not_writable;
60435 		}
60436 
60437 		DUK_DDD(DUK_DDDPRINT("base object is a string, start lookup from string prototype"));
60438 		curr = thr->builtins[DUK_BIDX_STRING_PROTOTYPE];
60439 		goto lookup;  /* avoid double coercion */
60440 	}
60441 
60442 	case DUK_TAG_OBJECT: {
60443 		orig = DUK_TVAL_GET_OBJECT(tv_obj);
60444 		DUK_ASSERT(orig != NULL);
60445 
60446 #if defined(DUK_USE_ROM_OBJECTS)
60447 		/* With this check in place fast paths won't need read-only
60448 		 * object checks.  This is technically incorrect if there are
60449 		 * setters that cause no writes to ROM objects, but current
60450 		 * built-ins don't have such setters.
60451 		 */
60452 		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
60453 			DUK_DD(DUK_DDPRINT("attempt to putprop on read-only target object"));
60454 			goto fail_not_writable_no_pop;  /* Must avoid duk_pop() in exit path */
60455 		}
60456 #endif
60457 
60458 		/* The fast path for array property put is not fully compliant:
60459 		 * If one places conflicting number-indexed properties into
60460 		 * Array.prototype (for example, a non-writable Array.prototype[7])
60461 		 * the fast path will incorrectly ignore them.
60462 		 *
60463 		 * This fast path could be made compliant by falling through
60464 		 * to the slow path if the previous value was UNUSED.  This would
60465 		 * also remove the need to check for extensibility.  Right now a
60466 		 * non-extensible array is slower than an extensible one as far
60467 		 * as writes are concerned.
60468 		 *
60469 		 * The fast path behavior is documented in more detail here:
60470 		 * tests/ecmascript/test-misc-array-fast-write.js
60471 		 */
60472 
60473 		/* XXX: array .length? */
60474 
60475 #if defined(DUK_USE_ARRAY_PROP_FASTPATH)
60476 		if (duk__putprop_shallow_fastpath_array_tval(thr, orig, tv_key, tv_val) != 0) {
60477 			DUK_DDD(DUK_DDDPRINT("array fast path success"));
60478 			DUK_STATS_INC(thr->heap, stats_putprop_arrayidx);
60479 			return 1;
60480 		}
60481 #endif
60482 
60483 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
60484 		if (duk__putprop_fastpath_bufobj_tval(thr, orig, tv_key, tv_val) != 0) {
60485 			DUK_DDD(DUK_DDDPRINT("base is bufobj, key is a number, bufobj fast path"));
60486 			DUK_STATS_INC(thr->heap, stats_putprop_bufobjidx);
60487 			return 1;
60488 		}
60489 #endif
60490 
60491 #if defined(DUK_USE_ES6_PROXY)
60492 		if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(orig))) {
60493 			duk_hobject *h_target;
60494 			duk_bool_t tmp_bool;
60495 
60496 			if (duk__proxy_check_prop(thr, orig, DUK_STRIDX_SET, tv_key, &h_target)) {
60497 				/* -> [ ... trap handler ] */
60498 				DUK_DDD(DUK_DDDPRINT("-> proxy object 'set' for key %!T", (duk_tval *) tv_key));
60499 				DUK_STATS_INC(thr->heap, stats_putprop_proxy);
60500 				duk_push_hobject(thr, h_target);  /* target */
60501 				duk_push_tval(thr, tv_key);       /* P */
60502 				duk_push_tval(thr, tv_val);       /* V */
60503 				duk_push_tval(thr, tv_obj);       /* Receiver: Proxy object */
60504 				duk_call_method(thr, 4 /*nargs*/);
60505 				tmp_bool = duk_to_boolean_top_pop(thr);
60506 				if (!tmp_bool) {
60507 					goto fail_proxy_rejected;
60508 				}
60509 
60510 				/* Target object must be checked for a conflicting
60511 				 * non-configurable property.
60512 				 */
60513 				arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
60514 				DUK_ASSERT(key != NULL);
60515 
60516 				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
60517 					duk_tval *tv_targ = duk_require_tval(thr, -1);
60518 					duk_bool_t datadesc_reject;
60519 					duk_bool_t accdesc_reject;
60520 
60521 					DUK_DDD(DUK_DDDPRINT("proxy 'set': target has matching property %!O, check for "
60522 					                     "conflicting property; tv_val=%!T, tv_targ=%!T, desc.flags=0x%08lx, "
60523 					                     "desc.get=%p, desc.set=%p",
60524 					                     (duk_heaphdr *) key, (duk_tval *) tv_val, (duk_tval *) tv_targ,
60525 					                     (unsigned long) desc.flags,
60526 					                     (void *) desc.get, (void *) desc.set));
60527 
60528 					datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
60529 					                  !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
60530 					                  !(desc.flags & DUK_PROPDESC_FLAG_WRITABLE) &&
60531 					                  !duk_js_samevalue(tv_val, tv_targ);
60532 					accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
60533 					                 !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
60534 					                 (desc.set == NULL);
60535 					if (datadesc_reject || accdesc_reject) {
60536 						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
60537 						DUK_WO_NORETURN(return 0;);
60538 					}
60539 
60540 					duk_pop_2_unsafe(thr);
60541 				} else {
60542 					duk_pop_unsafe(thr);
60543 				}
60544 				return 1;  /* success */
60545 			}
60546 
60547 			orig = h_target;  /* resume write to target */
60548 			DUK_TVAL_SET_OBJECT(tv_obj, orig);
60549 		}
60550 #endif  /* DUK_USE_ES6_PROXY */
60551 
60552 		curr = orig;
60553 		break;
60554 	}
60555 
60556 	case DUK_TAG_BUFFER: {
60557 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
60558 		duk_int_t pop_count = 0;
60559 
60560 		/*
60561 		 *  Because buffer values may be looped over and read/written
60562 		 *  from, an array index fast path is important.
60563 		 */
60564 
60565 #if defined(DUK_USE_FASTINT)
60566 		if (DUK_TVAL_IS_FASTINT(tv_key)) {
60567 			arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
60568 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
60569 			pop_count = 0;
60570 		} else
60571 #endif
60572 		if (DUK_TVAL_IS_NUMBER(tv_key)) {
60573 			arr_idx = duk__tval_number_to_arr_idx(tv_key);
60574 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path number; arr_idx %ld", (long) arr_idx));
60575 			pop_count = 0;
60576 		} else {
60577 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
60578 			DUK_ASSERT(key != NULL);
60579 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
60580 			                     "coercion key is %!T, arr_idx %ld",
60581 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
60582 			pop_count = 1;
60583 		}
60584 
60585 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
60586 		    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
60587 			duk_uint8_t *data;
60588 			DUK_DDD(DUK_DDDPRINT("writing to buffer data at index %ld", (long) arr_idx));
60589 			data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);
60590 
60591 			/* XXX: duk_to_int() ensures we'll get 8 lowest bits as
60592 			 * as input is within duk_int_t range (capped outside it).
60593 			 */
60594 #if defined(DUK_USE_FASTINT)
60595 			/* Buffer writes are often integers. */
60596 			if (DUK_TVAL_IS_FASTINT(tv_val)) {
60597 				data[arr_idx] = (duk_uint8_t) DUK_TVAL_GET_FASTINT_U32(tv_val);
60598 			}
60599 			else
60600 #endif
60601 			{
60602 				duk_push_tval(thr, tv_val);
60603 				data[arr_idx] = (duk_uint8_t) duk_to_uint32(thr, -1);
60604 				pop_count++;
60605 			}
60606 
60607 			duk_pop_n_unsafe(thr, pop_count);
60608 			DUK_DDD(DUK_DDDPRINT("result: success (buffer data write)"));
60609 			DUK_STATS_INC(thr->heap, stats_putprop_bufferidx);
60610 			return 1;
60611 		}
60612 
60613 		if (pop_count == 0) {
60614 			/* This is a pretty awkward control flow, but we need to recheck the
60615 			 * key coercion here.
60616 			 */
60617 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
60618 			DUK_ASSERT(key != NULL);
60619 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
60620 			                     "coercion key is %!T, arr_idx %ld",
60621 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
60622 		}
60623 
60624 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
60625 			goto fail_not_writable;
60626 		}
60627 
60628 		DUK_DDD(DUK_DDDPRINT("base object is a buffer, start lookup from Uint8Array prototype"));
60629 		curr = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
60630 		goto lookup;  /* avoid double coercion */
60631 	}
60632 
60633 	case DUK_TAG_POINTER: {
60634 		DUK_DDD(DUK_DDDPRINT("base object is a pointer, start lookup from pointer prototype"));
60635 		curr = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];
60636 		break;
60637 	}
60638 
60639 	case DUK_TAG_LIGHTFUNC: {
60640 		/* Lightfuncs have no own properties and are considered non-extensible.
60641 		 * However, the write may be captured by an inherited setter which
60642 		 * means we can't stop the lookup here.
60643 		 */
60644 		DUK_DDD(DUK_DDDPRINT("base object is a lightfunc, start lookup from function prototype"));
60645 		curr = thr->builtins[DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE];
60646 		break;
60647 	}
60648 
60649 #if defined(DUK_USE_FASTINT)
60650 	case DUK_TAG_FASTINT:
60651 #endif
60652 	default: {
60653 		/* number */
60654 		DUK_DDD(DUK_DDDPRINT("base object is a number, start lookup from number prototype"));
60655 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_obj));
60656 		curr = thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE];
60657 		break;
60658 	}
60659 	}
60660 
60661 	DUK_ASSERT(key == NULL);
60662 	arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
60663 	DUK_ASSERT(key != NULL);
60664 
60665  lookup:
60666 
60667 	/*
60668 	 *  Check whether the property already exists in the prototype chain.
60669 	 *  Note that the actual write goes into the original base object
60670 	 *  (except if an accessor property captures the write).
60671 	 */
60672 
60673 	/* [key] */
60674 
60675 	DUK_ASSERT(curr != NULL);
60676 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
60677 	do {
60678 		if (!duk__get_own_propdesc_raw(thr, curr, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
60679 			goto next_in_chain;
60680 		}
60681 
60682 		if (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
60683 			/*
60684 			 *  Found existing accessor property (own or inherited).
60685 			 *  Call setter with 'this' set to orig, and value as the only argument.
60686 			 *  Setter calls are OK even for ROM objects.
60687 			 *
60688 			 *  Note: no exotic arguments object behavior, because [[Put]] never
60689 			 *  calls [[DefineOwnProperty]] (E5 Section 8.12.5, step 5.b).
60690 			 */
60691 
60692 			duk_hobject *setter;
60693 
60694 			DUK_DD(DUK_DDPRINT("put to an own or inherited accessor, calling setter"));
60695 
60696 			setter = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, curr, desc.e_idx);
60697 			if (!setter) {
60698 				goto fail_no_setter;
60699 			}
60700 			duk_push_hobject(thr, setter);
60701 			duk_push_tval(thr, tv_obj);  /* note: original, uncoerced base */
60702 			duk_push_tval(thr, tv_val);  /* [key setter this val] */
60703 #if defined(DUK_USE_NONSTD_SETTER_KEY_ARGUMENT)
60704 			duk_dup_m4(thr);
60705 			duk_call_method(thr, 2);     /* [key setter this val key] -> [key retval] */
60706 #else
60707 			duk_call_method(thr, 1);     /* [key setter this val] -> [key retval] */
60708 #endif
60709 			duk_pop_unsafe(thr);         /* ignore retval -> [key] */
60710 			goto success_no_arguments_exotic;
60711 		}
60712 
60713 		if (orig == NULL) {
60714 			/*
60715 			 *  Found existing own or inherited plain property, but original
60716 			 *  base is a primitive value.
60717 			 */
60718 			DUK_DD(DUK_DDPRINT("attempt to create a new property in a primitive base object"));
60719 			goto fail_base_primitive;
60720 		}
60721 
60722 		if (curr != orig) {
60723 			/*
60724 			 *  Found existing inherited plain property.
60725 			 *  Do an access control check, and if OK, write
60726 			 *  new property to 'orig'.
60727 			 */
60728 			if (!DUK_HOBJECT_HAS_EXTENSIBLE(orig)) {
60729 				DUK_DD(DUK_DDPRINT("found existing inherited plain property, but original object is not extensible"));
60730 				goto fail_not_extensible;
60731 			}
60732 			if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
60733 				DUK_DD(DUK_DDPRINT("found existing inherited plain property, original object is extensible, but inherited property is not writable"));
60734 				goto fail_not_writable;
60735 			}
60736 			DUK_DD(DUK_DDPRINT("put to new property, object extensible, inherited property found and is writable"));
60737 			goto create_new;
60738 		} else {
60739 			/*
60740 			 *  Found existing own (non-inherited) plain property.
60741 			 *  Do an access control check and update in place.
60742 			 */
60743 
60744 			if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
60745 				DUK_DD(DUK_DDPRINT("found existing own (non-inherited) plain property, but property is not writable"));
60746 				goto fail_not_writable;
60747 			}
60748 			if (desc.flags & DUK_PROPDESC_FLAG_VIRTUAL) {
60749 				DUK_DD(DUK_DDPRINT("found existing own (non-inherited) virtual property, property is writable"));
60750 
60751 				if (DUK_HOBJECT_IS_ARRAY(curr)) {
60752 					/*
60753 					 *  Write to 'length' of an array is a very complex case
60754 					 *  handled in a helper which updates both the array elements
60755 					 *  and writes the new 'length'.  The write may result in an
60756 					 *  unconditional RangeError or a partial write (indicated
60757 					 *  by a return code).
60758 					 *
60759 					 *  Note: the helper has an unnecessary writability check
60760 					 *  for 'length', we already know it is writable.
60761 					 */
60762 					DUK_ASSERT(key == DUK_HTHREAD_STRING_LENGTH(thr));  /* only virtual array property */
60763 
60764 					DUK_DDD(DUK_DDDPRINT("writing existing 'length' property to array exotic, invoke complex helper"));
60765 
60766 					/* XXX: the helper currently assumes stack top contains new
60767 					 * 'length' value and the whole calling convention is not very
60768 					 * compatible with what we need.
60769 					 */
60770 
60771 					duk_push_tval(thr, tv_val);  /* [key val] */
60772 					rc = duk__handle_put_array_length(thr, orig);
60773 					duk_pop_unsafe(thr);  /* [key val] -> [key] */
60774 					if (!rc) {
60775 						goto fail_array_length_partial;
60776 					}
60777 
60778 					/* key is 'length', cannot match argument exotic behavior */
60779 					goto success_no_arguments_exotic;
60780 				}
60781 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
60782 				else if (DUK_HOBJECT_IS_BUFOBJ(curr)) {
60783 					duk_hbufobj *h_bufobj;
60784 					duk_uint_t byte_off;
60785 					duk_small_uint_t elem_size;
60786 
60787 					h_bufobj = (duk_hbufobj *) curr;
60788 					DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
60789 
60790 					DUK_DD(DUK_DDPRINT("writable virtual property is in buffer object"));
60791 
60792 					/* Careful with wrapping: arr_idx upshift may easily wrap, whereas
60793 					 * length downshift won't.
60794 					 */
60795 					if (arr_idx < (h_bufobj->length >> h_bufobj->shift) && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
60796 						duk_uint8_t *data;
60797 						DUK_DDD(DUK_DDDPRINT("writing to buffer data at index %ld", (long) arr_idx));
60798 
60799 						DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);  /* index/length check guarantees */
60800 						byte_off = arr_idx << h_bufobj->shift;       /* no wrap assuming h_bufobj->length is valid */
60801 						elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
60802 
60803 						/* Coerce to number before validating pointers etc so that the
60804 						 * number coercions in duk_hbufobj_validated_write() are
60805 						 * guaranteed to be side effect free and not invalidate the
60806 						 * pointer checks we do here.
60807 						 */
60808 						duk_push_tval(thr, tv_val);
60809 						(void) duk_to_number_m1(thr);
60810 
60811 						if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
60812 							data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
60813 							duk_hbufobj_validated_write(thr, h_bufobj, data, elem_size);
60814 						} else {
60815 							DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (write skipped)"));
60816 						}
60817 						duk_pop_unsafe(thr);
60818 						goto success_no_arguments_exotic;
60819 					}
60820 				}
60821 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
60822 
60823 				DUK_D(DUK_DPRINT("should not happen, key %!O", key));
60824 				goto fail_internal;  /* should not happen */
60825 			}
60826 			DUK_DD(DUK_DDPRINT("put to existing own plain property, property is writable"));
60827 			goto update_old;
60828 		}
60829 		DUK_UNREACHABLE();
60830 
60831 	 next_in_chain:
60832 		/* XXX: option to pretend property doesn't exist if sanity limit is
60833 		 * hit might be useful.
60834 		 */
60835 		if (DUK_UNLIKELY(sanity-- == 0)) {
60836 			DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
60837 			DUK_WO_NORETURN(return 0;);
60838 		}
60839 		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
60840 	} while (curr != NULL);
60841 
60842 	/*
60843 	 *  Property not found in prototype chain.
60844 	 */
60845 
60846 	DUK_DDD(DUK_DDDPRINT("property not found in prototype chain"));
60847 
60848 	if (orig == NULL) {
60849 		DUK_DD(DUK_DDPRINT("attempt to create a new property in a primitive base object"));
60850 		goto fail_base_primitive;
60851 	}
60852 
60853 	if (!DUK_HOBJECT_HAS_EXTENSIBLE(orig)) {
60854 		DUK_DD(DUK_DDPRINT("put to a new property (not found in prototype chain), but original object not extensible"));
60855 		goto fail_not_extensible;
60856 	}
60857 
60858 	goto create_new;
60859 
60860  update_old:
60861 
60862 	/*
60863 	 *  Update an existing property of the base object.
60864 	 */
60865 
60866 	/* [key] */
60867 
60868 	DUK_DDD(DUK_DDDPRINT("update an existing property of the original object"));
60869 
60870 	DUK_ASSERT(orig != NULL);
60871 #if defined(DUK_USE_ROM_OBJECTS)
60872 	/* This should not happen because DUK_TAG_OBJECT case checks
60873 	 * for this already, but check just in case.
60874 	 */
60875 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
60876 		goto fail_not_writable;
60877 	}
60878 #endif
60879 
60880 	/* Although there are writable virtual properties (e.g. plain buffer
60881 	 * and buffer object number indices), they are handled before we come
60882 	 * here.
60883 	 */
60884 	DUK_ASSERT((desc.flags & DUK_PROPDESC_FLAG_VIRTUAL) == 0);
60885 	DUK_ASSERT(desc.a_idx >= 0 || desc.e_idx >= 0);
60886 
60887 	/* Array own property .length is handled above. */
60888 	DUK_ASSERT(!(DUK_HOBJECT_IS_ARRAY(orig) && key == DUK_HTHREAD_STRING_LENGTH(thr)));
60889 
60890 	if (desc.e_idx >= 0) {
60891 		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, desc.e_idx);
60892 		DUK_DDD(DUK_DDDPRINT("previous entry value: %!iT", (duk_tval *) tv));
60893 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val);  /* side effects; e_idx may be invalidated */
60894 		/* don't touch property attributes or hash part */
60895 		DUK_DD(DUK_DDPRINT("put to an existing entry at index %ld -> new value %!iT",
60896 		                   (long) desc.e_idx, (duk_tval *) tv));
60897 	} else {
60898 		/* Note: array entries are always writable, so the writability check
60899 		 * above is pointless for them.  The check could be avoided with some
60900 		 * refactoring but is probably not worth it.
60901 		 */
60902 
60903 		DUK_ASSERT(desc.a_idx >= 0);
60904 		tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, orig, desc.a_idx);
60905 		DUK_DDD(DUK_DDDPRINT("previous array value: %!iT", (duk_tval *) tv));
60906 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val);  /* side effects; a_idx may be invalidated */
60907 		DUK_DD(DUK_DDPRINT("put to an existing array entry at index %ld -> new value %!iT",
60908 		                   (long) desc.a_idx, (duk_tval *) tv));
60909 	}
60910 
60911 	/* Regardless of whether property is found in entry or array part,
60912 	 * it may have arguments exotic behavior (array indices may reside
60913 	 * in entry part for abandoned / non-existent array parts).
60914 	 */
60915 	goto success_with_arguments_exotic;
60916 
60917  create_new:
60918 
60919 	/*
60920 	 *  Create a new property in the original object.
60921 	 *
60922 	 *  Exotic properties need to be reconsidered here from a write
60923 	 *  perspective (not just property attributes perspective).
60924 	 *  However, the property does not exist in the object already,
60925 	 *  so this limits the kind of exotic properties that apply.
60926 	 */
60927 
60928 	/* [key] */
60929 
60930 	DUK_DDD(DUK_DDDPRINT("create new property to original object"));
60931 
60932 	DUK_ASSERT(orig != NULL);
60933 
60934 	/* Array own property .length is handled above. */
60935 	DUK_ASSERT(!(DUK_HOBJECT_IS_ARRAY(orig) && key == DUK_HTHREAD_STRING_LENGTH(thr)));
60936 
60937 #if defined(DUK_USE_ROM_OBJECTS)
60938 	/* This should not happen because DUK_TAG_OBJECT case checks
60939 	 * for this already, but check just in case.
60940 	 */
60941 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
60942 		goto fail_not_writable;
60943 	}
60944 #endif
60945 
60946 	/* Not possible because array object 'length' is present
60947 	 * from its creation and cannot be deleted, and is thus
60948 	 * caught as an existing property above.
60949 	 */
60950 	DUK_ASSERT(!(DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) &&
60951 	             key == DUK_HTHREAD_STRING_LENGTH(thr)));
60952 
60953 	if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) &&
60954 	    arr_idx != DUK__NO_ARRAY_INDEX) {
60955 		/* automatic length update */
60956 		duk_uint32_t old_len;
60957 		duk_harray *a;
60958 
60959 		a = (duk_harray *) orig;
60960 		DUK_HARRAY_ASSERT_VALID(a);
60961 
60962 		old_len = a->length;
60963 
60964 		if (arr_idx >= old_len) {
60965 			DUK_DDD(DUK_DDDPRINT("write new array entry requires length update "
60966 			                     "(arr_idx=%ld, old_len=%ld)",
60967 			                     (long) arr_idx, (long) old_len));
60968 
60969 			if (DUK_HARRAY_LENGTH_NONWRITABLE(a)) {
60970 				DUK_DD(DUK_DDPRINT("attempt to extend array, but array 'length' is not writable"));
60971 				goto fail_not_writable;
60972 			}
60973 
60974 			/* Note: actual update happens once write has been completed
60975 			 * without error below.  The write should always succeed
60976 			 * from a specification viewpoint, but we may e.g. run out
60977 			 * of memory.  It's safer in this order.
60978 			 */
60979 
60980 			DUK_ASSERT(arr_idx != 0xffffffffUL);
60981 			new_array_length = arr_idx + 1;  /* flag for later write */
60982 		} else {
60983 			DUK_DDD(DUK_DDDPRINT("write new array entry does not require length update "
60984 			                     "(arr_idx=%ld, old_len=%ld)",
60985 			                     (long) arr_idx, (long) old_len));
60986 		}
60987 	}
60988 
60989  /* write_to_array_part: */
60990 
60991 	/*
60992 	 *  Write to array part?
60993 	 *
60994 	 *  Note: array abandonding requires a property resize which uses
60995 	 *  'rechecks' valstack for temporaries and may cause any existing
60996 	 *  valstack pointers to be invalidated.  To protect against this,
60997 	 *  tv_obj, tv_key, and tv_val are copies of the original inputs.
60998 	 */
60999 
61000 	if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(orig)) {
61001 		tv = duk__obtain_arridx_slot(thr, arr_idx, orig);
61002 		if (tv == NULL) {
61003 			DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(orig));
61004 			goto write_to_entry_part;
61005 		}
61006 
61007 		/* prev value must be unused, no decref */
61008 		DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv));
61009 		DUK_TVAL_SET_TVAL(tv, tv_val);
61010 		DUK_TVAL_INCREF(thr, tv);
61011 		DUK_DD(DUK_DDPRINT("put to new array entry: %ld -> %!T",
61012 		                   (long) arr_idx, (duk_tval *) tv));
61013 
61014 		/* Note: array part values are [[Writable]], [[Enumerable]],
61015 		 * and [[Configurable]] which matches the required attributes
61016 		 * here.
61017 		 */
61018 		goto entry_updated;
61019 	}
61020 
61021  write_to_entry_part:
61022 
61023 	/*
61024 	 *  Write to entry part
61025 	 */
61026 
61027 	/* entry allocation updates hash part and increases the key
61028 	 * refcount; may need a props allocation resize but doesn't
61029 	 * 'recheck' the valstack.
61030 	 */
61031 	e_idx = duk__hobject_alloc_entry_checked(thr, orig, key);
61032 	DUK_ASSERT(e_idx >= 0);
61033 
61034 	tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, e_idx);
61035 	/* prev value can be garbage, no decref */
61036 	DUK_TVAL_SET_TVAL(tv, tv_val);
61037 	DUK_TVAL_INCREF(thr, tv);
61038 	DUK_HOBJECT_E_SET_FLAGS(thr->heap, orig, e_idx, DUK_PROPDESC_FLAGS_WEC);
61039 	goto entry_updated;
61040 
61041  entry_updated:
61042 
61043 	/*
61044 	 *  Possible pending array length update, which must only be done
61045 	 *  if the actual entry write succeeded.
61046 	 */
61047 
61048 	if (new_array_length > 0) {
61049 		/* Note: zero works as a "no update" marker because the new length
61050 		 * can never be zero after a new property is written.
61051 		 */
61052 
61053 		DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig));
61054 
61055 		DUK_DDD(DUK_DDDPRINT("write successful, pending array length update to: %ld",
61056 		                     (long) new_array_length));
61057 
61058 		((duk_harray *) orig)->length = new_array_length;
61059 	}
61060 
61061 	/*
61062 	 *  Arguments exotic behavior not possible for new properties: all
61063 	 *  magically bound properties are initially present in the arguments
61064 	 *  object, and if they are deleted, the binding is also removed from
61065 	 *  parameter map.
61066 	 */
61067 
61068 	goto success_no_arguments_exotic;
61069 
61070  success_with_arguments_exotic:
61071 
61072 	/*
61073 	 *  Arguments objects have exotic [[DefineOwnProperty]] which updates
61074 	 *  the internal 'map' of arguments for writes to currently mapped
61075 	 *  arguments.  More conretely, writes to mapped arguments generate
61076 	 *  a write to a bound variable.
61077 	 *
61078 	 *  The [[Put]] algorithm invokes [[DefineOwnProperty]] for existing
61079 	 *  data properties and new properties, but not for existing accessors.
61080 	 *  Hence, in E5 Section 10.6 ([[DefinedOwnProperty]] algorithm), we
61081 	 *  have a Desc with 'Value' (and possibly other properties too), and
61082 	 *  we end up in step 5.b.i.
61083 	 */
61084 
61085 	if (arr_idx != DUK__NO_ARRAY_INDEX &&
61086 	    DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(orig)) {
61087 		/* Note: only numbered indices are relevant, so arr_idx fast reject
61088 		 * is good (this is valid unless there are more than 4**32-1 arguments).
61089 		 */
61090 
61091 		DUK_DDD(DUK_DDDPRINT("putprop successful, arguments exotic behavior needed"));
61092 
61093 		/* Note: we can reuse 'desc' here */
61094 
61095 		/* XXX: top of stack must contain value, which helper doesn't touch,
61096 		 * rework to use tv_val directly?
61097 		 */
61098 
61099 		duk_push_tval(thr, tv_val);
61100 		(void) duk__check_arguments_map_for_put(thr, orig, key, &desc, throw_flag);
61101 		duk_pop_unsafe(thr);
61102 	}
61103 	/* fall thru */
61104 
61105  success_no_arguments_exotic:
61106 	/* shared exit path now */
61107 	DUK_DDD(DUK_DDDPRINT("result: success"));
61108 	duk_pop_unsafe(thr);  /* remove key */
61109 	return 1;
61110 
61111 #if defined(DUK_USE_ES6_PROXY)
61112  fail_proxy_rejected:
61113 	DUK_DDD(DUK_DDDPRINT("result: error, proxy rejects"));
61114 	if (throw_flag) {
61115 		DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
61116 		DUK_WO_NORETURN(return 0;);
61117 	}
61118 	/* Note: no key on stack */
61119 	return 0;
61120 #endif
61121 
61122  fail_base_primitive:
61123 	DUK_DDD(DUK_DDDPRINT("result: error, base primitive"));
61124 	if (throw_flag) {
61125 #if defined(DUK_USE_PARANOID_ERRORS)
61126 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
61127 #else
61128 		DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s",
61129 		               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
61130 #endif
61131 		DUK_WO_NORETURN(return 0;);
61132 	}
61133 	duk_pop_unsafe(thr);  /* remove key */
61134 	return 0;
61135 
61136  fail_not_extensible:
61137 	DUK_DDD(DUK_DDDPRINT("result: error, not extensible"));
61138 	if (throw_flag) {
61139 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_EXTENSIBLE);
61140 		DUK_WO_NORETURN(return 0;);
61141 	}
61142 	duk_pop_unsafe(thr);  /* remove key */
61143 	return 0;
61144 
61145  fail_not_writable:
61146 	DUK_DDD(DUK_DDDPRINT("result: error, not writable"));
61147 	if (throw_flag) {
61148 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_WRITABLE);
61149 		DUK_WO_NORETURN(return 0;);
61150 	}
61151 	duk_pop_unsafe(thr);  /* remove key */
61152 	return 0;
61153 
61154 #if defined(DUK_USE_ROM_OBJECTS)
61155  fail_not_writable_no_pop:
61156 	DUK_DDD(DUK_DDDPRINT("result: error, not writable"));
61157 	if (throw_flag) {
61158 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_WRITABLE);
61159 		DUK_WO_NORETURN(return 0;);
61160 	}
61161 	return 0;
61162 #endif
61163 
61164  fail_array_length_partial:
61165 	DUK_DD(DUK_DDPRINT("result: error, array length write only partially successful"));
61166 	if (throw_flag) {
61167 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
61168 		DUK_WO_NORETURN(return 0;);
61169 	}
61170 	duk_pop_unsafe(thr);  /* remove key */
61171 	return 0;
61172 
61173  fail_no_setter:
61174 	DUK_DDD(DUK_DDDPRINT("result: error, accessor property without setter"));
61175 	if (throw_flag) {
61176 		DUK_ERROR_TYPE(thr, DUK_STR_SETTER_UNDEFINED);
61177 		DUK_WO_NORETURN(return 0;);
61178 	}
61179 	duk_pop_unsafe(thr);  /* remove key */
61180 	return 0;
61181 
61182  fail_internal:
61183 	DUK_DDD(DUK_DDDPRINT("result: error, internal"));
61184 	if (throw_flag) {
61185 		DUK_ERROR_INTERNAL(thr);
61186 		DUK_WO_NORETURN(return 0;);
61187 	}
61188 	duk_pop_unsafe(thr);  /* remove key */
61189 	return 0;
61190 }
61191 
61192 /*
61193  *  ECMAScript compliant [[Delete]](P, Throw).
61194  */
61195 
61196 DUK_INTERNAL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags) {
61197 	duk_propdesc desc;
61198 	duk_tval *tv;
61199 	duk_uint32_t arr_idx;
61200 	duk_bool_t throw_flag;
61201 	duk_bool_t force_flag;
61202 
61203 	throw_flag = (flags & DUK_DELPROP_FLAG_THROW);
61204 	force_flag = (flags & DUK_DELPROP_FLAG_FORCE);
61205 
61206 	DUK_DDD(DUK_DDDPRINT("delprop_raw: thr=%p, obj=%p, key=%p, throw=%ld, force=%ld (obj -> %!O, key -> %!O)",
61207 	                     (void *) thr, (void *) obj, (void *) key, (long) throw_flag, (long) force_flag,
61208 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
61209 
61210 	DUK_ASSERT(thr != NULL);
61211 	DUK_ASSERT(thr->heap != NULL);
61212 	DUK_ASSERT(obj != NULL);
61213 	DUK_ASSERT(key != NULL);
61214 
61215 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
61216 
61217 	arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
61218 
61219 	/* 0 = don't push current value */
61220 	if (!duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
61221 		DUK_DDD(DUK_DDDPRINT("property not found, succeed always"));
61222 		goto success;
61223 	}
61224 
61225 #if defined(DUK_USE_ROM_OBJECTS)
61226 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
61227 		DUK_DD(DUK_DDPRINT("attempt to delprop on read-only target object"));
61228 		goto fail_not_configurable;
61229 	}
61230 #endif
61231 
61232 	if ((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) == 0 && !force_flag) {
61233 		goto fail_not_configurable;
61234 	}
61235 	if (desc.a_idx < 0 && desc.e_idx < 0) {
61236 		/* Currently there are no deletable virtual properties, but
61237 		 * with force_flag we might attempt to delete one.
61238 		 */
61239 		DUK_DD(DUK_DDPRINT("delete failed: property found, force flag, but virtual (and implicitly non-configurable)"));
61240 		goto fail_virtual;
61241 	}
61242 
61243 	if (desc.a_idx >= 0) {
61244 		DUK_ASSERT(desc.e_idx < 0);
61245 
61246 		tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, desc.a_idx);
61247 		DUK_TVAL_SET_UNUSED_UPDREF(thr, tv);  /* side effects */
61248 		goto success;
61249 	} else {
61250 		DUK_ASSERT(desc.a_idx < 0);
61251 
61252 		/* remove hash entry (no decref) */
61253 #if defined(DUK_USE_HOBJECT_HASH_PART)
61254 		if (desc.h_idx >= 0) {
61255 			duk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(thr->heap, obj);
61256 
61257 			DUK_DDD(DUK_DDDPRINT("removing hash entry at h_idx %ld", (long) desc.h_idx));
61258 			DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) > 0);
61259 			DUK_ASSERT((duk_uint32_t) desc.h_idx < DUK_HOBJECT_GET_HSIZE(obj));
61260 			h_base[desc.h_idx] = DUK__HASH_DELETED;
61261 		} else {
61262 			DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) == 0);
61263 		}
61264 #else
61265 		DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) == 0);
61266 #endif
61267 
61268 		/* Remove value.  This requires multiple writes so avoid side
61269 		 * effects via no-refzero macros so that e_idx is not
61270 		 * invalidated.
61271 		 */
61272 		DUK_DDD(DUK_DDDPRINT("before removing value, e_idx %ld, key %p, key at slot %p",
61273 		                     (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
61274 		DUK_DDD(DUK_DDDPRINT("removing value at e_idx %ld", (long) desc.e_idx));
61275 		if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx)) {
61276 			duk_hobject *tmp;
61277 
61278 			tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, desc.e_idx);
61279 			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, desc.e_idx, NULL);
61280 			DUK_UNREF(tmp);
61281 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
61282 
61283 			tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, desc.e_idx);
61284 			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, desc.e_idx, NULL);
61285 			DUK_UNREF(tmp);
61286 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
61287 		} else {
61288 			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
61289 			DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);
61290 		}
61291 #if 0
61292 		/* Not strictly necessary because if key == NULL, flag MUST be ignored. */
61293 		DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, desc.e_idx, 0);
61294 #endif
61295 
61296 		/* Remove key. */
61297 		DUK_DDD(DUK_DDDPRINT("before removing key, e_idx %ld, key %p, key at slot %p",
61298 		                     (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
61299 		DUK_DDD(DUK_DDDPRINT("removing key at e_idx %ld", (long) desc.e_idx));
61300 		DUK_ASSERT(key == DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx));
61301 		DUK_HOBJECT_E_SET_KEY(thr->heap, obj, desc.e_idx, NULL);
61302 		DUK_HSTRING_DECREF_NORZ(thr, key);
61303 
61304 		/* Trigger refzero side effects only when we're done as a
61305 		 * finalizer might operate on the object and affect the
61306 		 * e_idx we're supposed to use.
61307 		 */
61308 		DUK_REFZERO_CHECK_SLOW(thr);
61309 		goto success;
61310 	}
61311 
61312 	DUK_UNREACHABLE();
61313 
61314  success:
61315 	/*
61316 	 *  Argument exotic [[Delete]] behavior (E5 Section 10.6) is
61317 	 *  a post-check, keeping arguments internal 'map' in sync with
61318 	 *  any successful deletes (note that property does not need to
61319 	 *  exist for delete to 'succeed').
61320 	 *
61321 	 *  Delete key from 'map'.  Since 'map' only contains array index
61322 	 *  keys, we can use arr_idx for a fast skip.
61323 	 */
61324 
61325 	DUK_DDD(DUK_DDDPRINT("delete successful, check for arguments exotic behavior"));
61326 
61327 	if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj)) {
61328 		/* Note: only numbered indices are relevant, so arr_idx fast reject
61329 		 * is good (this is valid unless there are more than 4**32-1 arguments).
61330 		 */
61331 
61332 		DUK_DDD(DUK_DDDPRINT("delete successful, arguments exotic behavior needed"));
61333 
61334 		/* Note: we can reuse 'desc' here */
61335 		(void) duk__check_arguments_map_for_delete(thr, obj, key, &desc);
61336 	}
61337 
61338 	DUK_DDD(DUK_DDDPRINT("delete successful"));
61339 	return 1;
61340 
61341  fail_virtual:  /* just use the same "not configurable" error message */
61342  fail_not_configurable:
61343 	DUK_DDD(DUK_DDDPRINT("delete failed: property found, not configurable"));
61344 
61345 	if (throw_flag) {
61346 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
61347 		DUK_WO_NORETURN(return 0;);
61348 	}
61349 	return 0;
61350 }
61351 
61352 /*
61353  *  DELPROP: ECMAScript property deletion.
61354  */
61355 
61356 DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_bool_t throw_flag) {
61357 	duk_hstring *key = NULL;
61358 #if defined(DUK_USE_ES6_PROXY)
61359 	duk_propdesc desc;
61360 #endif
61361 	duk_int_t entry_top;
61362 	duk_uint32_t arr_idx = DUK__NO_ARRAY_INDEX;
61363 	duk_bool_t rc;
61364 
61365 	DUK_DDD(DUK_DDDPRINT("delprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
61366 	                     (void *) thr, (void *) tv_obj, (void *) tv_key,
61367 	                     (duk_tval *) tv_obj, (duk_tval *) tv_key));
61368 
61369 	DUK_ASSERT(thr != NULL);
61370 	DUK_ASSERT(thr->heap != NULL);
61371 	DUK_ASSERT(tv_obj != NULL);
61372 	DUK_ASSERT(tv_key != NULL);
61373 
61374 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
61375 
61376 	/* Storing the entry top is cheaper here to ensure stack is correct at exit,
61377 	 * as there are several paths out.
61378 	 */
61379 	entry_top = duk_get_top(thr);
61380 
61381 	if (DUK_TVAL_IS_UNDEFINED(tv_obj) ||
61382 	    DUK_TVAL_IS_NULL(tv_obj)) {
61383 		DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject"));
61384 		goto fail_invalid_base_uncond;
61385 	}
61386 
61387 	duk_push_tval(thr, tv_obj);
61388 	duk_push_tval(thr, tv_key);
61389 
61390 	tv_obj = DUK_GET_TVAL_NEGIDX(thr, -2);
61391 	if (DUK_TVAL_IS_OBJECT(tv_obj)) {
61392 		duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv_obj);
61393 		DUK_ASSERT(obj != NULL);
61394 
61395 #if defined(DUK_USE_ES6_PROXY)
61396 		if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(obj))) {
61397 			duk_hobject *h_target;
61398 			duk_bool_t tmp_bool;
61399 
61400 			/* Note: proxy handling must happen before key is string coerced. */
61401 
61402 			if (duk__proxy_check_prop(thr, obj, DUK_STRIDX_DELETE_PROPERTY, tv_key, &h_target)) {
61403 				/* -> [ ... obj key trap handler ] */
61404 				DUK_DDD(DUK_DDDPRINT("-> proxy object 'deleteProperty' for key %!T", (duk_tval *) tv_key));
61405 				duk_push_hobject(thr, h_target);  /* target */
61406 				duk_dup_m4(thr);  /* P */
61407 				duk_call_method(thr, 2 /*nargs*/);
61408 				tmp_bool = duk_to_boolean_top_pop(thr);
61409 				if (!tmp_bool) {
61410 					goto fail_proxy_rejected;  /* retval indicates delete failed */
61411 				}
61412 
61413 				/* Target object must be checked for a conflicting
61414 				 * non-configurable property.
61415 				 */
61416 				tv_key = DUK_GET_TVAL_NEGIDX(thr, -1);
61417 				arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
61418 				DUK_ASSERT(key != NULL);
61419 
61420 				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
61421 					duk_small_int_t desc_reject;
61422 
61423 					DUK_DDD(DUK_DDDPRINT("proxy 'deleteProperty': target has matching property %!O, check for "
61424 					                     "conflicting property; desc.flags=0x%08lx, "
61425 					                     "desc.get=%p, desc.set=%p",
61426 					                     (duk_heaphdr *) key, (unsigned long) desc.flags,
61427 					                     (void *) desc.get, (void *) desc.set));
61428 
61429 					desc_reject = !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE);
61430 					if (desc_reject) {
61431 						/* unconditional */
61432 						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
61433 						DUK_WO_NORETURN(return 0;);
61434 					}
61435 				}
61436 				rc = 1;  /* success */
61437 				goto done_rc;
61438 			}
61439 
61440 			obj = h_target;  /* resume delete to target */
61441 		}
61442 #endif  /* DUK_USE_ES6_PROXY */
61443 
61444 		arr_idx = duk__to_property_key(thr, -1, &key);
61445 		DUK_ASSERT(key != NULL);
61446 
61447 		rc = duk_hobject_delprop_raw(thr, obj, key, throw_flag ? DUK_DELPROP_FLAG_THROW : 0);
61448 		goto done_rc;
61449 	} else if (DUK_TVAL_IS_STRING(tv_obj)) {
61450 		/* String has .length and array index virtual properties
61451 		 * which can't be deleted.  No need for a symbol check;
61452 		 * no offending virtual symbols exist.
61453 		 */
61454 		/* XXX: unnecessary string coercion for array indices,
61455 		 * intentional to keep small.
61456 		 */
61457 		duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
61458 		DUK_ASSERT(h != NULL);
61459 
61460 		arr_idx = duk__to_property_key(thr, -1, &key);
61461 		DUK_ASSERT(key != NULL);
61462 
61463 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
61464 			goto fail_not_configurable;
61465 		}
61466 
61467 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
61468 		    arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
61469 			goto fail_not_configurable;
61470 		}
61471 	} else if (DUK_TVAL_IS_BUFFER(tv_obj)) {
61472 		/* XXX: unnecessary string coercion for array indices,
61473 		 * intentional to keep small; some overlap with string
61474 		 * handling.
61475 		 */
61476 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
61477 		DUK_ASSERT(h != NULL);
61478 
61479 		arr_idx = duk__to_property_key(thr, -1, &key);
61480 		DUK_ASSERT(key != NULL);
61481 
61482 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
61483 			goto fail_not_configurable;
61484 		}
61485 
61486 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
61487 		    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
61488 			goto fail_not_configurable;
61489 		}
61490 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_obj)) {
61491 		/* Lightfunc has no virtual properties since Duktape 2.2
61492 		 * so success.  Still must coerce key for side effects.
61493 		 */
61494 
61495 		arr_idx = duk__to_property_key(thr, -1, &key);
61496 		DUK_ASSERT(key != NULL);
61497 		DUK_UNREF(key);
61498 	}
61499 
61500 	/* non-object base, no offending virtual property */
61501 	rc = 1;
61502 	goto done_rc;
61503 
61504  done_rc:
61505 	duk_set_top_unsafe(thr, entry_top);
61506 	return rc;
61507 
61508  fail_invalid_base_uncond:
61509 	/* Note: unconditional throw */
61510 	DUK_ASSERT(duk_get_top(thr) == entry_top);
61511 #if defined(DUK_USE_PARANOID_ERRORS)
61512 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
61513 #else
61514 	DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot delete property %s of %s",
61515 	               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
61516 #endif
61517 	DUK_WO_NORETURN(return 0;);
61518 
61519 #if defined(DUK_USE_ES6_PROXY)
61520  fail_proxy_rejected:
61521 	if (throw_flag) {
61522 		DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
61523 		DUK_WO_NORETURN(return 0;);
61524 	}
61525 	duk_set_top_unsafe(thr, entry_top);
61526 	return 0;
61527 #endif
61528 
61529  fail_not_configurable:
61530 	if (throw_flag) {
61531 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
61532 		DUK_WO_NORETURN(return 0;);
61533 	}
61534 	duk_set_top_unsafe(thr, entry_top);
61535 	return 0;
61536 }
61537 
61538 /*
61539  *  Internal helper to define a property with specific flags, ignoring
61540  *  normal semantics such as extensibility, write protection etc.
61541  *  Overwrites any existing value and attributes unless caller requests
61542  *  that value only be updated if it doesn't already exists.
61543  *
61544  *  Does not support:
61545  *    - virtual properties (error if write attempted)
61546  *    - getter/setter properties (error if write attempted)
61547  *    - non-default (!= WEC) attributes for array entries (error if attempted)
61548  *    - array abandoning: if array part exists, it is always extended
61549  *    - array 'length' updating
61550  *
61551  *  Stack: [... in_val] -> []
61552  *
61553  *  Used for e.g. built-in initialization and environment record
61554  *  operations.
61555  */
61556 
61557 DUK_INTERNAL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags) {
61558 	duk_propdesc desc;
61559 	duk_uint32_t arr_idx;
61560 	duk_int_t e_idx;
61561 	duk_tval *tv1 = NULL;
61562 	duk_tval *tv2 = NULL;
61563 	duk_small_uint_t propflags = flags & DUK_PROPDESC_FLAGS_MASK;  /* mask out flags not actually stored */
61564 
61565 	DUK_DDD(DUK_DDDPRINT("define new property (internal): thr=%p, obj=%!O, key=%!O, flags=0x%02lx, val=%!T",
61566 	                     (void *) thr, (duk_heaphdr *) obj, (duk_heaphdr *) key,
61567 	                     (unsigned long) flags, (duk_tval *) duk_get_tval(thr, -1)));
61568 
61569 	DUK_ASSERT(thr != NULL);
61570 	DUK_ASSERT(thr->heap != NULL);
61571 	DUK_ASSERT(obj != NULL);
61572 	DUK_ASSERT(key != NULL);
61573 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
61574 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
61575 	DUK_ASSERT(duk_is_valid_index(thr, -1));  /* contains value */
61576 
61577 	arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
61578 
61579 	if (duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
61580 		if (desc.e_idx >= 0) {
61581 			if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
61582 				DUK_DDD(DUK_DDDPRINT("property already exists in the entry part -> skip as requested"));
61583 				goto pop_exit;
61584 			}
61585 			DUK_DDD(DUK_DDDPRINT("property already exists in the entry part -> update value and attributes"));
61586 			if (DUK_UNLIKELY(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx))) {
61587 				DUK_D(DUK_DPRINT("existing property is an accessor, not supported"));
61588 				goto error_internal;
61589 			}
61590 
61591 			DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, desc.e_idx, propflags);
61592 			tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
61593 		} else if (desc.a_idx >= 0) {
61594 			if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
61595 				DUK_DDD(DUK_DDDPRINT("property already exists in the array part -> skip as requested"));
61596 				goto pop_exit;
61597 			}
61598 			DUK_DDD(DUK_DDDPRINT("property already exists in the array part -> update value (assert attributes)"));
61599 			if (propflags != DUK_PROPDESC_FLAGS_WEC) {
61600 				DUK_D(DUK_DPRINT("existing property in array part, but propflags not WEC (0x%02lx)",
61601 				                 (unsigned long) propflags));
61602 				goto error_internal;
61603 			}
61604 
61605 			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, desc.a_idx);
61606 		} else {
61607 			if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
61608 				DUK_DDD(DUK_DDDPRINT("property already exists but is virtual -> skip as requested"));
61609 				goto pop_exit;
61610 			}
61611 			if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
61612 				duk_uint32_t new_len;
61613 #if defined(DUK_USE_DEBUG)
61614 				duk_uint32_t prev_len;
61615 				prev_len = ((duk_harray *) obj)->length;
61616 #endif
61617 				new_len = duk__to_new_array_length_checked(thr, DUK_GET_TVAL_NEGIDX(thr, -1));
61618 				((duk_harray *) obj)->length = new_len;
61619 				DUK_DD(DUK_DDPRINT("internal define property for array .length: %ld -> %ld",
61620 				                   (long) prev_len, (long) ((duk_harray *) obj)->length));
61621 				goto pop_exit;
61622 			}
61623 			DUK_DD(DUK_DDPRINT("property already exists but is virtual -> failure"));
61624 			goto error_virtual;
61625 		}
61626 
61627 		goto write_value;
61628 	}
61629 
61630 	if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
61631 		if (arr_idx != DUK__NO_ARRAY_INDEX) {
61632 			DUK_DDD(DUK_DDDPRINT("property does not exist, object has array part -> possibly extend array part and write value (assert attributes)"));
61633 			DUK_ASSERT(propflags == DUK_PROPDESC_FLAGS_WEC);
61634 
61635 			tv1 = duk__obtain_arridx_slot(thr, arr_idx, obj);
61636 			if (tv1 == NULL) {
61637 				DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(obj));
61638 				goto write_to_entry_part;
61639 			}
61640 
61641 			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
61642 			goto write_value;
61643 		}
61644 	}
61645 
61646  write_to_entry_part:
61647 	DUK_DDD(DUK_DDDPRINT("property does not exist, object belongs in entry part -> allocate new entry and write value and attributes"));
61648 	e_idx = duk__hobject_alloc_entry_checked(thr, obj, key);  /* increases key refcount */
61649 	DUK_ASSERT(e_idx >= 0);
61650 	DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, propflags);
61651 	tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
61652 	/* new entry: previous value is garbage; set to undefined to share write_value */
61653 	DUK_TVAL_SET_UNDEFINED(tv1);
61654 	goto write_value;
61655 
61656  write_value:
61657 	/* tv1 points to value storage */
61658 
61659 	tv2 = duk_require_tval(thr, -1);  /* late lookup, avoid side effects */
61660 	DUK_DDD(DUK_DDDPRINT("writing/updating value: %!T -> %!T",
61661 	                     (duk_tval *) tv1, (duk_tval *) tv2));
61662 
61663 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
61664 	goto pop_exit;
61665 
61666  pop_exit:
61667 	duk_pop_unsafe(thr);  /* remove in_val */
61668 	return;
61669 
61670  error_virtual:  /* share error message */
61671  error_internal:
61672 	DUK_ERROR_INTERNAL(thr);
61673 	DUK_WO_NORETURN(return;);
61674 }
61675 
61676 /*
61677  *  Fast path for defining array indexed values without interning the key.
61678  *  This is used by e.g. code for Array prototype and traceback creation so
61679  *  must avoid interning.
61680  */
61681 
61682 DUK_INTERNAL void duk_hobject_define_property_internal_arridx(duk_hthread *thr, duk_hobject *obj, duk_uarridx_t arr_idx, duk_small_uint_t flags) {
61683 	duk_hstring *key;
61684 	duk_tval *tv1, *tv2;
61685 
61686 	DUK_DDD(DUK_DDDPRINT("define new property (internal) arr_idx fast path: thr=%p, obj=%!O, "
61687 	                     "arr_idx=%ld, flags=0x%02lx, val=%!T",
61688 	                     (void *) thr, obj, (long) arr_idx, (unsigned long) flags,
61689 	                     (duk_tval *) duk_get_tval(thr, -1)));
61690 
61691 	DUK_ASSERT(thr != NULL);
61692 	DUK_ASSERT(thr->heap != NULL);
61693 	DUK_ASSERT(obj != NULL);
61694 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
61695 
61696 	if (DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
61697 	    arr_idx != DUK__NO_ARRAY_INDEX &&
61698 	    flags == DUK_PROPDESC_FLAGS_WEC) {
61699 		DUK_ASSERT((flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) == 0);  /* covered by comparison */
61700 
61701 		DUK_DDD(DUK_DDDPRINT("define property to array part (property may or may not exist yet)"));
61702 
61703 		tv1 = duk__obtain_arridx_slot(thr, arr_idx, obj);
61704 		if (tv1 == NULL) {
61705 			DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(obj));
61706 			goto write_slow;
61707 		}
61708 		tv2 = duk_require_tval(thr, -1);
61709 
61710 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
61711 
61712 		duk_pop_unsafe(thr);  /* [ ...val ] -> [ ... ] */
61713 		return;
61714 	}
61715 
61716  write_slow:
61717 	DUK_DDD(DUK_DDDPRINT("define property fast path didn't work, use slow path"));
61718 
61719 	key = duk_push_uint_to_hstring(thr, (duk_uint_t) arr_idx);
61720 	DUK_ASSERT(key != NULL);
61721 	duk_insert(thr, -2);  /* [ ... val key ] -> [ ... key val ] */
61722 
61723 	duk_hobject_define_property_internal(thr, obj, key, flags);
61724 
61725 	duk_pop_unsafe(thr);  /* [ ... key ] -> [ ... ] */
61726 }
61727 
61728 /*
61729  *  Internal helpers for managing object 'length'
61730  */
61731 
61732 DUK_INTERNAL duk_size_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj) {
61733 	duk_double_t val;
61734 
61735 	DUK_CTX_ASSERT_VALID(thr);
61736 	DUK_ASSERT(obj != NULL);
61737 
61738 	/* Fast path for Arrays. */
61739 	if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
61740 		return ((duk_harray *) obj)->length;
61741 	}
61742 
61743 	/* Slow path, .length can be e.g. accessor, obj can be a Proxy, etc. */
61744 	duk_push_hobject(thr, obj);
61745 	duk_push_hstring_stridx(thr, DUK_STRIDX_LENGTH);
61746 	(void) duk_hobject_getprop(thr,
61747 	                           DUK_GET_TVAL_NEGIDX(thr, -2),
61748 	                           DUK_GET_TVAL_NEGIDX(thr, -1));
61749 	val = duk_to_number_m1(thr);
61750 	duk_pop_3_unsafe(thr);
61751 
61752 	/* This isn't part of ECMAScript semantics; return a value within
61753 	 * duk_size_t range, or 0 otherwise.
61754 	 */
61755 	if (val >= 0.0 && val <= (duk_double_t) DUK_SIZE_MAX) {
61756 		return (duk_size_t) val;
61757 	}
61758 	return 0;
61759 }
61760 
61761 /*
61762  *  Fast finalizer check for an object.  Walks the prototype chain, checking
61763  *  for finalizer presence using DUK_HOBJECT_FLAG_HAVE_FINALIZER which is kept
61764  *  in sync with the actual property when setting/removing the finalizer.
61765  */
61766 
61767 #if defined(DUK_USE_HEAPPTR16)
61768 DUK_INTERNAL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_heap *heap, duk_hobject *obj) {
61769 #else
61770 DUK_INTERNAL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_hobject *obj) {
61771 #endif
61772 	duk_uint_t sanity;
61773 
61774 	DUK_ASSERT(obj != NULL);
61775 
61776 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
61777 	do {
61778 		if (DUK_UNLIKELY(DUK_HOBJECT_HAS_HAVE_FINALIZER(obj))) {
61779 			return 1;
61780 		}
61781 		if (DUK_UNLIKELY(sanity-- == 0)) {
61782 			DUK_D(DUK_DPRINT("prototype loop when checking for finalizer existence; returning false"));
61783 			return 0;
61784 		}
61785 #if defined(DUK_USE_HEAPPTR16)
61786 		DUK_ASSERT(heap != NULL);
61787 		obj = DUK_HOBJECT_GET_PROTOTYPE(heap, obj);
61788 #else
61789 		obj = DUK_HOBJECT_GET_PROTOTYPE(NULL, obj);  /* 'heap' arg ignored */
61790 #endif
61791 	} while (obj != NULL);
61792 
61793 	return 0;
61794 }
61795 
61796 /*
61797  *  Object.getOwnPropertyDescriptor()  (E5 Sections 15.2.3.3, 8.10.4)
61798  *
61799  *  [ ... key ] -> [ ... desc/undefined ]
61800  */
61801 
61802 DUK_INTERNAL void duk_hobject_object_get_own_property_descriptor(duk_hthread *thr, duk_idx_t obj_idx) {
61803 	duk_hobject *obj;
61804 	duk_hstring *key;
61805 	duk_propdesc pd;
61806 
61807 	DUK_ASSERT(thr != NULL);
61808 	DUK_ASSERT(thr->heap != NULL);
61809 
61810 	obj = duk_require_hobject_promote_mask(thr, obj_idx, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
61811 	key = duk_to_property_key_hstring(thr, -1);
61812 	DUK_ASSERT(key != NULL);
61813 
61814 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
61815 
61816 	if (!duk_hobject_get_own_propdesc(thr, obj, key, &pd, DUK_GETDESC_FLAG_PUSH_VALUE)) {
61817 		duk_push_undefined(thr);
61818 		duk_remove_m2(thr);
61819 		return;
61820 	}
61821 
61822 	duk_push_object(thr);
61823 
61824 	/* [ ... key value desc ] */
61825 
61826 	if (DUK_PROPDESC_IS_ACCESSOR(&pd)) {
61827 		/* If a setter/getter is missing (undefined), the descriptor must
61828 		 * still have the property present with the value 'undefined'.
61829 		 */
61830 		if (pd.get) {
61831 			duk_push_hobject(thr, pd.get);
61832 		} else {
61833 			duk_push_undefined(thr);
61834 		}
61835 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_GET);
61836 		if (pd.set) {
61837 			duk_push_hobject(thr, pd.set);
61838 		} else {
61839 			duk_push_undefined(thr);
61840 		}
61841 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_SET);
61842 	} else {
61843 		duk_dup_m2(thr);
61844 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_VALUE);
61845 		duk_push_boolean(thr, DUK_PROPDESC_IS_WRITABLE(&pd));
61846 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_WRITABLE);
61847 	}
61848 	duk_push_boolean(thr, DUK_PROPDESC_IS_ENUMERABLE(&pd));
61849 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_ENUMERABLE);
61850 	duk_push_boolean(thr, DUK_PROPDESC_IS_CONFIGURABLE(&pd));
61851 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_CONFIGURABLE);
61852 
61853 	/* [ ... key value desc ] */
61854 
61855 	duk_replace(thr, -3);
61856 	duk_pop_unsafe(thr);  /* -> [ ... desc ] */
61857 }
61858 
61859 /*
61860  *  NormalizePropertyDescriptor() related helper.
61861  *
61862  *  Internal helper which validates and normalizes a property descriptor
61863  *  represented as an ECMAScript object (e.g. argument to defineProperty()).
61864  *  The output of this conversion is a set of defprop_flags and possibly
61865  *  some values pushed on the value stack to (1) ensure borrowed pointers
61866  *  remain valid, and (2) avoid unnecessary pops for footprint reasons.
61867  *  Caller must manage stack top carefully because the number of values
61868  *  pushed depends on the input property descriptor.
61869  *
61870  *  The original descriptor object must not be altered in the process.
61871  */
61872 
61873 /* XXX: very basic optimization -> duk_get_prop_stridx_top */
61874 
61875 DUK_INTERNAL
61876 void duk_hobject_prepare_property_descriptor(duk_hthread *thr,
61877                                              duk_idx_t idx_in,
61878                                              duk_uint_t *out_defprop_flags,
61879                                              duk_idx_t *out_idx_value,
61880                                              duk_hobject **out_getter,
61881                                              duk_hobject **out_setter) {
61882 	duk_idx_t idx_value = -1;
61883 	duk_hobject *getter = NULL;
61884 	duk_hobject *setter = NULL;
61885 	duk_bool_t is_data_desc = 0;
61886 	duk_bool_t is_acc_desc = 0;
61887 	duk_uint_t defprop_flags = 0;
61888 
61889 	DUK_ASSERT(out_defprop_flags != NULL);
61890 	DUK_ASSERT(out_idx_value != NULL);
61891 	DUK_ASSERT(out_getter != NULL);
61892 	DUK_ASSERT(out_setter != NULL);
61893 	DUK_ASSERT(idx_in <= 0x7fffL);  /* short variants would be OK, but not used to avoid shifts */
61894 
61895 	/* Must be an object, otherwise TypeError (E5.1 Section 8.10.5, step 1). */
61896 	idx_in = duk_require_normalize_index(thr, idx_in);
61897 	(void) duk_require_hobject(thr, idx_in);
61898 
61899 	/* The coercion order must match the ToPropertyDescriptor() algorithm
61900 	 * so that side effects in coercion happen in the correct order.
61901 	 * (This order also happens to be compatible with duk_def_prop(),
61902 	 * although it doesn't matter in practice.)
61903 	 */
61904 
61905 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_VALUE)) {
61906 		is_data_desc = 1;
61907 		defprop_flags |= DUK_DEFPROP_HAVE_VALUE;
61908 		idx_value = duk_get_top_index(thr);
61909 	}
61910 
61911 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_WRITABLE)) {
61912 		is_data_desc = 1;
61913 		if (duk_to_boolean_top_pop(thr)) {
61914 			defprop_flags |= DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE;
61915 		} else {
61916 			defprop_flags |= DUK_DEFPROP_HAVE_WRITABLE;
61917 		}
61918 	}
61919 
61920 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_GET)) {
61921 		duk_tval *tv = duk_require_tval(thr, -1);
61922 		duk_hobject *h_get;
61923 
61924 		if (DUK_TVAL_IS_UNDEFINED(tv)) {
61925 			/* undefined is accepted */
61926 			DUK_ASSERT(getter == NULL);
61927 		} else {
61928 			/* NOTE: lightfuncs are coerced to full functions because
61929 			 * lightfuncs don't fit into a property value slot.  This
61930 			 * has some side effects, see test-dev-lightfunc-accessor.js.
61931 			 */
61932 			h_get = duk_get_hobject_promote_lfunc(thr, -1);
61933 			if (h_get == NULL || !DUK_HOBJECT_IS_CALLABLE(h_get)) {
61934 				goto type_error;
61935 			}
61936 			getter = h_get;
61937 		}
61938 		is_acc_desc = 1;
61939 		defprop_flags |= DUK_DEFPROP_HAVE_GETTER;
61940 	}
61941 
61942 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_SET)) {
61943 		duk_tval *tv = duk_require_tval(thr, -1);
61944 		duk_hobject *h_set;
61945 
61946 		if (DUK_TVAL_IS_UNDEFINED(tv)) {
61947 			/* undefined is accepted */
61948 			DUK_ASSERT(setter == NULL);
61949 		}  else {
61950 			/* NOTE: lightfuncs are coerced to full functions because
61951 			 * lightfuncs don't fit into a property value slot.  This
61952 			 * has some side effects, see test-dev-lightfunc-accessor.js.
61953 			 */
61954 			h_set = duk_get_hobject_promote_lfunc(thr, -1);
61955 			if (h_set == NULL || !DUK_HOBJECT_IS_CALLABLE(h_set)) {
61956 				goto type_error;
61957 			}
61958 			setter = h_set;
61959 		}
61960 		is_acc_desc = 1;
61961 		defprop_flags |= DUK_DEFPROP_HAVE_SETTER;
61962 	}
61963 
61964 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_ENUMERABLE)) {
61965 		if (duk_to_boolean_top_pop(thr)) {
61966 			defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE;
61967 		} else {
61968 			defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE;
61969 		}
61970 	}
61971 
61972 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_CONFIGURABLE)) {
61973 		if (duk_to_boolean_top_pop(thr)) {
61974 			defprop_flags |= DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE;
61975 		} else {
61976 			defprop_flags |= DUK_DEFPROP_HAVE_CONFIGURABLE;
61977 		}
61978 	}
61979 
61980 	if (is_data_desc && is_acc_desc) {
61981 		goto type_error;
61982 	}
61983 
61984 	*out_defprop_flags = defprop_flags;
61985 	*out_idx_value = idx_value;
61986 	*out_getter = getter;
61987 	*out_setter = setter;
61988 
61989 	/* [ ... [multiple values] ] */
61990 	return;
61991 
61992  type_error:
61993 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_DESCRIPTOR);
61994 	DUK_WO_NORETURN(return;);
61995 }
61996 
61997 /*
61998  *  Object.defineProperty() related helper (E5 Section 15.2.3.6).
61999  *  Also handles ES2015 Reflect.defineProperty().
62000  *
62001  *  Inlines all [[DefineOwnProperty]] exotic behaviors.
62002  *
62003  *  Note: ECMAScript compliant [[DefineOwnProperty]](P, Desc, Throw) is not
62004  *  implemented directly, but Object.defineProperty() serves its purpose.
62005  *  We don't need the [[DefineOwnProperty]] internally and we don't have a
62006  *  property descriptor with 'missing values' so it's easier to avoid it
62007  *  entirely.
62008  *
62009  *  Note: this is only called for actual objects, not primitive values.
62010  *  This must support virtual properties for full objects (e.g. Strings)
62011  *  but not for plain values (e.g. strings).  Lightfuncs, even though
62012  *  primitive in a sense, are treated like objects and accepted as target
62013  *  values.
62014  */
62015 
62016 /* XXX: this is a major target for size optimization */
62017 DUK_INTERNAL
62018 duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
62019                                               duk_uint_t defprop_flags,
62020                                               duk_hobject *obj,
62021                                               duk_hstring *key,
62022                                               duk_idx_t idx_value,
62023                                               duk_hobject *get,
62024                                               duk_hobject *set,
62025                                               duk_bool_t throw_flag) {
62026 	duk_uint32_t arr_idx;
62027 	duk_tval tv;
62028 	duk_bool_t has_enumerable;
62029 	duk_bool_t has_configurable;
62030 	duk_bool_t has_writable;
62031 	duk_bool_t has_value;
62032 	duk_bool_t has_get;
62033 	duk_bool_t has_set;
62034 	duk_bool_t is_enumerable;
62035 	duk_bool_t is_configurable;
62036 	duk_bool_t is_writable;
62037 	duk_bool_t force_flag;
62038 	duk_small_uint_t new_flags;
62039 	duk_propdesc curr;
62040 	duk_uint32_t arridx_new_array_length;  /* != 0 => post-update for array 'length' (used when key is an array index) */
62041 	duk_uint32_t arrlen_old_len;
62042 	duk_uint32_t arrlen_new_len;
62043 	duk_bool_t pending_write_protect;
62044 
62045 	DUK_ASSERT(thr != NULL);
62046 	DUK_ASSERT(thr->heap != NULL);
62047 	DUK_ASSERT(obj != NULL);
62048 	DUK_ASSERT(key != NULL);
62049 	/* idx_value may be < 0 (no value), set and get may be NULL */
62050 
62051 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
62052 
62053 	/* All the flags fit in 16 bits, so will fit into duk_bool_t. */
62054 
62055 	has_writable = (defprop_flags & DUK_DEFPROP_HAVE_WRITABLE);
62056 	has_enumerable = (defprop_flags & DUK_DEFPROP_HAVE_ENUMERABLE);
62057 	has_configurable = (defprop_flags & DUK_DEFPROP_HAVE_CONFIGURABLE);
62058 	has_value = (defprop_flags & DUK_DEFPROP_HAVE_VALUE);
62059 	has_get = (defprop_flags & DUK_DEFPROP_HAVE_GETTER);
62060 	has_set = (defprop_flags & DUK_DEFPROP_HAVE_SETTER);
62061 	is_writable = (defprop_flags & DUK_DEFPROP_WRITABLE);
62062 	is_enumerable = (defprop_flags & DUK_DEFPROP_ENUMERABLE);
62063 	is_configurable = (defprop_flags & DUK_DEFPROP_CONFIGURABLE);
62064 	force_flag = (defprop_flags & DUK_DEFPROP_FORCE);
62065 
62066 	arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
62067 
62068 	arridx_new_array_length = 0;
62069 	pending_write_protect = 0;
62070 	arrlen_old_len = 0;
62071 	arrlen_new_len = 0;
62072 
62073 	DUK_DDD(DUK_DDDPRINT("has_enumerable=%ld is_enumerable=%ld "
62074 	                     "has_configurable=%ld is_configurable=%ld "
62075 	                     "has_writable=%ld is_writable=%ld "
62076 	                     "has_value=%ld value=%!T "
62077 	                     "has_get=%ld get=%p=%!O "
62078 	                     "has_set=%ld set=%p=%!O "
62079 	                     "arr_idx=%ld throw_flag=!%ld",
62080 	                     (long) has_enumerable, (long) is_enumerable,
62081 	                     (long) has_configurable, (long) is_configurable,
62082 	                     (long) has_writable, (long) is_writable,
62083 	                     (long) has_value, (duk_tval *) (idx_value >= 0 ? duk_get_tval(thr, idx_value) : NULL),
62084 	                     (long) has_get, (void *) get, (duk_heaphdr *) get,
62085 	                     (long) has_set, (void *) set, (duk_heaphdr *) set,
62086 	                     (long) arr_idx, (long) throw_flag));
62087 
62088 	/*
62089 	 *  Array exotic behaviors can be implemented at this point.  The local variables
62090 	 *  are essentially a 'value copy' of the input descriptor (Desc), which is modified
62091 	 *  by the Array [[DefineOwnProperty]] (E5 Section 15.4.5.1).
62092 	 */
62093 
62094 	if (!DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
62095 		goto skip_array_exotic;
62096 	}
62097 
62098 	if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
62099 		duk_harray *a;
62100 
62101 		/* E5 Section 15.4.5.1, step 3, steps a - i are implemented here, j - n at the end */
62102 		if (!has_value) {
62103 			DUK_DDD(DUK_DDDPRINT("exotic array behavior for 'length', but no value in descriptor -> normal behavior"));
62104 			goto skip_array_exotic;
62105 		}
62106 
62107 		DUK_DDD(DUK_DDDPRINT("exotic array behavior for 'length', value present in descriptor -> exotic behavior"));
62108 
62109 		/*
62110 		 *  Get old and new length
62111 		 */
62112 
62113 		a = (duk_harray *) obj;
62114 		DUK_HARRAY_ASSERT_VALID(a);
62115 		arrlen_old_len = a->length;
62116 
62117 		DUK_ASSERT(idx_value >= 0);
62118 		arrlen_new_len = duk__to_new_array_length_checked(thr, DUK_GET_TVAL_POSIDX(thr, idx_value));
62119 		duk_push_u32(thr, arrlen_new_len);
62120 		duk_replace(thr, idx_value);  /* step 3.e: replace 'Desc.[[Value]]' */
62121 
62122 		DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld", (long) arrlen_old_len, (long) arrlen_new_len));
62123 
62124 		if (arrlen_new_len >= arrlen_old_len) {
62125 			/* standard behavior, step 3.f.i */
62126 			DUK_DDD(DUK_DDDPRINT("new length is same or higher as previous => standard behavior"));
62127 			goto skip_array_exotic;
62128 		}
62129 		DUK_DDD(DUK_DDDPRINT("new length is smaller than previous => exotic post behavior"));
62130 
62131 		/* XXX: consolidated algorithm step 15.f -> redundant? */
62132 		if (DUK_HARRAY_LENGTH_NONWRITABLE(a) && !force_flag) {
62133 			/* Array .length is always non-configurable; if it's also
62134 			 * non-writable, don't allow it to be written.
62135 			 */
62136 			goto fail_not_configurable;
62137 		}
62138 
62139 		/* steps 3.h and 3.i */
62140 		if (has_writable && !is_writable) {
62141 			DUK_DDD(DUK_DDDPRINT("desc writable is false, force it back to true, and flag pending write protect"));
62142 			is_writable = 1;
62143 			pending_write_protect = 1;
62144 		}
62145 
62146 		/* remaining actual steps are carried out if standard DefineOwnProperty succeeds */
62147 	} else if (arr_idx != DUK__NO_ARRAY_INDEX) {
62148 		/* XXX: any chance of unifying this with the 'length' key handling? */
62149 
62150 		/* E5 Section 15.4.5.1, step 4 */
62151 		duk_uint32_t old_len;
62152 		duk_harray *a;
62153 
62154 		a = (duk_harray *) obj;
62155 		DUK_HARRAY_ASSERT_VALID(a);
62156 
62157 		old_len = a->length;
62158 
62159 		if (arr_idx >= old_len) {
62160 			DUK_DDD(DUK_DDDPRINT("defineProperty requires array length update "
62161 			                     "(arr_idx=%ld, old_len=%ld)",
62162 			                     (long) arr_idx, (long) old_len));
62163 
62164 			if (DUK_HARRAY_LENGTH_NONWRITABLE(a) && !force_flag) {
62165 				/* Array .length is always non-configurable, so
62166 				 * if it's also non-writable, don't allow a value
62167 				 * write.  With force flag allow writing.
62168 				 */
62169 				goto fail_not_configurable;
62170 			}
62171 
62172 			/* actual update happens once write has been completed without
62173 			 * error below.
62174 			 */
62175 			DUK_ASSERT(arr_idx != 0xffffffffUL);
62176 			arridx_new_array_length = arr_idx + 1;
62177 		} else {
62178 			DUK_DDD(DUK_DDDPRINT("defineProperty does not require length update "
62179 			                     "(arr_idx=%ld, old_len=%ld) -> standard behavior",
62180 			                     (long) arr_idx, (long) old_len));
62181 		}
62182 	}
62183  skip_array_exotic:
62184 
62185 	/* XXX: There is currently no support for writing buffer object
62186 	 * indexed elements here.  Attempt to do so will succeed and
62187 	 * write a concrete property into the buffer object.  This should
62188 	 * be fixed at some point but because buffers are a custom feature
62189 	 * anyway, this is relatively unimportant.
62190 	 */
62191 
62192 	/*
62193 	 *  Actual Object.defineProperty() default algorithm.
62194 	 */
62195 
62196 	/*
62197 	 *  First check whether property exists; if not, simple case.  This covers
62198 	 *  steps 1-4.
62199 	 */
62200 
62201 	if (!duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE)) {
62202 		DUK_DDD(DUK_DDDPRINT("property does not exist"));
62203 
62204 		if (!DUK_HOBJECT_HAS_EXTENSIBLE(obj) && !force_flag) {
62205 			goto fail_not_extensible;
62206 		}
62207 
62208 #if defined(DUK_USE_ROM_OBJECTS)
62209 		/* ROM objects are never extensible but force flag may
62210 		 * allow us to come here anyway.
62211 		 */
62212 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj) || !DUK_HOBJECT_HAS_EXTENSIBLE(obj));
62213 		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
62214 			DUK_D(DUK_DPRINT("attempt to define property on a read-only target object"));
62215 			goto fail_not_configurable;
62216 		}
62217 #endif
62218 
62219 		/* XXX: share final setting code for value and flags?  difficult because
62220 		 * refcount code is different.  Share entry allocation?  But can't allocate
62221 		 * until array index checked.
62222 		 */
62223 
62224 		/* steps 4.a and 4.b are tricky */
62225 		if (has_set || has_get) {
62226 			duk_int_t e_idx;
62227 
62228 			DUK_DDD(DUK_DDDPRINT("create new accessor property"));
62229 
62230 			DUK_ASSERT(has_set || set == NULL);
62231 			DUK_ASSERT(has_get || get == NULL);
62232 			DUK_ASSERT(!has_value);
62233 			DUK_ASSERT(!has_writable);
62234 
62235 			new_flags = DUK_PROPDESC_FLAG_ACCESSOR;  /* defaults, E5 Section 8.6.1, Table 7 */
62236 			if (has_enumerable && is_enumerable) {
62237 				new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
62238 			}
62239 			if (has_configurable && is_configurable) {
62240 				new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
62241 			}
62242 
62243 			if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
62244 				DUK_DDD(DUK_DDDPRINT("accessor cannot go to array part, abandon array"));
62245 				duk__abandon_array_part(thr, obj);
62246 			}
62247 
62248 			/* write to entry part */
62249 			e_idx = duk__hobject_alloc_entry_checked(thr, obj, key);
62250 			DUK_ASSERT(e_idx >= 0);
62251 
62252 			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, e_idx, get);
62253 			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, e_idx, set);
62254 			DUK_HOBJECT_INCREF_ALLOWNULL(thr, get);
62255 			DUK_HOBJECT_INCREF_ALLOWNULL(thr, set);
62256 
62257 			DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, new_flags);
62258 			goto success_exotics;
62259 		} else {
62260 			duk_int_t e_idx;
62261 			duk_tval *tv2;
62262 
62263 			DUK_DDD(DUK_DDDPRINT("create new data property"));
62264 
62265 			DUK_ASSERT(!has_set);
62266 			DUK_ASSERT(!has_get);
62267 
62268 			new_flags = 0;  /* defaults, E5 Section 8.6.1, Table 7 */
62269 			if (has_writable && is_writable) {
62270 				new_flags |= DUK_PROPDESC_FLAG_WRITABLE;
62271 			}
62272 			if (has_enumerable && is_enumerable) {
62273 				new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
62274 			}
62275 			if (has_configurable && is_configurable) {
62276 				new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
62277 			}
62278 			if (has_value) {
62279 				duk_tval *tv_tmp = duk_require_tval(thr, idx_value);
62280 				DUK_TVAL_SET_TVAL(&tv, tv_tmp);
62281 			} else {
62282 				DUK_TVAL_SET_UNDEFINED(&tv);  /* default value */
62283 			}
62284 
62285 			if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
62286 				if (new_flags == DUK_PROPDESC_FLAGS_WEC) {
62287 					DUK_DDD(DUK_DDDPRINT("new data property attributes match array defaults, attempt to write to array part"));
62288 					tv2 = duk__obtain_arridx_slot(thr, arr_idx, obj);
62289 					if (tv2 == NULL) {
62290 						DUK_DDD(DUK_DDDPRINT("failed writing to array part, abandoned array"));
62291 					} else {
62292 						DUK_DDD(DUK_DDDPRINT("success in writing to array part"));
62293 						DUK_ASSERT(DUK_HOBJECT_HAS_ARRAY_PART(obj));
62294 						DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv2));
62295 						DUK_TVAL_SET_TVAL(tv2, &tv);
62296 						DUK_TVAL_INCREF(thr, tv2);
62297 						goto success_exotics;
62298 					}
62299 				} else {
62300 					DUK_DDD(DUK_DDDPRINT("new data property cannot go to array part, abandon array"));
62301 					duk__abandon_array_part(thr, obj);
62302 				}
62303 				/* fall through */
62304 			}
62305 
62306 			/* write to entry part */
62307 			e_idx = duk__hobject_alloc_entry_checked(thr, obj, key);
62308 			DUK_ASSERT(e_idx >= 0);
62309 			tv2 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
62310 			DUK_TVAL_SET_TVAL(tv2, &tv);
62311 			DUK_TVAL_INCREF(thr, tv2);
62312 
62313 			DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, new_flags);
62314 			goto success_exotics;
62315 		}
62316 		DUK_UNREACHABLE();
62317 	}
62318 
62319 	/* we currently assume virtual properties are not configurable (as none of them are) */
62320 	DUK_ASSERT((curr.e_idx >= 0 || curr.a_idx >= 0) || !(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE));
62321 
62322 	/* [obj key desc value get set curr_value] */
62323 
62324 	/*
62325 	 *  Property already exists.  Steps 5-6 detect whether any changes need
62326 	 *  to be made.
62327 	 */
62328 
62329 	if (has_enumerable) {
62330 		if (is_enumerable) {
62331 			if (!(curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE)) {
62332 				goto need_check;
62333 			}
62334 		} else {
62335 			if (curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE) {
62336 				goto need_check;
62337 			}
62338 		}
62339 	}
62340 	if (has_configurable) {
62341 		if (is_configurable) {
62342 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
62343 				goto need_check;
62344 			}
62345 		} else {
62346 			if (curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) {
62347 				goto need_check;
62348 			}
62349 		}
62350 	}
62351 	if (has_value) {
62352 		duk_tval *tmp1;
62353 		duk_tval *tmp2;
62354 
62355 		/* attempt to change from accessor to data property */
62356 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
62357 			goto need_check;
62358 		}
62359 
62360 		tmp1 = duk_require_tval(thr, -1);         /* curr value */
62361 		tmp2 = duk_require_tval(thr, idx_value);  /* new value */
62362 		if (!duk_js_samevalue(tmp1, tmp2)) {
62363 			goto need_check;
62364 		}
62365 	}
62366 	if (has_writable) {
62367 		/* attempt to change from accessor to data property */
62368 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
62369 			goto need_check;
62370 		}
62371 
62372 		if (is_writable) {
62373 			if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
62374 				goto need_check;
62375 			}
62376 		} else {
62377 			if (curr.flags & DUK_PROPDESC_FLAG_WRITABLE) {
62378 				goto need_check;
62379 			}
62380 		}
62381 	}
62382 	if (has_set) {
62383 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
62384 			if (set != curr.set) {
62385 				goto need_check;
62386 			}
62387 		} else {
62388 			goto need_check;
62389 		}
62390 	}
62391 	if (has_get) {
62392 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
62393 			if (get != curr.get) {
62394 				goto need_check;
62395 			}
62396 		} else {
62397 			goto need_check;
62398 		}
62399 	}
62400 
62401 	/* property exists, either 'desc' is empty, or all values
62402 	 * match (SameValue)
62403 	 */
62404 	goto success_no_exotics;
62405 
62406  need_check:
62407 
62408 	/*
62409 	 *  Some change(s) need to be made.  Steps 7-11.
62410 	 */
62411 
62412 	/* shared checks for all descriptor types */
62413 	if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
62414 		if (has_configurable && is_configurable) {
62415 			goto fail_not_configurable;
62416 		}
62417 		if (has_enumerable) {
62418 			if (curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE) {
62419 				if (!is_enumerable) {
62420 					goto fail_not_configurable;
62421 				}
62422 			} else {
62423 				if (is_enumerable) {
62424 					goto fail_not_configurable;
62425 				}
62426 			}
62427 		}
62428 	}
62429 
62430 	/* Virtual properties don't have backing so they can't mostly be
62431 	 * edited.  Some virtual properties are, however, writable: for
62432 	 * example, virtual index properties of buffer objects and Array
62433 	 * instance .length.  These are not configurable so the checks
62434 	 * above mostly cover attempts to change them, except when the
62435 	 * duk_def_prop() call is used with DUK_DEFPROP_FORCE; even in
62436 	 * that case we can't forcibly change the property attributes
62437 	 * because they don't have concrete backing.
62438 	 */
62439 
62440 	/* XXX: for ROM objects too it'd be best if value modify was
62441 	 * allowed if the value matches SameValue.
62442 	 */
62443 	/* Reject attempt to change a read-only object. */
62444 #if defined(DUK_USE_ROM_OBJECTS)
62445 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
62446 		DUK_DD(DUK_DDPRINT("attempt to define property on read-only target object"));
62447 		goto fail_not_configurable;
62448 	}
62449 #endif
62450 
62451 	/* descriptor type specific checks */
62452 	if (has_set || has_get) {
62453 		/* IsAccessorDescriptor(desc) == true */
62454 		DUK_ASSERT(!has_writable);
62455 		DUK_ASSERT(!has_value);
62456 
62457 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
62458 			/* curr and desc are accessors */
62459 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
62460 				if (has_set && set != curr.set) {
62461 					goto fail_not_configurable;
62462 				}
62463 				if (has_get && get != curr.get) {
62464 					goto fail_not_configurable;
62465 				}
62466 			}
62467 		} else {
62468 			duk_bool_t rc;
62469 			duk_tval *tv1;
62470 
62471 			/* curr is data, desc is accessor */
62472 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
62473 				goto fail_not_configurable;
62474 			}
62475 
62476 			DUK_DDD(DUK_DDDPRINT("convert property to accessor property"));
62477 			if (curr.a_idx >= 0) {
62478 				DUK_DDD(DUK_DDDPRINT("property to convert is stored in an array entry, abandon array and re-lookup"));
62479 				duk__abandon_array_part(thr, obj);
62480 				duk_pop_unsafe(thr);  /* remove old value */
62481 				rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
62482 				DUK_UNREF(rc);
62483 				DUK_ASSERT(rc != 0);
62484 				DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
62485 			}
62486 			if (curr.e_idx < 0) {
62487 				DUK_ASSERT(curr.a_idx < 0 && curr.e_idx < 0);
62488 				goto fail_virtual;  /* safeguard for virtual property */
62489 			}
62490 
62491 			DUK_ASSERT(curr.e_idx >= 0);
62492 			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
62493 
62494 			tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
62495 			DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv1);  /* XXX: just decref */
62496 
62497 			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, NULL);
62498 			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, NULL);
62499 			DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(thr->heap, obj, curr.e_idx);
62500 			DUK_HOBJECT_E_SLOT_SET_ACCESSOR(thr->heap, obj, curr.e_idx);
62501 
62502 			DUK_DDD(DUK_DDDPRINT("flags after data->accessor conversion: 0x%02lx",
62503 			                     (unsigned long) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, curr.e_idx)));
62504 			/* Update curr.flags; faster than a re-lookup. */
62505 			curr.flags &= ~DUK_PROPDESC_FLAG_WRITABLE;
62506 			curr.flags |= DUK_PROPDESC_FLAG_ACCESSOR;
62507 		}
62508 	} else if (has_value || has_writable) {
62509 		/* IsDataDescriptor(desc) == true */
62510 		DUK_ASSERT(!has_set);
62511 		DUK_ASSERT(!has_get);
62512 
62513 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
62514 			duk_hobject *tmp;
62515 
62516 			/* curr is accessor, desc is data */
62517 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
62518 				goto fail_not_configurable;
62519 			}
62520 
62521 			/* curr is accessor -> cannot be in array part. */
62522 			DUK_ASSERT(curr.a_idx < 0);
62523 			if (curr.e_idx < 0) {
62524 				goto fail_virtual;  /* safeguard; no virtual accessors now */
62525 			}
62526 
62527 			DUK_DDD(DUK_DDDPRINT("convert property to data property"));
62528 
62529 			DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
62530 			tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, curr.e_idx);
62531 			DUK_UNREF(tmp);
62532 			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, NULL);
62533 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
62534 			tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, curr.e_idx);
62535 			DUK_UNREF(tmp);
62536 			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, NULL);
62537 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
62538 
62539 			DUK_TVAL_SET_UNDEFINED(DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx));
62540 			DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(thr->heap, obj, curr.e_idx);
62541 			DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(thr->heap, obj, curr.e_idx);
62542 
62543 			DUK_DDD(DUK_DDDPRINT("flags after accessor->data conversion: 0x%02lx",
62544 			                     (unsigned long) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, curr.e_idx)));
62545 
62546 			/* Update curr.flags; faster than a re-lookup. */
62547 			curr.flags &= ~(DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ACCESSOR);
62548 		} else {
62549 			/* curr and desc are data */
62550 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
62551 				if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && has_writable && is_writable) {
62552 					goto fail_not_configurable;
62553 				}
62554 				/* Note: changing from writable to non-writable is OK */
62555 				if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && has_value) {
62556 					duk_tval *tmp1 = duk_require_tval(thr, -1);         /* curr value */
62557 					duk_tval *tmp2 = duk_require_tval(thr, idx_value);  /* new value */
62558 					if (!duk_js_samevalue(tmp1, tmp2)) {
62559 						goto fail_not_configurable;
62560 					}
62561 				}
62562 			}
62563 		}
62564 	} else {
62565 		/* IsGenericDescriptor(desc) == true; this means in practice that 'desc'
62566 		 * only has [[Enumerable]] or [[Configurable]] flag updates, which are
62567 		 * allowed at this point.
62568 		 */
62569 
62570 		DUK_ASSERT(!has_value && !has_writable && !has_get && !has_set);
62571 	}
62572 
62573 	/*
62574 	 *  Start doing property attributes updates.  Steps 12-13.
62575 	 *
62576 	 *  Start by computing new attribute flags without writing yet.
62577 	 *  Property type conversion is done above if necessary.
62578 	 */
62579 
62580 	new_flags = curr.flags;
62581 
62582 	if (has_enumerable) {
62583 		if (is_enumerable) {
62584 			new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
62585 		} else {
62586 			new_flags &= ~DUK_PROPDESC_FLAG_ENUMERABLE;
62587 		}
62588 	}
62589 	if (has_configurable) {
62590 		if (is_configurable) {
62591 			new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
62592 		} else {
62593 			new_flags &= ~DUK_PROPDESC_FLAG_CONFIGURABLE;
62594 		}
62595 	}
62596 	if (has_writable) {
62597 		if (is_writable) {
62598 			new_flags |= DUK_PROPDESC_FLAG_WRITABLE;
62599 		} else {
62600 			new_flags &= ~DUK_PROPDESC_FLAG_WRITABLE;
62601 		}
62602 	}
62603 
62604 	/* XXX: write protect after flag? -> any chance of handling it here? */
62605 
62606 	DUK_DDD(DUK_DDDPRINT("new flags that we want to write: 0x%02lx",
62607 	                     (unsigned long) new_flags));
62608 
62609 	/*
62610 	 *  Check whether we need to abandon an array part (if it exists)
62611 	 */
62612 
62613 	if (curr.a_idx >= 0) {
62614 		duk_bool_t rc;
62615 
62616 		DUK_ASSERT(curr.e_idx < 0);
62617 
62618 		if (new_flags == DUK_PROPDESC_FLAGS_WEC) {
62619 			duk_tval *tv1, *tv2;
62620 
62621 			DUK_DDD(DUK_DDDPRINT("array index, new property attributes match array defaults, update in-place"));
62622 
62623 			DUK_ASSERT(curr.flags == DUK_PROPDESC_FLAGS_WEC);  /* must have been, since in array part */
62624 			DUK_ASSERT(!has_set);
62625 			DUK_ASSERT(!has_get);
62626 			DUK_ASSERT(idx_value >= 0);  /* must be: if attributes match and we get here the value must differ (otherwise no change) */
62627 
62628 			tv2 = duk_require_tval(thr, idx_value);
62629 			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, curr.a_idx);
62630 			DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects; may invalidate a_idx */
62631 			goto success_exotics;
62632 		}
62633 
62634 		DUK_DDD(DUK_DDDPRINT("array index, new property attributes do not match array defaults, abandon array and re-lookup"));
62635 		duk__abandon_array_part(thr, obj);
62636 		duk_pop_unsafe(thr);  /* remove old value */
62637 		rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
62638 		DUK_UNREF(rc);
62639 		DUK_ASSERT(rc != 0);
62640 		DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
62641 	}
62642 
62643 	DUK_DDD(DUK_DDDPRINT("updating existing property in entry part"));
62644 
62645 	/* Array case is handled comprehensively above: either in entry
62646 	 * part or a virtual property.
62647 	 */
62648 	DUK_ASSERT(curr.a_idx < 0);
62649 
62650 	DUK_DDD(DUK_DDDPRINT("update existing property attributes"));
62651 	if (curr.e_idx >= 0) {
62652 		DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, curr.e_idx, new_flags);
62653 	} else {
62654 		/* For Array .length the only allowed transition is for .length
62655 		 * to become non-writable.
62656 		 */
62657 		if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
62658 			duk_harray *a;
62659 			a = (duk_harray *) obj;
62660 			DUK_DD(DUK_DDPRINT("Object.defineProperty() attribute update for duk_harray .length -> %02lx", (unsigned long) new_flags));
62661 			DUK_HARRAY_ASSERT_VALID(a);
62662 			if ((new_flags & DUK_PROPDESC_FLAGS_EC) != (curr.flags & DUK_PROPDESC_FLAGS_EC)) {
62663 				DUK_D(DUK_DPRINT("Object.defineProperty() attempt to change virtual array .length enumerable or configurable attribute, fail"));
62664 				goto fail_virtual;
62665 			}
62666 			if (new_flags & DUK_PROPDESC_FLAG_WRITABLE) {
62667 				DUK_HARRAY_SET_LENGTH_WRITABLE(a);
62668 			} else {
62669 				DUK_HARRAY_SET_LENGTH_NONWRITABLE(a);
62670 			}
62671 		}
62672 	}
62673 
62674 	if (has_set) {
62675 		duk_hobject *tmp;
62676 
62677 		/* Virtual properties are non-configurable but with a 'force'
62678 		 * flag we might come here so check explicitly for virtual.
62679 		 */
62680 		if (curr.e_idx < 0) {
62681 			goto fail_virtual;
62682 		}
62683 
62684 		DUK_DDD(DUK_DDDPRINT("update existing property setter"));
62685 		DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
62686 
62687 		tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, curr.e_idx);
62688 		DUK_UNREF(tmp);
62689 		DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, set);
62690 		DUK_HOBJECT_INCREF_ALLOWNULL(thr, set);
62691 		DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);  /* side effects; may invalidate e_idx */
62692 	}
62693 	if (has_get) {
62694 		duk_hobject *tmp;
62695 
62696 		if (curr.e_idx < 0) {
62697 			goto fail_virtual;
62698 		}
62699 
62700 		DUK_DDD(DUK_DDDPRINT("update existing property getter"));
62701 		DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
62702 
62703 		tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, curr.e_idx);
62704 		DUK_UNREF(tmp);
62705 		DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, get);
62706 		DUK_HOBJECT_INCREF_ALLOWNULL(thr, get);
62707 		DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);  /* side effects; may invalidate e_idx */
62708 	}
62709 	if (has_value) {
62710 		duk_tval *tv1, *tv2;
62711 
62712 		DUK_DDD(DUK_DDDPRINT("update existing property value"));
62713 
62714 		if (curr.e_idx >= 0) {
62715 			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
62716 			tv2 = duk_require_tval(thr, idx_value);
62717 			tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
62718 			DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects; may invalidate e_idx */
62719 		} else {
62720 			DUK_ASSERT(curr.a_idx < 0);  /* array part case handled comprehensively previously */
62721 
62722 			DUK_DD(DUK_DDPRINT("Object.defineProperty(), value update for virtual property"));
62723 			/* XXX: Uint8Array and other typed array virtual writes not currently
62724 			 * handled.
62725 			 */
62726 			if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
62727 				duk_harray *a;
62728 				a = (duk_harray *) obj;
62729 				DUK_DD(DUK_DDPRINT("Object.defineProperty() value update for duk_harray .length -> %ld", (long) arrlen_new_len));
62730 				DUK_HARRAY_ASSERT_VALID(a);
62731 				a->length = arrlen_new_len;
62732 			} else {
62733 				goto fail_virtual;  /* should not happen */
62734 			}
62735 		}
62736 	}
62737 
62738 	/*
62739 	 *  Standard algorithm succeeded without errors, check for exotic post-behaviors.
62740 	 *
62741 	 *  Arguments exotic behavior in E5 Section 10.6 occurs after the standard
62742 	 *  [[DefineOwnProperty]] has completed successfully.
62743 	 *
62744 	 *  Array exotic behavior in E5 Section 15.4.5.1 is implemented partly
62745 	 *  prior to the default [[DefineOwnProperty]], but:
62746 	 *    - for an array index key (e.g. "10") the final 'length' update occurs here
62747 	 *    - for 'length' key the element deletion and 'length' update occurs here
62748 	 */
62749 
62750  success_exotics:
62751 
62752 	/* curr.a_idx or curr.e_idx may have been invalidated by side effects
62753 	 * above.
62754 	 */
62755 
62756 	/* [obj key desc value get set curr_value] */
62757 
62758 	if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
62759 		duk_harray *a;
62760 
62761 		a = (duk_harray *) obj;
62762 		DUK_HARRAY_ASSERT_VALID(a);
62763 
62764 		if (arridx_new_array_length > 0) {
62765 			/*
62766 			 *  Note: zero works as a "no update" marker because the new length
62767 			 *  can never be zero after a new property is written.
62768 			 */
62769 
62770 			/* E5 Section 15.4.5.1, steps 4.e.i - 4.e.ii */
62771 
62772 			DUK_DDD(DUK_DDDPRINT("defineProperty successful, pending array length update to: %ld",
62773 			                     (long) arridx_new_array_length));
62774 
62775 			a->length = arridx_new_array_length;
62776 		}
62777 
62778 		if (key == DUK_HTHREAD_STRING_LENGTH(thr) && arrlen_new_len < arrlen_old_len) {
62779 			/*
62780 			 *  E5 Section 15.4.5.1, steps 3.k - 3.n.  The order at the end combines
62781 			 *  the error case 3.l.iii and the success case 3.m-3.n.
62782 			 */
62783 
62784 			/* XXX: investigate whether write protect can be handled above, if we
62785 			 * just update length here while ignoring its protected status
62786 			 */
62787 
62788 			duk_uint32_t result_len;
62789 			duk_bool_t rc;
62790 
62791 			DUK_DDD(DUK_DDDPRINT("defineProperty successful, key is 'length', exotic array behavior, "
62792 			                     "doing array element deletion and length update"));
62793 
62794 			rc = duk__handle_put_array_length_smaller(thr, obj, arrlen_old_len, arrlen_new_len, force_flag, &result_len);
62795 
62796 			/* update length (curr points to length, and we assume it's still valid) */
62797 			DUK_ASSERT(result_len >= arrlen_new_len && result_len <= arrlen_old_len);
62798 
62799 			a->length = result_len;
62800 
62801 			if (pending_write_protect) {
62802 				DUK_DDD(DUK_DDDPRINT("setting array length non-writable (pending writability update)"));
62803 				DUK_HARRAY_SET_LENGTH_NONWRITABLE(a);
62804 			}
62805 
62806 			/* XXX: shrink array allocation or entries compaction here? */
62807 			if (!rc) {
62808 				DUK_DD(DUK_DDPRINT("array length write only partially successful"));
62809 				goto fail_not_configurable;
62810 			}
62811 		}
62812 	} else if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj)) {
62813 		duk_hobject *map;
62814 		duk_hobject *varenv;
62815 
62816 		DUK_ASSERT(arridx_new_array_length == 0);
62817 		DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj));  /* traits are separate; in particular, arguments not an array */
62818 
62819 		map = NULL;
62820 		varenv = NULL;
62821 		if (!duk__lookup_arguments_map(thr, obj, key, &curr, &map, &varenv)) {
62822 			goto success_no_exotics;
62823 		}
62824 		DUK_ASSERT(map != NULL);
62825 		DUK_ASSERT(varenv != NULL);
62826 
62827 		/* [obj key desc value get set curr_value varname] */
62828 
62829 		if (has_set || has_get) {
62830 			/* = IsAccessorDescriptor(Desc) */
62831 			DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map' "
62832 			                     "changed to an accessor, delete arguments binding"));
62833 
62834 			(void) duk_hobject_delprop_raw(thr, map, key, 0);  /* ignore result */
62835 		} else {
62836 			/* Note: this order matters (final value before deleting map entry must be done) */
62837 			DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
62838 			                     "check for value update / binding deletion"));
62839 
62840 			if (has_value) {
62841 				duk_hstring *varname;
62842 
62843 				DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
62844 				                     "update bound value (variable/argument)"));
62845 
62846 				varname = duk_require_hstring(thr, -1);
62847 				DUK_ASSERT(varname != NULL);
62848 
62849 				DUK_DDD(DUK_DDDPRINT("arguments object automatic putvar for a bound variable; "
62850 				                     "key=%!O, varname=%!O, value=%!T",
62851 				                     (duk_heaphdr *) key,
62852 				                     (duk_heaphdr *) varname,
62853 				                     (duk_tval *) duk_require_tval(thr, idx_value)));
62854 
62855 				/* strict flag for putvar comes from our caller (currently: fixed) */
62856 				duk_js_putvar_envrec(thr, varenv, varname, duk_require_tval(thr, idx_value), 1 /*throw_flag*/);
62857 			}
62858 			if (has_writable && !is_writable) {
62859 				DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
62860 				                     "changed to non-writable, delete arguments binding"));
62861 
62862 				(void) duk_hobject_delprop_raw(thr, map, key, 0);  /* ignore result */
62863 			}
62864 		}
62865 
62866 		/* 'varname' is in stack in this else branch, leaving an unbalanced stack below,
62867 		 * but this doesn't matter now.
62868 		 */
62869 	}
62870 
62871  success_no_exotics:
62872 	/* Some code paths use NORZ macros for simplicity, ensure refzero
62873 	 * handling is completed.
62874 	 */
62875 	DUK_REFZERO_CHECK_SLOW(thr);
62876 	return 1;
62877 
62878  fail_not_extensible:
62879 	if (throw_flag) {
62880 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_EXTENSIBLE);
62881 		DUK_WO_NORETURN(return 0;);
62882 	}
62883 	return 0;
62884 
62885  fail_virtual:  /* just use the same "not configurable" error message" */
62886  fail_not_configurable:
62887 	if (throw_flag) {
62888 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
62889 		DUK_WO_NORETURN(return 0;);
62890 	}
62891 	return 0;
62892 }
62893 
62894 /*
62895  *  Object.prototype.hasOwnProperty() and Object.prototype.propertyIsEnumerable().
62896  */
62897 
62898 DUK_INTERNAL duk_bool_t duk_hobject_object_ownprop_helper(duk_hthread *thr, duk_small_uint_t required_desc_flags) {
62899 	duk_hstring *h_v;
62900 	duk_hobject *h_obj;
62901 	duk_propdesc desc;
62902 	duk_bool_t ret;
62903 
62904 	/* coercion order matters */
62905 	h_v = duk_to_hstring_acceptsymbol(thr, 0);
62906 	DUK_ASSERT(h_v != NULL);
62907 
62908 	h_obj = duk_push_this_coercible_to_object(thr);
62909 	DUK_ASSERT(h_obj != NULL);
62910 
62911 	ret = duk_hobject_get_own_propdesc(thr, h_obj, h_v, &desc, 0 /*flags*/);  /* don't push value */
62912 
62913 	duk_push_boolean(thr, ret && ((desc.flags & required_desc_flags) == required_desc_flags));
62914 	return 1;
62915 }
62916 
62917 /*
62918  *  Object.seal() and Object.freeze()  (E5 Sections 15.2.3.8 and 15.2.3.9)
62919  *
62920  *  Since the algorithms are similar, a helper provides both functions.
62921  *  Freezing is essentially sealing + making plain properties non-writable.
62922  *
62923  *  Note: virtual (non-concrete) properties which are non-configurable but
62924  *  writable would pose some problems, but such properties do not currently
62925  *  exist (all virtual properties are non-configurable and non-writable).
62926  *  If they did exist, the non-configurability does NOT prevent them from
62927  *  becoming non-writable.  However, this change should be recorded somehow
62928  *  so that it would turn up (e.g. when getting the property descriptor),
62929  *  requiring some additional flags in the object.
62930  */
62931 
62932 DUK_INTERNAL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_freeze) {
62933 	duk_uint_fast32_t i;
62934 
62935 	DUK_ASSERT(thr != NULL);
62936 	DUK_ASSERT(thr->heap != NULL);
62937 	DUK_ASSERT(obj != NULL);
62938 
62939 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
62940 
62941 #if defined(DUK_USE_ROM_OBJECTS)
62942 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
62943 		DUK_DD(DUK_DDPRINT("attempt to seal/freeze a readonly object, reject"));
62944 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
62945 		DUK_WO_NORETURN(return;);
62946 	}
62947 #endif
62948 
62949 	/*
62950 	 *  Abandon array part because all properties must become non-configurable.
62951 	 *  Note that this is now done regardless of whether this is always the case
62952 	 *  (skips check, but performance problem if caller would do this many times
62953 	 *  for the same object; not likely).
62954 	 */
62955 
62956 	duk__abandon_array_part(thr, obj);
62957 	DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(obj) == 0);
62958 
62959 	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
62960 		duk_uint8_t *fp;
62961 
62962 		/* since duk__abandon_array_part() causes a resize, there should be no gaps in keys */
62963 		DUK_ASSERT(DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i) != NULL);
62964 
62965 		/* avoid multiple computations of flags address; bypasses macros */
62966 		fp = DUK_HOBJECT_E_GET_FLAGS_PTR(thr->heap, obj, i);
62967 		if (is_freeze && !((*fp) & DUK_PROPDESC_FLAG_ACCESSOR)) {
62968 			*fp &= ~(DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_CONFIGURABLE);
62969 		} else {
62970 			*fp &= ~DUK_PROPDESC_FLAG_CONFIGURABLE;
62971 		}
62972 	}
62973 
62974 	DUK_HOBJECT_CLEAR_EXTENSIBLE(obj);
62975 
62976 	/* no need to compact since we already did that in duk__abandon_array_part()
62977 	 * (regardless of whether an array part existed or not.
62978 	 */
62979 
62980 	return;
62981 }
62982 
62983 /*
62984  *  Object.isSealed() and Object.isFrozen()  (E5 Sections 15.2.3.11, 15.2.3.13)
62985  *
62986  *  Since the algorithms are similar, a helper provides both functions.
62987  *  Freezing is essentially sealing + making plain properties non-writable.
62988  *
62989  *  Note: all virtual (non-concrete) properties are currently non-configurable
62990  *  and non-writable (and there are no accessor virtual properties), so they don't
62991  *  need to be considered here now.
62992  */
62993 
62994 DUK_INTERNAL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_frozen) {
62995 	duk_uint_fast32_t i;
62996 
62997 	DUK_ASSERT(obj != NULL);
62998 	DUK_UNREF(thr);
62999 
63000 	/* Note: no allocation pressure, no need to check refcounts etc */
63001 
63002 	/* must not be extensible */
63003 	if (DUK_HOBJECT_HAS_EXTENSIBLE(obj)) {
63004 		return 0;
63005 	}
63006 
63007 	/* all virtual properties are non-configurable and non-writable */
63008 
63009 	/* entry part must not contain any configurable properties, or
63010 	 * writable properties (if is_frozen).
63011 	 */
63012 	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
63013 		duk_small_uint_t flags;
63014 
63015 		if (!DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i)) {
63016 			continue;
63017 		}
63018 
63019 		/* avoid multiple computations of flags address; bypasses macros */
63020 		flags = (duk_small_uint_t) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, i);
63021 
63022 		if (flags & DUK_PROPDESC_FLAG_CONFIGURABLE) {
63023 			return 0;
63024 		}
63025 		if (is_frozen &&
63026 		    !(flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
63027 		    (flags & DUK_PROPDESC_FLAG_WRITABLE)) {
63028 			return 0;
63029 		}
63030 	}
63031 
63032 	/* array part must not contain any non-unused properties, as they would
63033 	 * be configurable and writable.
63034 	 */
63035 	for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
63036 		duk_tval *tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
63037 		if (!DUK_TVAL_IS_UNUSED(tv)) {
63038 			return 0;
63039 		}
63040 	}
63041 
63042 	return 1;
63043 }
63044 
63045 /*
63046  *  Object.preventExtensions() and Object.isExtensible()  (E5 Sections 15.2.3.10, 15.2.3.13)
63047  *
63048  *  Not needed, implemented by macros DUK_HOBJECT_{HAS,CLEAR,SET}_EXTENSIBLE
63049  *  and the Object built-in bindings.
63050  */
63051 
63052 /* automatic undefs */
63053 #undef DUK__HASH_DELETED
63054 #undef DUK__HASH_UNUSED
63055 #undef DUK__NO_ARRAY_INDEX
63056 #undef DUK__VALSTACK_PROXY_LOOKUP
63057 #undef DUK__VALSTACK_SPACE
63058 /*
63059  *  duk_hstring assertion helpers.
63060  */
63061 
63062 /* #include duk_internal.h -> already included */
63063 
63064 #if defined(DUK_USE_ASSERTIONS)
63065 
63066 DUK_INTERNAL void duk_hstring_assert_valid(duk_hstring *h) {
63067 	DUK_ASSERT(h != NULL);
63068 }
63069 
63070 #endif  /* DUK_USE_ASSERTIONS */
63071 /*
63072  *  Misc support functions
63073  */
63074 
63075 /* #include duk_internal.h -> already included */
63076 
63077 /*
63078  *  duk_hstring charCodeAt, with and without surrogate awareness
63079  */
63080 
63081 DUK_INTERNAL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h, duk_uint_t pos, duk_bool_t surrogate_aware) {
63082 	duk_uint32_t boff;
63083 	const duk_uint8_t *p, *p_start, *p_end;
63084 	duk_ucodepoint_t cp1;
63085 	duk_ucodepoint_t cp2;
63086 
63087 	/* Caller must check character offset to be inside the string. */
63088 	DUK_ASSERT(thr != NULL);
63089 	DUK_ASSERT(h != NULL);
63090 	DUK_ASSERT_DISABLE(pos >= 0);  /* unsigned */
63091 	DUK_ASSERT(pos < (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h));
63092 
63093 	boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint32_t) pos);
63094 	DUK_DDD(DUK_DDDPRINT("charCodeAt: pos=%ld -> boff=%ld, str=%!O",
63095 	                     (long) pos, (long) boff, (duk_heaphdr *) h));
63096 	DUK_ASSERT_DISABLE(boff >= 0);
63097 	DUK_ASSERT(boff < DUK_HSTRING_GET_BYTELEN(h));
63098 
63099 	p_start = DUK_HSTRING_GET_DATA(h);
63100 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h);
63101 	p = p_start + boff;
63102 	DUK_DDD(DUK_DDDPRINT("p_start=%p, p_end=%p, p=%p",
63103 	                     (const void *) p_start, (const void *) p_end,
63104 	                     (const void *) p));
63105 
63106 	/* For invalid UTF-8 (never happens for standard ECMAScript strings)
63107 	 * return U+FFFD replacement character.
63108 	 */
63109 	if (duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp1)) {
63110 		if (surrogate_aware && cp1 >= 0xd800UL && cp1 <= 0xdbffUL) {
63111 			/* The decode helper is memory safe even if 'cp1' was
63112 			 * decoded at the end of the string and 'p' is no longer
63113 			 * within string memory range.
63114 			 */
63115 			cp2 = 0;  /* If call fails, this is left untouched and won't match cp2 check. */
63116 			(void) duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp2);
63117 			if (cp2 >= 0xdc00UL && cp2 <= 0xdfffUL) {
63118 				cp1 = (duk_ucodepoint_t) (((cp1 - 0xd800UL) << 10) + (cp2 - 0xdc00UL) + 0x10000UL);
63119 			}
63120 		}
63121 	} else {
63122 		cp1 = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
63123 	}
63124 
63125 	return cp1;
63126 }
63127 
63128 /*
63129  *  duk_hstring charlen, when lazy charlen disabled
63130  */
63131 
63132 #if !defined(DUK_USE_HSTRING_LAZY_CLEN)
63133 #if !defined(DUK_USE_HSTRING_CLEN)
63134 #error non-lazy duk_hstring charlen but DUK_USE_HSTRING_CLEN not set
63135 #endif
63136 DUK_INTERNAL void duk_hstring_init_charlen(duk_hstring *h) {
63137 	duk_uint32_t clen;
63138 
63139 	DUK_ASSERT(h != NULL);
63140 	DUK_ASSERT(!DUK_HSTRING_HAS_ASCII(h));
63141 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h));
63142 
63143 	clen = duk_unicode_unvalidated_utf8_length(DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
63144 #if defined(DUK_USE_STRLEN16)
63145 	DUK_ASSERT(clen <= 0xffffUL);  /* Bytelength checked during interning. */
63146 	h->clen16 = (duk_uint16_t) clen;
63147 #else
63148 	h->clen = (duk_uint32_t) clen;
63149 #endif
63150 	if (DUK_LIKELY(clen == DUK_HSTRING_GET_BYTELEN(h))) {
63151 		DUK_HSTRING_SET_ASCII(h);
63152 	}
63153 }
63154 
63155 DUK_INTERNAL DUK_HOT duk_size_t duk_hstring_get_charlen(duk_hstring *h) {
63156 #if defined(DUK_USE_STRLEN16)
63157 	return h->clen16;
63158 #else
63159 	return h->clen;
63160 #endif
63161 }
63162 #endif  /* !DUK_USE_HSTRING_LAZY_CLEN */
63163 
63164 /*
63165  *  duk_hstring charlen, when lazy charlen enabled
63166  */
63167 
63168 #if defined(DUK_USE_HSTRING_LAZY_CLEN)
63169 #if defined(DUK_USE_HSTRING_CLEN)
63170 DUK_LOCAL DUK_COLD duk_size_t duk__hstring_get_charlen_slowpath(duk_hstring *h) {
63171 	duk_size_t res;
63172 
63173 	DUK_ASSERT(h->clen == 0);  /* Checked by caller. */
63174 
63175 #if defined(DUK_USE_ROM_STRINGS)
63176 	/* ROM strings have precomputed clen, but if the computed clen is zero
63177 	 * we can still come here and can't write anything.
63178 	 */
63179 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) {
63180 		return 0;
63181 	}
63182 #endif
63183 
63184 	res = duk_unicode_unvalidated_utf8_length(DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
63185 #if defined(DUK_USE_STRLEN16)
63186 	DUK_ASSERT(res <= 0xffffUL);  /* Bytelength checked during interning. */
63187 	h->clen16 = (duk_uint16_t) res;
63188 #else
63189 	h->clen = (duk_uint32_t) res;
63190 #endif
63191 	if (DUK_LIKELY(res == DUK_HSTRING_GET_BYTELEN(h))) {
63192 		DUK_HSTRING_SET_ASCII(h);
63193 	}
63194 	return res;
63195 }
63196 #else  /* DUK_USE_HSTRING_CLEN */
63197 DUK_LOCAL duk_size_t duk__hstring_get_charlen_slowpath(duk_hstring *h) {
63198 	if (DUK_LIKELY(DUK_HSTRING_HAS_ASCII(h))) {
63199 		/* Most practical strings will go here. */
63200 		return DUK_HSTRING_GET_BYTELEN(h);
63201 	} else {
63202 		/* ASCII flag is lazy, so set it here. */
63203 		duk_size_t res;
63204 
63205 		/* XXX: here we could use the strcache to speed up the
63206 		 * computation (matters for 'i < str.length' loops).
63207 		 */
63208 
63209 		res = duk_unicode_unvalidated_utf8_length(DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
63210 
63211 #if defined(DUK_USE_ROM_STRINGS)
63212 		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) {
63213 			/* For ROM strings, can't write anything; ASCII flag
63214 			 * is preset so we don't need to update it.
63215 			 */
63216 			return res;
63217 		}
63218 #endif
63219 		if (DUK_LIKELY(res == DUK_HSTRING_GET_BYTELEN(h))) {
63220 			DUK_HSTRING_SET_ASCII(h);
63221 		}
63222 		return res;
63223 	}
63224 }
63225 #endif  /* DUK_USE_HSTRING_CLEN */
63226 
63227 #if defined(DUK_USE_HSTRING_CLEN)
63228 DUK_INTERNAL DUK_HOT duk_size_t duk_hstring_get_charlen(duk_hstring *h) {
63229 #if defined(DUK_USE_STRLEN16)
63230 	if (DUK_LIKELY(h->clen16 != 0)) {
63231 		return h->clen16;
63232 	}
63233 #else
63234 	if (DUK_LIKELY(h->clen != 0)) {
63235 		return h->clen;
63236 	}
63237 #endif
63238 	return duk__hstring_get_charlen_slowpath(h);
63239 }
63240 #else  /* DUK_USE_HSTRING_CLEN */
63241 DUK_INTERNAL DUK_HOT duk_size_t duk_hstring_get_charlen(duk_hstring *h) {
63242 	/* Always use slow path. */
63243 	return duk__hstring_get_charlen_slowpath(h);
63244 }
63245 #endif  /* DUK_USE_HSTRING_CLEN */
63246 #endif  /* DUK_USE_HSTRING_LAZY_CLEN */
63247 
63248 /*
63249  *  Compare duk_hstring to an ASCII cstring.
63250  */
63251 
63252 DUK_INTERNAL duk_bool_t duk_hstring_equals_ascii_cstring(duk_hstring *h, const char *cstr) {
63253 	duk_size_t len;
63254 
63255 	DUK_ASSERT(h != NULL);
63256 	DUK_ASSERT(cstr != NULL);
63257 
63258 	len = DUK_STRLEN(cstr);
63259 	if (len != DUK_HSTRING_GET_BYTELEN(h)) {
63260 		return 0;
63261 	}
63262 	if (duk_memcmp((const void *) cstr, (const void *) DUK_HSTRING_GET_DATA(h), len) == 0) {
63263 		return 1;
63264 	}
63265 	return 0;
63266 }
63267 /*
63268  *  duk_hthread allocation and freeing.
63269  */
63270 
63271 /* #include duk_internal.h -> already included */
63272 
63273 /*
63274  *  Allocate initial stacks for a thread.  Note that 'thr' must be reachable
63275  *  as a garbage collection may be triggered by the allocation attempts.
63276  *  Returns zero (without leaking memory) if init fails.
63277  */
63278 
63279 DUK_INTERNAL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr) {
63280 	duk_size_t alloc_size;
63281 	duk_size_t i;
63282 
63283 	DUK_ASSERT(heap != NULL);
63284 	DUK_ASSERT(thr != NULL);
63285 	DUK_ASSERT(thr->valstack == NULL);
63286 	DUK_ASSERT(thr->valstack_end == NULL);
63287 	DUK_ASSERT(thr->valstack_alloc_end == NULL);
63288 	DUK_ASSERT(thr->valstack_bottom == NULL);
63289 	DUK_ASSERT(thr->valstack_top == NULL);
63290 	DUK_ASSERT(thr->callstack_curr == NULL);
63291 
63292 	/* valstack */
63293 	DUK_ASSERT(DUK_VALSTACK_API_ENTRY_MINIMUM <= DUK_VALSTACK_INITIAL_SIZE);
63294 	alloc_size = sizeof(duk_tval) * DUK_VALSTACK_INITIAL_SIZE;
63295 	thr->valstack = (duk_tval *) DUK_ALLOC(heap, alloc_size);
63296 	if (!thr->valstack) {
63297 		goto fail;
63298 	}
63299 	duk_memzero(thr->valstack, alloc_size);
63300 	thr->valstack_end = thr->valstack + DUK_VALSTACK_API_ENTRY_MINIMUM;
63301 	thr->valstack_alloc_end = thr->valstack + DUK_VALSTACK_INITIAL_SIZE;
63302 	thr->valstack_bottom = thr->valstack;
63303 	thr->valstack_top = thr->valstack;
63304 
63305 	for (i = 0; i < DUK_VALSTACK_INITIAL_SIZE; i++) {
63306 		DUK_TVAL_SET_UNDEFINED(&thr->valstack[i]);
63307 	}
63308 
63309 	return 1;
63310 
63311  fail:
63312 	DUK_FREE(heap, thr->valstack);
63313 	DUK_ASSERT(thr->callstack_curr == NULL);
63314 
63315 	thr->valstack = NULL;
63316 	return 0;
63317 }
63318 
63319 /* For indirect allocs. */
63320 
63321 DUK_INTERNAL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud) {
63322 	duk_hthread *thr = (duk_hthread *) ud;
63323 	DUK_UNREF(heap);
63324 	return (void *) thr->valstack;
63325 }
63326 /*
63327  *  Initialize built-in objects.  Current thread must have a valstack
63328  *  and initialization errors may longjmp, so a setjmp() catch point
63329  *  must exist.
63330  */
63331 
63332 /* #include duk_internal.h -> already included */
63333 
63334 /*
63335  *  Encoding constants, must match genbuiltins.py
63336  */
63337 
63338 #define DUK__PROP_FLAGS_BITS             3
63339 #define DUK__LENGTH_PROP_BITS            3
63340 #define DUK__NARGS_BITS                  3
63341 #define DUK__PROP_TYPE_BITS              3
63342 
63343 #define DUK__NARGS_VARARGS_MARKER        0x07
63344 
63345 #define DUK__PROP_TYPE_DOUBLE            0
63346 #define DUK__PROP_TYPE_STRING            1
63347 #define DUK__PROP_TYPE_STRIDX            2
63348 #define DUK__PROP_TYPE_BUILTIN           3
63349 #define DUK__PROP_TYPE_UNDEFINED         4
63350 #define DUK__PROP_TYPE_BOOLEAN_TRUE      5
63351 #define DUK__PROP_TYPE_BOOLEAN_FALSE     6
63352 #define DUK__PROP_TYPE_ACCESSOR          7
63353 
63354 /*
63355  *  Create built-in objects by parsing an init bitstream generated
63356  *  by genbuiltins.py.
63357  */
63358 
63359 #if defined(DUK_USE_ROM_OBJECTS)
63360 #if defined(DUK_USE_ROM_GLOBAL_CLONE) || defined(DUK_USE_ROM_GLOBAL_INHERIT)
63361 DUK_LOCAL void duk__duplicate_ram_global_object(duk_hthread *thr) {
63362 	duk_hobject *h_global;
63363 #if defined(DUK_USE_ROM_GLOBAL_CLONE)
63364 	duk_hobject *h_oldglobal;
63365 	duk_uint8_t *props;
63366 	duk_size_t alloc_size;
63367 #endif
63368 	duk_hobject *h_objenv;
63369 
63370 	/* XXX: refactor into internal helper, duk_clone_hobject() */
63371 
63372 #if defined(DUK_USE_ROM_GLOBAL_INHERIT)
63373 	/* Inherit from ROM-based global object: less RAM usage, less transparent. */
63374 	h_global = duk_push_object_helper(thr,
63375 	                                  DUK_HOBJECT_FLAG_EXTENSIBLE |
63376 	                                  DUK_HOBJECT_FLAG_FASTREFS |
63377 	                                  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_GLOBAL),
63378 	                                  DUK_BIDX_GLOBAL);
63379 	DUK_ASSERT(h_global != NULL);
63380 #elif defined(DUK_USE_ROM_GLOBAL_CLONE)
63381 	/* Clone the properties of the ROM-based global object to create a
63382 	 * fully RAM-based global object.  Uses more memory than the inherit
63383 	 * model but more compliant.
63384 	 */
63385 	h_global = duk_push_object_helper(thr,
63386 	                                  DUK_HOBJECT_FLAG_EXTENSIBLE |
63387 	                                  DUK_HOBJECT_FLAG_FASTREFS |
63388 	                                  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_GLOBAL),
63389 	                                  DUK_BIDX_OBJECT_PROTOTYPE);
63390 	DUK_ASSERT(h_global != NULL);
63391 	h_oldglobal = thr->builtins[DUK_BIDX_GLOBAL];
63392 	DUK_ASSERT(h_oldglobal != NULL);
63393 
63394 	/* Copy the property table verbatim; this handles attributes etc.
63395 	 * For ROM objects it's not necessary (or possible) to update
63396 	 * refcounts so leave them as is.
63397 	 */
63398 	alloc_size = DUK_HOBJECT_P_ALLOC_SIZE(h_oldglobal);
63399 	DUK_ASSERT(alloc_size > 0);
63400 	props = DUK_ALLOC_CHECKED(thr, alloc_size);
63401 	DUK_ASSERT(props != NULL);
63402 	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, h_oldglobal) != NULL);
63403 	duk_memcpy((void *) props, (const void *) DUK_HOBJECT_GET_PROPS(thr->heap, h_oldglobal), alloc_size);
63404 
63405 	/* XXX: keep property attributes or tweak them here?
63406 	 * Properties will now be non-configurable even when they're
63407 	 * normally configurable for the global object.
63408 	 */
63409 
63410 	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, h_global) == NULL);
63411 	DUK_HOBJECT_SET_PROPS(thr->heap, h_global, props);
63412 	DUK_HOBJECT_SET_ESIZE(h_global, DUK_HOBJECT_GET_ESIZE(h_oldglobal));
63413 	DUK_HOBJECT_SET_ENEXT(h_global, DUK_HOBJECT_GET_ENEXT(h_oldglobal));
63414 	DUK_HOBJECT_SET_ASIZE(h_global, DUK_HOBJECT_GET_ASIZE(h_oldglobal));
63415 	DUK_HOBJECT_SET_HSIZE(h_global, DUK_HOBJECT_GET_HSIZE(h_oldglobal));
63416 #else
63417 #error internal error in config defines
63418 #endif
63419 
63420 	duk_hobject_compact_props(thr, h_global);
63421 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
63422 	DUK_ASSERT(!DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE((duk_heaphdr *) thr->builtins[DUK_BIDX_GLOBAL]));  /* no need to decref: ROM object */
63423 	thr->builtins[DUK_BIDX_GLOBAL] = h_global;
63424 	DUK_HOBJECT_INCREF(thr, h_global);
63425 	DUK_D(DUK_DPRINT("duplicated global object: %!O", h_global));
63426 
63427 	/* Create a fresh object environment for the global scope.  This is
63428 	 * needed so that the global scope points to the newly created RAM-based
63429 	 * global object.
63430 	 */
63431 	h_objenv = (duk_hobject *) duk_hobjenv_alloc(thr,
63432 	                                             DUK_HOBJECT_FLAG_EXTENSIBLE |
63433 	                                             DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
63434 	DUK_ASSERT(h_objenv != NULL);
63435 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_objenv) == NULL);
63436 	duk_push_hobject(thr, h_objenv);
63437 
63438 	DUK_ASSERT(h_global != NULL);
63439 	((duk_hobjenv *) h_objenv)->target = h_global;
63440 	DUK_HOBJECT_INCREF(thr, h_global);
63441 	DUK_ASSERT(((duk_hobjenv *) h_objenv)->has_this == 0);
63442 
63443 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL_ENV] != NULL);
63444 	DUK_ASSERT(!DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE((duk_heaphdr *) thr->builtins[DUK_BIDX_GLOBAL_ENV]));  /* no need to decref: ROM object */
63445 	thr->builtins[DUK_BIDX_GLOBAL_ENV] = h_objenv;
63446 	DUK_HOBJECT_INCREF(thr, h_objenv);
63447 	DUK_D(DUK_DPRINT("duplicated global env: %!O", h_objenv));
63448 
63449 	DUK_HOBJENV_ASSERT_VALID((duk_hobjenv *) h_objenv);
63450 
63451 	duk_pop_2(thr);  /* Pop global object and global env. */
63452 }
63453 #endif  /* DUK_USE_ROM_GLOBAL_CLONE || DUK_USE_ROM_GLOBAL_INHERIT */
63454 
63455 DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
63456 	/* Setup builtins from ROM objects.  All heaps/threads will share
63457 	 * the same readonly objects.
63458 	 */
63459 	duk_small_uint_t i;
63460 
63461 	for (i = 0; i < DUK_NUM_BUILTINS; i++) {
63462 		duk_hobject *h;
63463 		h = (duk_hobject *) DUK_LOSE_CONST(duk_rom_builtins_bidx[i]);
63464 		DUK_ASSERT(h != NULL);
63465 		thr->builtins[i] = h;
63466 	}
63467 
63468 #if defined(DUK_USE_ROM_GLOBAL_CLONE) || defined(DUK_USE_ROM_GLOBAL_INHERIT)
63469 	/* By default the global object is read-only which is often much
63470 	 * more of an issue than having read-only built-in objects (like
63471 	 * RegExp, Date, etc).  Use a RAM-based copy of the global object
63472 	 * and the global environment object for convenience.
63473 	 */
63474 	duk__duplicate_ram_global_object(thr);
63475 #endif
63476 }
63477 #else  /* DUK_USE_ROM_OBJECTS */
63478 DUK_LOCAL void duk__push_stridx(duk_hthread *thr, duk_bitdecoder_ctx *bd) {
63479 	duk_small_uint_t n;
63480 
63481 	n = (duk_small_uint_t) duk_bd_decode_varuint(bd);
63482 	DUK_ASSERT_DISABLE(n >= 0);  /* unsigned */
63483 	DUK_ASSERT(n < DUK_HEAP_NUM_STRINGS);
63484 	duk_push_hstring_stridx(thr, n);
63485 }
63486 DUK_LOCAL void duk__push_string(duk_hthread *thr, duk_bitdecoder_ctx *bd) {
63487 	/* XXX: built-ins data could provide a maximum length that is
63488 	 * actually needed; bitpacked max length is now 256 bytes.
63489 	 */
63490 	duk_uint8_t tmp[DUK_BD_BITPACKED_STRING_MAXLEN];
63491 	duk_small_uint_t len;
63492 
63493 	len = duk_bd_decode_bitpacked_string(bd, tmp);
63494 	duk_push_lstring(thr, (const char *) tmp, (duk_size_t) len);
63495 }
63496 DUK_LOCAL void duk__push_stridx_or_string(duk_hthread *thr, duk_bitdecoder_ctx *bd) {
63497 	duk_small_uint_t n;
63498 
63499 	n = (duk_small_uint_t) duk_bd_decode_varuint(bd);
63500 	if (n == 0) {
63501 		duk__push_string(thr, bd);
63502 	} else {
63503 		n--;
63504 		DUK_ASSERT(n < DUK_HEAP_NUM_STRINGS);
63505 		duk_push_hstring_stridx(thr, n);
63506 	}
63507 }
63508 DUK_LOCAL void duk__push_double(duk_hthread *thr, duk_bitdecoder_ctx *bd) {
63509 	duk_double_union du;
63510 	duk_small_uint_t i;
63511 
63512 	for (i = 0; i < 8; i++) {
63513 		/* Encoding endianness must match target memory layout,
63514 		 * build scripts and genbuiltins.py must ensure this.
63515 		 */
63516 		du.uc[i] = (duk_uint8_t) duk_bd_decode(bd, 8);
63517 	}
63518 
63519 	duk_push_number(thr, du.d);  /* push operation normalizes NaNs */
63520 }
63521 
63522 DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
63523 	duk_bitdecoder_ctx bd_ctx;
63524 	duk_bitdecoder_ctx *bd = &bd_ctx;  /* convenience */
63525 	duk_hobject *h;
63526 	duk_small_uint_t i, j;
63527 
63528 	DUK_D(DUK_DPRINT("INITBUILTINS BEGIN: DUK_NUM_BUILTINS=%d, DUK_NUM_BUILTINS_ALL=%d", (int) DUK_NUM_BUILTINS, (int) DUK_NUM_ALL_BUILTINS));
63529 
63530 	duk_memzero(&bd_ctx, sizeof(bd_ctx));
63531 	bd->data = (const duk_uint8_t *) duk_builtins_data;
63532 	bd->length = (duk_size_t) DUK_BUILTINS_DATA_LENGTH;
63533 
63534 	/*
63535 	 *  First create all built-in bare objects on the empty valstack.
63536 	 *
63537 	 *  Built-ins in the index range [0,DUK_NUM_BUILTINS-1] have value
63538 	 *  stack indices matching their eventual thr->builtins[] index.
63539 	 *
63540 	 *  Built-ins in the index range [DUK_NUM_BUILTINS,DUK_NUM_ALL_BUILTINS]
63541 	 *  will exist on the value stack during init but won't be placed
63542 	 *  into thr->builtins[].  These are objects referenced in some way
63543 	 *  from thr->builtins[] roots but which don't need to be indexed by
63544 	 *  Duktape through thr->builtins[] (e.g. user custom objects).
63545 	 *
63546 	 *  Internal prototypes will be incorrect (NULL) at this stage.
63547 	 */
63548 
63549 	duk_require_stack(thr, DUK_NUM_ALL_BUILTINS);
63550 
63551 	DUK_DD(DUK_DDPRINT("create empty built-ins"));
63552 	DUK_ASSERT_TOP(thr, 0);
63553 	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
63554 		duk_small_uint_t class_num;
63555 		duk_small_int_t len = -1;  /* must be signed */
63556 
63557 		class_num = (duk_small_uint_t) duk_bd_decode_varuint(bd);
63558 		len = (duk_small_int_t) duk_bd_decode_flagged_signed(bd, DUK__LENGTH_PROP_BITS, (duk_int32_t) -1 /*def_value*/);
63559 
63560 		if (class_num == DUK_HOBJECT_CLASS_FUNCTION) {
63561 			duk_small_uint_t natidx;
63562 			duk_small_int_t c_nargs;  /* must hold DUK_VARARGS */
63563 			duk_c_function c_func;
63564 			duk_int16_t magic;
63565 
63566 			DUK_DDD(DUK_DDDPRINT("len=%ld", (long) len));
63567 			DUK_ASSERT(len >= 0);
63568 
63569 			natidx = (duk_small_uint_t) duk_bd_decode_varuint(bd);
63570 			DUK_ASSERT(natidx != 0);
63571 			c_func = duk_bi_native_functions[natidx];
63572 			DUK_ASSERT(c_func != NULL);
63573 
63574 			c_nargs = (duk_small_int_t) duk_bd_decode_flagged_signed(bd, DUK__NARGS_BITS, len /*def_value*/);
63575 			if (c_nargs == DUK__NARGS_VARARGS_MARKER) {
63576 				c_nargs = DUK_VARARGS;
63577 			}
63578 
63579 			/* XXX: set magic directly here? (it could share the c_nargs arg) */
63580 			(void) duk_push_c_function_builtin(thr, c_func, c_nargs);
63581 			h = duk_known_hobject(thr, -1);
63582 
63583 			/* Currently all built-in native functions are strict.
63584 			 * duk_push_c_function() now sets strict flag, so
63585 			 * assert for it.
63586 			 */
63587 			DUK_ASSERT(DUK_HOBJECT_HAS_STRICT(h));
63588 
63589 			/* XXX: function properties */
63590 
63591 			duk__push_stridx_or_string(thr, bd);
63592 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
63593 			duk_xdef_prop_stridx_short(thr,
63594 			                           -2,
63595 			                           DUK_STRIDX_NAME,
63596 			                           DUK_PROPDESC_FLAGS_C);
63597 #else
63598 			duk_pop(thr);  /* Not very ideal but good enough for now. */
63599 #endif
63600 
63601 			/* Almost all global level Function objects are constructable
63602 			 * but not all: Function.prototype is a non-constructable,
63603 			 * callable Function.
63604 			 */
63605 			if (duk_bd_decode_flag(bd)) {
63606 				DUK_ASSERT(DUK_HOBJECT_HAS_CONSTRUCTABLE(h));
63607 			} else {
63608 				DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h);
63609 			}
63610 
63611 			/* Cast converts magic to 16-bit signed value */
63612 			magic = (duk_int16_t) duk_bd_decode_varuint(bd);
63613 			((duk_hnatfunc *) h)->magic = magic;
63614 		} else if (class_num == DUK_HOBJECT_CLASS_ARRAY) {
63615 			duk_push_array(thr);
63616 		} else if (class_num == DUK_HOBJECT_CLASS_OBJENV) {
63617 			duk_hobjenv *env;
63618 			duk_hobject *global;
63619 
63620 			DUK_ASSERT(i == DUK_BIDX_GLOBAL_ENV);
63621 			DUK_ASSERT(DUK_BIDX_GLOBAL_ENV > DUK_BIDX_GLOBAL);
63622 
63623 			env = duk_hobjenv_alloc(thr,
63624 	                                        DUK_HOBJECT_FLAG_EXTENSIBLE |
63625 	                                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
63626 			DUK_ASSERT(env->target == NULL);
63627 			duk_push_hobject(thr, (duk_hobject *) env);
63628 
63629 			global = duk_known_hobject(thr, DUK_BIDX_GLOBAL);
63630 			DUK_ASSERT(global != NULL);
63631 			env->target = global;
63632 			DUK_HOBJECT_INCREF(thr, global);
63633 			DUK_ASSERT(env->has_this == 0);
63634 
63635 			DUK_HOBJENV_ASSERT_VALID(env);
63636 		} else {
63637 			DUK_ASSERT(class_num != DUK_HOBJECT_CLASS_DECENV);
63638 
63639 			(void) duk_push_object_helper(thr,
63640 			                              DUK_HOBJECT_FLAG_FASTREFS |
63641 			                              DUK_HOBJECT_FLAG_EXTENSIBLE,
63642 			                              -1);  /* no prototype or class yet */
63643 
63644 		}
63645 
63646 		h = duk_known_hobject(thr, -1);
63647 		DUK_HOBJECT_SET_CLASS_NUMBER(h, class_num);
63648 
63649 		if (i < DUK_NUM_BUILTINS) {
63650 			thr->builtins[i] = h;
63651 			DUK_HOBJECT_INCREF(thr, &h->hdr);
63652 		}
63653 
63654 		if (len >= 0) {
63655 			/* In ES2015+ built-in function object .length property
63656 			 * has property attributes C (configurable only):
63657 			 * http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-standard-built-in-objects
63658 			 *
63659 			 * Array.prototype remains an Array instance in ES2015+
63660 			 * and its length has attributes W (writable only).
63661 			 * Because .length is now virtual for duk_harray, it is
63662 			 * not encoded explicitly in init data.
63663 			 */
63664 
63665 			DUK_ASSERT(class_num != DUK_HOBJECT_CLASS_ARRAY);  /* .length is virtual */
63666 			duk_push_int(thr, len);
63667 			duk_xdef_prop_stridx_short(thr,
63668 			                           -2,
63669 			                           DUK_STRIDX_LENGTH,
63670 			                           DUK_PROPDESC_FLAGS_C);
63671 		}
63672 
63673 		/* enable exotic behaviors last */
63674 
63675 		if (class_num == DUK_HOBJECT_CLASS_ARRAY) {
63676 			DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(h));  /* set by duk_push_array() */
63677 		}
63678 		if (class_num == DUK_HOBJECT_CLASS_STRING) {
63679 			DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h);
63680 		}
63681 
63682 		/* some assertions */
63683 
63684 		DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h));
63685 		/* DUK_HOBJECT_FLAG_CONSTRUCTABLE varies */
63686 		DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(h));
63687 		DUK_ASSERT(!DUK_HOBJECT_HAS_COMPFUNC(h));
63688 		/* DUK_HOBJECT_FLAG_NATFUNC varies */
63689 		DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(h));
63690 		DUK_ASSERT(!DUK_HOBJECT_IS_PROXY(h));
63691 		DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(h) || class_num == DUK_HOBJECT_CLASS_ARRAY);
63692 		/* DUK_HOBJECT_FLAG_STRICT varies */
63693 		DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(h) ||  /* all native functions have NEWENV */
63694 		           DUK_HOBJECT_HAS_NEWENV(h));
63695 		DUK_ASSERT(!DUK_HOBJECT_HAS_NAMEBINDING(h));
63696 		DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(h));
63697 		/* DUK_HOBJECT_FLAG_EXOTIC_ARRAY varies */
63698 		/* DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ varies */
63699 		DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h));
63700 
63701 		DUK_DDD(DUK_DDDPRINT("created built-in %ld, class=%ld, length=%ld", (long) i, (long) class_num, (long) len));
63702 	}
63703 
63704 	/*
63705 	 *  Then decode the builtins init data (see genbuiltins.py) to
63706 	 *  init objects.  Internal prototypes are set at this stage,
63707 	 *  with thr->builtins[] populated.
63708 	 */
63709 
63710 	DUK_DD(DUK_DDPRINT("initialize built-in object properties"));
63711 	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
63712 		duk_small_uint_t t;
63713 		duk_small_uint_t num;
63714 
63715 		DUK_DDD(DUK_DDDPRINT("initializing built-in object at index %ld", (long) i));
63716 		h = duk_known_hobject(thr, (duk_idx_t) i);
63717 
63718 		t = (duk_small_uint_t) duk_bd_decode_varuint(bd);
63719 		if (t > 0) {
63720 			t--;
63721 			DUK_DDD(DUK_DDDPRINT("set internal prototype: built-in %ld", (long) t));
63722 			DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, duk_known_hobject(thr, (duk_idx_t) t));
63723 		} else if (DUK_HOBJECT_IS_NATFUNC(h)) {
63724 			/* Standard native built-ins cannot inherit from
63725 			 * %NativeFunctionPrototype%, they are required to
63726 			 * inherit from Function.prototype directly.
63727 			 */
63728 			DUK_ASSERT(thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE] != NULL);
63729 			DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
63730 		}
63731 
63732 		t = (duk_small_uint_t) duk_bd_decode_varuint(bd);
63733 		if (t > 0) {
63734 			/* 'prototype' property for all built-in objects (which have it) has attributes:
63735 			 *  [[Writable]] = false,
63736 			 *  [[Enumerable]] = false,
63737 			 *  [[Configurable]] = false
63738 			 */
63739 			t--;
63740 			DUK_DDD(DUK_DDDPRINT("set external prototype: built-in %ld", (long) t));
63741 			duk_dup(thr, (duk_idx_t) t);
63742 			duk_xdef_prop_stridx(thr, (duk_idx_t) i, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_NONE);
63743 		}
63744 
63745 		t = (duk_small_uint_t) duk_bd_decode_varuint(bd);
63746 		if (t > 0) {
63747 			/* 'constructor' property for all built-in objects (which have it) has attributes:
63748 			 *  [[Writable]] = true,
63749 			 *  [[Enumerable]] = false,
63750 			 *  [[Configurable]] = true
63751 			 */
63752 			t--;
63753 			DUK_DDD(DUK_DDDPRINT("set external constructor: built-in %ld", (long) t));
63754 			duk_dup(thr, (duk_idx_t) t);
63755 			duk_xdef_prop_stridx(thr, (duk_idx_t) i, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC);
63756 		}
63757 
63758 		/* normal valued properties */
63759 		num = (duk_small_uint_t) duk_bd_decode_varuint(bd);
63760 		DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld normal valued properties", (long) i, (long) num));
63761 		for (j = 0; j < num; j++) {
63762 			duk_small_uint_t defprop_flags;
63763 
63764 			duk__push_stridx_or_string(thr, bd);
63765 
63766 			/*
63767 			 *  Property attribute defaults are defined in E5 Section 15 (first
63768 			 *  few pages); there is a default for all properties and a special
63769 			 *  default for 'length' properties.  Variation from the defaults is
63770 			 *  signaled using a single flag bit in the bitstream.
63771 			 */
63772 
63773 			defprop_flags = (duk_small_uint_t) duk_bd_decode_flagged(bd,
63774 			                                                         DUK__PROP_FLAGS_BITS,
63775 			                                                         (duk_uint32_t) DUK_PROPDESC_FLAGS_WC);
63776 			defprop_flags |= DUK_DEFPROP_FORCE |
63777 			                 DUK_DEFPROP_HAVE_VALUE |
63778 			                 DUK_DEFPROP_HAVE_WRITABLE |
63779 			                 DUK_DEFPROP_HAVE_ENUMERABLE |
63780 			                 DUK_DEFPROP_HAVE_CONFIGURABLE;  /* Defaults for data properties. */
63781 
63782 			/* The writable, enumerable, configurable flags in prop_flags
63783 			 * match both duk_def_prop() and internal property flags.
63784 			 */
63785 			DUK_ASSERT(DUK_PROPDESC_FLAG_WRITABLE == DUK_DEFPROP_WRITABLE);
63786 			DUK_ASSERT(DUK_PROPDESC_FLAG_ENUMERABLE == DUK_DEFPROP_ENUMERABLE);
63787 			DUK_ASSERT(DUK_PROPDESC_FLAG_CONFIGURABLE == DUK_DEFPROP_CONFIGURABLE);
63788 
63789 			t = (duk_small_uint_t) duk_bd_decode(bd, DUK__PROP_TYPE_BITS);
63790 
63791 			DUK_DDD(DUK_DDDPRINT("built-in %ld, normal-valued property %ld, key %!T, flags 0x%02lx, type %ld",
63792 			                     (long) i, (long) j, duk_get_tval(thr, -1), (unsigned long) defprop_flags, (long) t));
63793 
63794 			switch (t) {
63795 			case DUK__PROP_TYPE_DOUBLE: {
63796 				duk__push_double(thr, bd);
63797 				break;
63798 			}
63799 			case DUK__PROP_TYPE_STRING: {
63800 				duk__push_string(thr, bd);
63801 				break;
63802 			}
63803 			case DUK__PROP_TYPE_STRIDX: {
63804 				duk__push_stridx(thr, bd);
63805 				break;
63806 			}
63807 			case DUK__PROP_TYPE_BUILTIN: {
63808 				duk_small_uint_t bidx;
63809 
63810 				bidx = (duk_small_uint_t) duk_bd_decode_varuint(bd);
63811 				duk_dup(thr, (duk_idx_t) bidx);
63812 				break;
63813 			}
63814 			case DUK__PROP_TYPE_UNDEFINED: {
63815 				duk_push_undefined(thr);
63816 				break;
63817 			}
63818 			case DUK__PROP_TYPE_BOOLEAN_TRUE: {
63819 				duk_push_true(thr);
63820 				break;
63821 			}
63822 			case DUK__PROP_TYPE_BOOLEAN_FALSE: {
63823 				duk_push_false(thr);
63824 				break;
63825 			}
63826 			case DUK__PROP_TYPE_ACCESSOR: {
63827 				duk_small_uint_t natidx_getter = (duk_small_uint_t) duk_bd_decode_varuint(bd);
63828 				duk_small_uint_t natidx_setter = (duk_small_uint_t) duk_bd_decode_varuint(bd);
63829 				duk_small_uint_t accessor_magic = (duk_small_uint_t) duk_bd_decode_varuint(bd);
63830 				duk_c_function c_func_getter;
63831 				duk_c_function c_func_setter;
63832 
63833 				DUK_DDD(DUK_DDDPRINT("built-in accessor property: objidx=%ld, key=%!T, getteridx=%ld, setteridx=%ld, flags=0x%04lx",
63834 				                     (long) i, duk_get_tval(thr, -1), (long) natidx_getter, (long) natidx_setter, (unsigned long) defprop_flags));
63835 
63836 				c_func_getter = duk_bi_native_functions[natidx_getter];
63837 				if (c_func_getter != NULL) {
63838 					duk_push_c_function_builtin_noconstruct(thr, c_func_getter, 0);  /* always 0 args */
63839 					duk_set_magic(thr, -1, (duk_int_t) accessor_magic);
63840 					defprop_flags |= DUK_DEFPROP_HAVE_GETTER;
63841 				}
63842 				c_func_setter = duk_bi_native_functions[natidx_setter];
63843 				if (c_func_setter != NULL) {
63844 					duk_push_c_function_builtin_noconstruct(thr, c_func_setter, 1);  /* always 1 arg */
63845 					duk_set_magic(thr, -1, (duk_int_t) accessor_magic);
63846 					defprop_flags |= DUK_DEFPROP_HAVE_SETTER;
63847 				}
63848 
63849 				/* Writable flag doesn't make sense for an accessor. */
63850 				DUK_ASSERT((defprop_flags & DUK_PROPDESC_FLAG_WRITABLE) == 0);  /* genbuiltins.py ensures */
63851 
63852 				defprop_flags &= ~(DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE);
63853 				defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_HAVE_CONFIGURABLE;
63854 				break;
63855 			}
63856 			default: {
63857 				/* exhaustive */
63858 				DUK_UNREACHABLE();
63859 			}
63860 			}
63861 
63862 			duk_def_prop(thr, (duk_idx_t) i, defprop_flags);
63863 			DUK_ASSERT_TOP(thr, DUK_NUM_ALL_BUILTINS);
63864 		}
63865 
63866 		/* native function properties */
63867 		num = (duk_small_uint_t) duk_bd_decode_varuint(bd);
63868 		DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld function valued properties", (long) i, (long) num));
63869 		for (j = 0; j < num; j++) {
63870 			duk_hstring *h_key;
63871 			duk_small_uint_t natidx;
63872 			duk_int_t c_nargs;  /* must hold DUK_VARARGS */
63873 			duk_small_uint_t c_length;
63874 			duk_int16_t magic;
63875 			duk_c_function c_func;
63876 			duk_hnatfunc *h_func;
63877 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
63878 			duk_small_int_t lightfunc_eligible;
63879 #endif
63880 			duk_small_uint_t defprop_flags;
63881 
63882 			duk__push_stridx_or_string(thr, bd);
63883 			h_key = duk_known_hstring(thr, -1);
63884 			DUK_UNREF(h_key);
63885 			natidx = (duk_small_uint_t) duk_bd_decode_varuint(bd);
63886 
63887 			c_length = (duk_small_uint_t) duk_bd_decode(bd, DUK__LENGTH_PROP_BITS);
63888 			c_nargs = (duk_int_t) duk_bd_decode_flagged(bd, DUK__NARGS_BITS, (duk_uint32_t) c_length /*def_value*/);
63889 			if (c_nargs == DUK__NARGS_VARARGS_MARKER) {
63890 				c_nargs = DUK_VARARGS;
63891 			}
63892 
63893 			c_func = duk_bi_native_functions[natidx];
63894 
63895 			DUK_DDD(DUK_DDDPRINT("built-in %ld, function-valued property %ld, key %!O, natidx %ld, length %ld, nargs %ld",
63896 			                     (long) i, (long) j, (duk_heaphdr *) h_key, (long) natidx, (long) c_length,
63897 			                     (c_nargs == DUK_VARARGS ? (long) -1 : (long) c_nargs)));
63898 
63899 			/* Cast converts magic to 16-bit signed value */
63900 			magic = (duk_int16_t) duk_bd_decode_varuint(bd);
63901 
63902 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
63903 			lightfunc_eligible =
63904 				((c_nargs >= DUK_LFUNC_NARGS_MIN && c_nargs <= DUK_LFUNC_NARGS_MAX) || (c_nargs == DUK_VARARGS)) &&
63905 				(c_length <= DUK_LFUNC_LENGTH_MAX) &&
63906 				(magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX);
63907 
63908 			/* These functions have trouble working as lightfuncs.
63909 			 * Some of them have specific asserts and some may have
63910 		         * additional properties (e.g. 'require.id' may be written).
63911 			 */
63912 			if (c_func == duk_bi_global_object_eval) {
63913 				lightfunc_eligible = 0;
63914 			}
63915 #if defined(DUK_USE_COROUTINE_SUPPORT)
63916 			if (c_func == duk_bi_thread_yield ||
63917 			    c_func == duk_bi_thread_resume) {
63918 				lightfunc_eligible = 0;
63919 			}
63920 #endif
63921 			if (c_func == duk_bi_function_prototype_call ||
63922 			    c_func == duk_bi_function_prototype_apply ||
63923 			    c_func == duk_bi_reflect_apply ||
63924 			    c_func == duk_bi_reflect_construct) {
63925 				lightfunc_eligible = 0;
63926 			}
63927 
63928 			if (lightfunc_eligible) {
63929 				duk_tval tv_lfunc;
63930 				duk_small_uint_t lf_nargs = (duk_small_uint_t) (c_nargs == DUK_VARARGS ? DUK_LFUNC_NARGS_VARARGS : c_nargs);
63931 				duk_small_uint_t lf_flags = DUK_LFUNC_FLAGS_PACK(magic, c_length, lf_nargs);
63932 				DUK_TVAL_SET_LIGHTFUNC(&tv_lfunc, c_func, lf_flags);
63933 				duk_push_tval(thr, &tv_lfunc);
63934 				DUK_D(DUK_DPRINT("built-in function eligible as light function: i=%d, j=%d c_length=%ld, c_nargs=%ld, magic=%ld -> %!iT", (int) i, (int) j, (long) c_length, (long) c_nargs, (long) magic, duk_get_tval(thr, -1)));
63935 				goto lightfunc_skip;
63936 			}
63937 
63938 			DUK_D(DUK_DPRINT("built-in function NOT ELIGIBLE as light function: i=%d, j=%d c_length=%ld, c_nargs=%ld, magic=%ld", (int) i, (int) j, (long) c_length, (long) c_nargs, (long) magic));
63939 #endif  /* DUK_USE_LIGHTFUNC_BUILTINS */
63940 
63941 			/* [ (builtin objects) name ] */
63942 
63943 			duk_push_c_function_builtin_noconstruct(thr, c_func, c_nargs);
63944 			h_func = duk_known_hnatfunc(thr, -1);
63945 			DUK_UNREF(h_func);
63946 
63947 			/* XXX: add into init data? */
63948 
63949 			/* Special call handling, not described in init data. */
63950 			if (c_func == duk_bi_global_object_eval ||
63951 			    c_func == duk_bi_function_prototype_call ||
63952 			    c_func == duk_bi_function_prototype_apply ||
63953 			    c_func == duk_bi_reflect_apply ||
63954 			    c_func == duk_bi_reflect_construct) {
63955 				DUK_HOBJECT_SET_SPECIAL_CALL((duk_hobject *) h_func);
63956 			}
63957 
63958 			/* Currently all built-in native functions are strict.
63959 			 * This doesn't matter for many functions, but e.g.
63960 			 * String.prototype.charAt (and other string functions)
63961 			 * rely on being strict so that their 'this' binding is
63962 			 * not automatically coerced.
63963 			 */
63964 			DUK_HOBJECT_SET_STRICT((duk_hobject *) h_func);
63965 
63966 			/* No built-in functions are constructable except the top
63967 			 * level ones (Number, etc).
63968 			 */
63969 			DUK_ASSERT(!DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) h_func));
63970 
63971 			/* XXX: any way to avoid decoding magic bit; there are quite
63972 			 * many function properties and relatively few with magic values.
63973 			 */
63974 			h_func->magic = magic;
63975 
63976 			/* [ (builtin objects) name func ] */
63977 
63978 			duk_push_uint(thr, c_length);
63979 			duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);
63980 
63981 			duk_dup_m2(thr);
63982 			duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
63983 
63984 			/* XXX: other properties of function instances; 'arguments', 'caller'. */
63985 
63986 			DUK_DD(DUK_DDPRINT("built-in object %ld, function property %ld -> %!T",
63987 			                   (long) i, (long) j, (duk_tval *) duk_get_tval(thr, -1)));
63988 
63989 			/* [ (builtin objects) name func ] */
63990 
63991 			/*
63992 			 *  The default property attributes are correct for all
63993 			 *  function valued properties of built-in objects now.
63994 			 */
63995 
63996 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
63997 		 lightfunc_skip:
63998 #endif
63999 
64000 			defprop_flags = (duk_small_uint_t) duk_bd_decode_flagged(bd,
64001 			                                                         DUK__PROP_FLAGS_BITS,
64002 			                                                         (duk_uint32_t) DUK_PROPDESC_FLAGS_WC);
64003 			defprop_flags |= DUK_DEFPROP_FORCE |
64004 			                 DUK_DEFPROP_HAVE_VALUE |
64005 			                 DUK_DEFPROP_HAVE_WRITABLE |
64006 			                 DUK_DEFPROP_HAVE_ENUMERABLE |
64007 			                 DUK_DEFPROP_HAVE_CONFIGURABLE;
64008 			DUK_ASSERT(DUK_PROPDESC_FLAG_WRITABLE == DUK_DEFPROP_WRITABLE);
64009 			DUK_ASSERT(DUK_PROPDESC_FLAG_ENUMERABLE == DUK_DEFPROP_ENUMERABLE);
64010 			DUK_ASSERT(DUK_PROPDESC_FLAG_CONFIGURABLE == DUK_DEFPROP_CONFIGURABLE);
64011 
64012 			duk_def_prop(thr, (duk_idx_t) i, defprop_flags);
64013 
64014 			/* [ (builtin objects) ] */
64015 		}
64016 	}
64017 
64018 	/*
64019 	 *  Special post-tweaks, for cases not covered by the init data format.
64020 	 *
64021 	 *  - Set Date.prototype.toGMTString to Date.prototype.toUTCString.
64022 	 *    toGMTString is required to have the same Function object as
64023 	 *    toUTCString in E5 Section B.2.6.  Note that while Smjs respects
64024 	 *    this, V8 does not (the Function objects are distinct).
64025 	 *
64026 	 *  - Make DoubleError non-extensible.
64027 	 *
64028 	 *  - Add info about most important effective compile options to Duktape.
64029 	 *
64030 	 *  - Possibly remove some properties (values or methods) which are not
64031 	 *    desirable with current feature options but are not currently
64032 	 *    conditional in init data.
64033 	 */
64034 
64035 #if defined(DUK_USE_DATE_BUILTIN)
64036 	duk_get_prop_stridx_short(thr, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_UTC_STRING);
64037 	duk_xdef_prop_stridx_short(thr, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_GMT_STRING, DUK_PROPDESC_FLAGS_WC);
64038 #endif
64039 
64040 	h = duk_known_hobject(thr, DUK_BIDX_DOUBLE_ERROR);
64041 	DUK_HOBJECT_CLEAR_EXTENSIBLE(h);
64042 
64043 #if !defined(DUK_USE_ES6_OBJECT_PROTO_PROPERTY)
64044 	DUK_DD(DUK_DDPRINT("delete Object.prototype.__proto__ built-in which is not enabled in features"));
64045 	(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_PROTOTYPE], DUK_HTHREAD_STRING___PROTO__(thr), DUK_DELPROP_FLAG_THROW);
64046 #endif
64047 
64048 #if !defined(DUK_USE_ES6_OBJECT_SETPROTOTYPEOF)
64049 	DUK_DD(DUK_DDPRINT("delete Object.setPrototypeOf built-in which is not enabled in features"));
64050 	(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_CONSTRUCTOR], DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr), DUK_DELPROP_FLAG_THROW);
64051 #endif
64052 
64053 	/* XXX: relocate */
64054 	duk_push_string(thr,
64055 			/* Endianness indicator */
64056 #if defined(DUK_USE_INTEGER_LE)
64057 	                "l"
64058 #elif defined(DUK_USE_INTEGER_BE)
64059 	                "b"
64060 #elif defined(DUK_USE_INTEGER_ME)  /* integer mixed endian not really used now */
64061 	                "m"
64062 #else
64063 	                "?"
64064 #endif
64065 #if defined(DUK_USE_DOUBLE_LE)
64066 	                "l"
64067 #elif defined(DUK_USE_DOUBLE_BE)
64068 	                "b"
64069 #elif defined(DUK_USE_DOUBLE_ME)
64070 	                "m"
64071 #else
64072 	                "?"
64073 #endif
64074 	                " "
64075 			/* Packed or unpacked tval */
64076 #if defined(DUK_USE_PACKED_TVAL)
64077 	                "p"
64078 #else
64079 	                "u"
64080 #endif
64081 #if defined(DUK_USE_FASTINT)
64082 			"f"
64083 #endif
64084 			" "
64085 			/* Low memory/performance options */
64086 #if defined(DUK_USE_STRTAB_PTRCOMP)
64087 			"s"
64088 #endif
64089 #if !defined(DUK_USE_HEAPPTR16) && !defined(DUK_DATAPTR16) && !defined(DUK_FUNCPTR16)
64090 			"n"
64091 #endif
64092 #if defined(DUK_USE_HEAPPTR16)
64093 			"h"
64094 #endif
64095 #if defined(DUK_USE_DATAPTR16)
64096 			"d"
64097 #endif
64098 #if defined(DUK_USE_FUNCPTR16)
64099 			"f"
64100 #endif
64101 #if defined(DUK_USE_REFCOUNT16)
64102 			"R"
64103 #endif
64104 #if defined(DUK_USE_STRHASH16)
64105 			"H"
64106 #endif
64107 #if defined(DUK_USE_STRLEN16)
64108 			"S"
64109 #endif
64110 #if defined(DUK_USE_BUFLEN16)
64111 			"B"
64112 #endif
64113 #if defined(DUK_USE_OBJSIZES16)
64114 			"O"
64115 #endif
64116 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
64117 			"L"
64118 #endif
64119 #if defined(DUK_USE_ROM_STRINGS) || defined(DUK_USE_ROM_OBJECTS)
64120 			/* XXX: This won't be shown in practice now
64121 			 * because this code is not run when builtins
64122 			 * are in ROM.
64123 			 */
64124 			"Z"
64125 #endif
64126 #if defined(DUK_USE_LITCACHE_SIZE)
64127 			"l"
64128 #endif
64129 	                " "
64130 			/* Object property allocation layout */
64131 #if defined(DUK_USE_HOBJECT_LAYOUT_1)
64132 			"p1"
64133 #elif defined(DUK_USE_HOBJECT_LAYOUT_2)
64134 			"p2"
64135 #elif defined(DUK_USE_HOBJECT_LAYOUT_3)
64136 			"p3"
64137 #else
64138 			"p?"
64139 #endif
64140 			" "
64141 			/* Alignment guarantee */
64142 #if (DUK_USE_ALIGN_BY == 4)
64143 			"a4"
64144 #elif (DUK_USE_ALIGN_BY == 8)
64145 			"a8"
64146 #elif (DUK_USE_ALIGN_BY == 1)
64147 			"a1"
64148 #else
64149 #error invalid DUK_USE_ALIGN_BY
64150 #endif
64151 			" "
64152 			/* Architecture, OS, and compiler strings */
64153 	                DUK_USE_ARCH_STRING
64154 			" "
64155 	                DUK_USE_OS_STRING
64156 			" "
64157 	                DUK_USE_COMPILER_STRING);
64158 	duk_xdef_prop_stridx_short(thr, DUK_BIDX_DUKTAPE, DUK_STRIDX_ENV, DUK_PROPDESC_FLAGS_WC);
64159 
64160 	/*
64161 	 *  Since built-ins are not often extended, compact them.
64162 	 */
64163 
64164 	DUK_DD(DUK_DDPRINT("compact built-ins"));
64165 	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
64166 		duk_hobject_compact_props(thr, duk_known_hobject(thr, (duk_idx_t) i));
64167 	}
64168 
64169 	DUK_D(DUK_DPRINT("INITBUILTINS END"));
64170 
64171 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
64172 	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
64173 		DUK_DD(DUK_DDPRINT("built-in object %ld after initialization and compacting: %!@iO",
64174 		                   (long) i, (duk_heaphdr *) duk_require_hobject(thr, (duk_idx_t) i)));
64175 	}
64176 #endif
64177 
64178 	/*
64179 	 *  Pop built-ins from stack: they are now INCREF'd and
64180 	 *  reachable from the builtins[] array or indirectly
64181 	 *  through builtins[].
64182 	 */
64183 
64184 	duk_set_top(thr, 0);
64185 	DUK_ASSERT_TOP(thr, 0);
64186 }
64187 #endif  /* DUK_USE_ROM_OBJECTS */
64188 
64189 DUK_INTERNAL void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to) {
64190 	duk_small_uint_t i;
64191 
64192 	for (i = 0; i < DUK_NUM_BUILTINS; i++) {
64193 		thr_to->builtins[i] = thr_from->builtins[i];
64194 		DUK_HOBJECT_INCREF_ALLOWNULL(thr_to, thr_to->builtins[i]);  /* side effect free */
64195 	}
64196 }
64197 
64198 /* automatic undefs */
64199 #undef DUK__LENGTH_PROP_BITS
64200 #undef DUK__NARGS_BITS
64201 #undef DUK__NARGS_VARARGS_MARKER
64202 #undef DUK__PROP_FLAGS_BITS
64203 #undef DUK__PROP_TYPE_ACCESSOR
64204 #undef DUK__PROP_TYPE_BITS
64205 #undef DUK__PROP_TYPE_BOOLEAN_FALSE
64206 #undef DUK__PROP_TYPE_BOOLEAN_TRUE
64207 #undef DUK__PROP_TYPE_BUILTIN
64208 #undef DUK__PROP_TYPE_DOUBLE
64209 #undef DUK__PROP_TYPE_STRIDX
64210 #undef DUK__PROP_TYPE_STRING
64211 #undef DUK__PROP_TYPE_UNDEFINED
64212 /*
64213  *  Thread support.
64214  */
64215 
64216 /* #include duk_internal.h -> already included */
64217 
64218 DUK_INTERNAL void duk_hthread_terminate(duk_hthread *thr) {
64219 	DUK_ASSERT(thr != NULL);
64220 
64221 	while (thr->callstack_curr != NULL) {
64222 		duk_hthread_activation_unwind_norz(thr);
64223 	}
64224 
64225 	thr->valstack_bottom = thr->valstack;
64226 	duk_set_top(thr, 0);  /* unwinds valstack, updating refcounts */
64227 
64228 	thr->state = DUK_HTHREAD_STATE_TERMINATED;
64229 
64230 	/* Here we could remove references to built-ins, but it may not be
64231 	 * worth the effort because built-ins are quite likely to be shared
64232 	 * with another (unterminated) thread, and terminated threads are also
64233 	 * usually garbage collected quite quickly.
64234 	 *
64235 	 * We could also shrink the value stack here, but that also may not
64236 	 * be worth the effort for the same reason.
64237 	 */
64238 
64239 	DUK_REFZERO_CHECK_SLOW(thr);
64240 }
64241 
64242 #if defined(DUK_USE_DEBUGGER_SUPPORT)
64243 DUK_INTERNAL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act) {
64244 	duk_instr_t *bcode;
64245 
64246 	DUK_ASSERT(thr != NULL);
64247 	DUK_ASSERT(act != NULL);
64248 	DUK_UNREF(thr);
64249 
64250 	/* XXX: store 'bcode' pointer to activation for faster lookup? */
64251 	if (act->func && DUK_HOBJECT_IS_COMPFUNC(act->func)) {
64252 		bcode = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) (act->func));
64253 		return (duk_uint_fast32_t) (act->curr_pc - bcode);
64254 	}
64255 	return 0;
64256 }
64257 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
64258 
64259 DUK_INTERNAL duk_uint_fast32_t duk_hthread_get_act_prev_pc(duk_hthread *thr, duk_activation *act) {
64260 	duk_instr_t *bcode;
64261 	duk_uint_fast32_t ret;
64262 
64263 	DUK_ASSERT(thr != NULL);
64264 	DUK_ASSERT(act != NULL);
64265 	DUK_UNREF(thr);
64266 
64267 	if (act->func && DUK_HOBJECT_IS_COMPFUNC(act->func)) {
64268 		bcode = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) (act->func));
64269 		ret = (duk_uint_fast32_t) (act->curr_pc - bcode);
64270 		if (ret > 0) {
64271 			ret--;
64272 		}
64273 		return ret;
64274 	}
64275 	return 0;
64276 }
64277 
64278 /* Write bytecode executor's curr_pc back to topmost activation (if any). */
64279 DUK_INTERNAL void duk_hthread_sync_currpc(duk_hthread *thr) {
64280 	duk_activation *act;
64281 
64282 	DUK_ASSERT(thr != NULL);
64283 
64284 	if (thr->ptr_curr_pc != NULL) {
64285 		/* ptr_curr_pc != NULL only when bytecode executor is active. */
64286 		DUK_ASSERT(thr->callstack_top > 0);
64287 		DUK_ASSERT(thr->callstack_curr != NULL);
64288 		act = thr->callstack_curr;
64289 		DUK_ASSERT(act != NULL);
64290 		act->curr_pc = *thr->ptr_curr_pc;
64291 	}
64292 }
64293 
64294 DUK_INTERNAL void duk_hthread_sync_and_null_currpc(duk_hthread *thr) {
64295 	duk_activation *act;
64296 
64297 	DUK_ASSERT(thr != NULL);
64298 
64299 	if (thr->ptr_curr_pc != NULL) {
64300 		/* ptr_curr_pc != NULL only when bytecode executor is active. */
64301 		DUK_ASSERT(thr->callstack_top > 0);
64302 		DUK_ASSERT(thr->callstack_curr != NULL);
64303 		act = thr->callstack_curr;
64304 		DUK_ASSERT(act != NULL);
64305 		act->curr_pc = *thr->ptr_curr_pc;
64306 		thr->ptr_curr_pc = NULL;
64307 	}
64308 }
64309 /*
64310  *  Thread stack (mainly call stack) primitives: allocation of activations,
64311  *  unwinding catchers and activations, etc.
64312  *
64313  *  Value stack handling is a part of the API implementation.
64314  */
64315 
64316 /* #include duk_internal.h -> already included */
64317 
64318 /* Unwind the topmost catcher of the current activation (caller must check that
64319  * both exist) without side effects.
64320  */
64321 DUK_INTERNAL void duk_hthread_catcher_unwind_norz(duk_hthread *thr, duk_activation *act) {
64322 	duk_catcher *cat;
64323 
64324 	DUK_ASSERT(thr != NULL);
64325 	DUK_ASSERT(act != NULL);
64326 	DUK_ASSERT(act->cat != NULL);  /* caller must check */
64327 	cat = act->cat;
64328 	DUK_ASSERT(cat != NULL);
64329 
64330 	DUK_DDD(DUK_DDDPRINT("unwinding catch stack entry %p (lexenv check is done)", (void *) cat));
64331 
64332 	if (DUK_CAT_HAS_LEXENV_ACTIVE(cat)) {
64333 		duk_hobject *env;
64334 
64335 		env = act->lex_env;             /* current lex_env of the activation (created for catcher) */
64336 		DUK_ASSERT(env != NULL);        /* must be, since env was created when catcher was created */
64337 		act->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env);  /* prototype is lex_env before catcher created */
64338 		DUK_HOBJECT_INCREF(thr, act->lex_env);
64339 		DUK_HOBJECT_DECREF_NORZ(thr, env);
64340 
64341 		/* There is no need to decref anything else than 'env': if 'env'
64342 		 * becomes unreachable, refzero will handle decref'ing its prototype.
64343 		 */
64344 	}
64345 
64346 	act->cat = cat->parent;
64347 	duk_hthread_catcher_free(thr, cat);
64348 }
64349 
64350 /* Same as above, but caller is certain no catcher-related lexenv may exist. */
64351 DUK_INTERNAL void duk_hthread_catcher_unwind_nolexenv_norz(duk_hthread *thr, duk_activation *act) {
64352 	duk_catcher *cat;
64353 
64354 	DUK_ASSERT(thr != NULL);
64355 	DUK_ASSERT(act != NULL);
64356 	DUK_ASSERT(act->cat != NULL);  /* caller must check */
64357 	cat = act->cat;
64358 	DUK_ASSERT(cat != NULL);
64359 
64360 	DUK_DDD(DUK_DDDPRINT("unwinding catch stack entry %p (lexenv check is not done)", (void *) cat));
64361 
64362 	DUK_ASSERT(!DUK_CAT_HAS_LEXENV_ACTIVE(cat));
64363 
64364 	act->cat = cat->parent;
64365 	duk_hthread_catcher_free(thr, cat);
64366 }
64367 
64368 DUK_LOCAL
64369 #if defined(DUK_USE_CACHE_CATCHER)
64370 DUK_NOINLINE
64371 #endif
64372 duk_catcher *duk__hthread_catcher_alloc_slow(duk_hthread *thr) {
64373 	duk_catcher *cat;
64374 
64375 	cat = (duk_catcher *) DUK_ALLOC_CHECKED(thr, sizeof(duk_catcher));
64376 	DUK_ASSERT(cat != NULL);
64377 	return cat;
64378 }
64379 
64380 #if defined(DUK_USE_CACHE_CATCHER)
64381 DUK_INTERNAL DUK_INLINE duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr) {
64382 	duk_catcher *cat;
64383 
64384 	DUK_ASSERT(thr != NULL);
64385 
64386 	cat = thr->heap->catcher_free;
64387 	if (DUK_LIKELY(cat != NULL)) {
64388 		thr->heap->catcher_free = cat->parent;
64389 		return cat;
64390 	}
64391 
64392 	return duk__hthread_catcher_alloc_slow(thr);
64393 }
64394 #else  /* DUK_USE_CACHE_CATCHER */
64395 DUK_INTERNAL duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr) {
64396 	return duk__hthread_catcher_alloc_slow(thr);
64397 }
64398 #endif  /* DUK_USE_CACHE_CATCHER */
64399 
64400 DUK_INTERNAL void duk_hthread_catcher_free(duk_hthread *thr, duk_catcher *cat) {
64401 	DUK_ASSERT(thr != NULL);
64402 	DUK_ASSERT(cat != NULL);
64403 
64404 #if defined(DUK_USE_CACHE_CATCHER)
64405 	/* Unconditional caching for now; freed in mark-and-sweep. */
64406 	cat->parent = thr->heap->catcher_free;
64407 	thr->heap->catcher_free = cat;
64408 #else
64409 	DUK_FREE_CHECKED(thr, (void *) cat);
64410 #endif
64411 }
64412 
64413 DUK_LOCAL
64414 #if defined(DUK_USE_CACHE_ACTIVATION)
64415 DUK_NOINLINE
64416 #endif
64417 duk_activation *duk__hthread_activation_alloc_slow(duk_hthread *thr) {
64418 	duk_activation *act;
64419 
64420 	act = (duk_activation *) DUK_ALLOC_CHECKED(thr, sizeof(duk_activation));
64421 	DUK_ASSERT(act != NULL);
64422 	return act;
64423 }
64424 
64425 #if defined(DUK_USE_CACHE_ACTIVATION)
64426 DUK_INTERNAL DUK_INLINE duk_activation *duk_hthread_activation_alloc(duk_hthread *thr) {
64427 	duk_activation *act;
64428 
64429 	DUK_ASSERT(thr != NULL);
64430 
64431 	act = thr->heap->activation_free;
64432 	if (DUK_LIKELY(act != NULL)) {
64433 		thr->heap->activation_free = act->parent;
64434 		return act;
64435 	}
64436 
64437 	return duk__hthread_activation_alloc_slow(thr);
64438 }
64439 #else  /* DUK_USE_CACHE_ACTIVATION */
64440 DUK_INTERNAL duk_activation *duk_hthread_activation_alloc(duk_hthread *thr) {
64441 	return duk__hthread_activation_alloc_slow(thr);
64442 }
64443 #endif  /* DUK_USE_CACHE_ACTIVATION */
64444 
64445 
64446 DUK_INTERNAL void duk_hthread_activation_free(duk_hthread *thr, duk_activation *act) {
64447 	DUK_ASSERT(thr != NULL);
64448 	DUK_ASSERT(act != NULL);
64449 
64450 #if defined(DUK_USE_CACHE_ACTIVATION)
64451 	/* Unconditional caching for now; freed in mark-and-sweep. */
64452 	act->parent = thr->heap->activation_free;
64453 	thr->heap->activation_free = act;
64454 #else
64455 	DUK_FREE_CHECKED(thr, (void *) act);
64456 #endif
64457 }
64458 
64459 /* Internal helper: process the unwind for the topmost activation of a thread,
64460  * but leave the duk_activation in place for possible tailcall reuse.
64461  */
64462 DUK_LOCAL void duk__activation_unwind_nofree_norz(duk_hthread *thr) {
64463 #if defined(DUK_USE_DEBUGGER_SUPPORT)
64464 	duk_heap *heap;
64465 #endif
64466 	duk_activation *act;
64467 	duk_hobject *func;
64468 	duk_hobject *tmp;
64469 
64470 	DUK_ASSERT(thr != NULL);
64471 	DUK_ASSERT(thr->callstack_curr != NULL);  /* caller must check */
64472 	DUK_ASSERT(thr->callstack_top > 0);
64473 	act = thr->callstack_curr;
64474 	DUK_ASSERT(act != NULL);
64475 	/* With lightfuncs, act 'func' may be NULL. */
64476 
64477 	/* With duk_activation records allocated separately, 'act' is a stable
64478 	 * pointer and not affected by side effects.
64479 	 */
64480 
64481 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
64482 	/*
64483 	 *  Restore 'caller' property for non-strict callee functions.
64484 	 */
64485 
64486 	func = DUK_ACT_GET_FUNC(act);
64487 	if (func != NULL && !DUK_HOBJECT_HAS_STRICT(func)) {
64488 		duk_tval *tv_caller;
64489 		duk_tval tv_tmp;
64490 		duk_hobject *h_tmp;
64491 
64492 		tv_caller = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, func, DUK_STRIDX_CALLER);
64493 
64494 		/* The act->prev_caller should only be set if the entry for 'caller'
64495 		 * exists (as it is only set in that case, and the property is not
64496 		 * configurable), but handle all the cases anyway.
64497 		 */
64498 
64499 		if (tv_caller) {
64500 			DUK_TVAL_SET_TVAL(&tv_tmp, tv_caller);
64501 			if (act->prev_caller) {
64502 				/* Just transfer the refcount from act->prev_caller to tv_caller,
64503 				 * so no need for a refcount update.  This is the expected case.
64504 				 */
64505 				DUK_TVAL_SET_OBJECT(tv_caller, act->prev_caller);
64506 				act->prev_caller = NULL;
64507 			} else {
64508 				DUK_TVAL_SET_NULL(tv_caller);   /* no incref needed */
64509 				DUK_ASSERT(act->prev_caller == NULL);
64510 			}
64511 			DUK_TVAL_DECREF_NORZ(thr, &tv_tmp);
64512 		} else {
64513 			h_tmp = act->prev_caller;
64514 			if (h_tmp) {
64515 				act->prev_caller = NULL;
64516 				DUK_HOBJECT_DECREF_NORZ(thr, h_tmp);
64517 			}
64518 		}
64519 		DUK_ASSERT(act->prev_caller == NULL);
64520 	}
64521 #endif
64522 
64523 	/*
64524 	 *  Unwind debugger state.  If we unwind while stepping
64525 	 *  (for any step type), pause execution.  This is the
64526 	 *  only place explicitly handling a step out.
64527 	 */
64528 
64529 #if defined(DUK_USE_DEBUGGER_SUPPORT)
64530 	heap = thr->heap;
64531 	if (heap->dbg_pause_act == thr->callstack_curr) {
64532 		if (heap->dbg_pause_flags & DUK_PAUSE_FLAG_FUNC_EXIT) {
64533 			DUK_D(DUK_DPRINT("PAUSE TRIGGERED by function exit"));
64534 			duk_debug_set_paused(heap);
64535 		} else {
64536 			DUK_D(DUK_DPRINT("unwound past dbg_pause_act, set to NULL"));
64537 			heap->dbg_pause_act = NULL;  /* avoid stale pointers */
64538 		}
64539 		DUK_ASSERT(heap->dbg_pause_act == NULL);
64540 	}
64541 #endif
64542 
64543 	/*
64544 	 *  Unwind catchers.
64545 	 *
64546 	 *  Since there are no references in the catcher structure,
64547 	 *  unwinding is quite simple.  The only thing we need to
64548 	 *  look out for is popping a possible lexical environment
64549 	 *  established for an active catch clause.
64550 	 */
64551 
64552 	while (act->cat != NULL) {
64553 		duk_hthread_catcher_unwind_norz(thr, act);
64554 	}
64555 
64556 	/*
64557 	 *  Close environment record(s) if they exist.
64558 	 *
64559 	 *  Only variable environments are closed.  If lex_env != var_env, it
64560 	 *  cannot currently contain any register bound declarations.
64561 	 *
64562 	 *  Only environments created for a NEWENV function are closed.  If an
64563 	 *  environment is created for e.g. an eval call, it must not be closed.
64564 	 */
64565 
64566 	func = DUK_ACT_GET_FUNC(act);
64567 	if (func != NULL && !DUK_HOBJECT_HAS_NEWENV(func)) {
64568 		DUK_DDD(DUK_DDDPRINT("skip closing environments, envs not owned by this activation"));
64569 		goto skip_env_close;
64570 	}
64571 	/* func is NULL for lightfunc */
64572 
64573 	/* Catch sites are required to clean up their environments
64574 	 * in FINALLY part before propagating, so this should
64575 	 * always hold here.
64576 	 */
64577 	DUK_ASSERT(act->lex_env == act->var_env);
64578 
64579 	/* XXX: Closing the environment record copies values from registers
64580 	 * into the scope object.  It's side effect free as such, but may
64581 	 * currently run out of memory which causes an error throw.  This is
64582 	 * an actual sandboxing problem for error unwinds, and needs to be
64583 	 * fixed e.g. by preallocating the scope property slots.
64584 	 */
64585 	if (act->var_env != NULL) {
64586 		DUK_DDD(DUK_DDDPRINT("closing var_env record %p -> %!O",
64587 		                     (void *) act->var_env, (duk_heaphdr *) act->var_env));
64588 		duk_js_close_environment_record(thr, act->var_env);
64589 	}
64590 
64591  skip_env_close:
64592 
64593 	/*
64594 	 *  Update preventcount
64595 	 */
64596 
64597 	if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
64598 		DUK_ASSERT(thr->callstack_preventcount >= 1);
64599 		thr->callstack_preventcount--;
64600 	}
64601 
64602 	/*
64603 	 *  Reference count updates, using NORZ macros so we don't
64604 	 *  need to handle side effects.
64605 	 *
64606 	 *  duk_activation pointers like act->var_env are intentionally
64607 	 *  left as garbage and not NULLed.  Without side effects they
64608 	 *  can't be used when the values are dangling/garbage.
64609 	 */
64610 
64611 	DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, act->var_env);
64612 	DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, act->lex_env);
64613 	tmp = DUK_ACT_GET_FUNC(act);
64614 	DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
64615 	DUK_UNREF(tmp);
64616 }
64617 
64618 /* Unwind topmost duk_activation of a thread, caller must ensure that an
64619  * activation exists.  The call is side effect free, except that scope
64620  * closure may currently throw an out-of-memory error.
64621  */
64622 DUK_INTERNAL void duk_hthread_activation_unwind_norz(duk_hthread *thr) {
64623 	duk_activation *act;
64624 
64625 	duk__activation_unwind_nofree_norz(thr);
64626 
64627 	DUK_ASSERT(thr->callstack_curr != NULL);
64628 	DUK_ASSERT(thr->callstack_top > 0);
64629 	act = thr->callstack_curr;
64630 	thr->callstack_curr = act->parent;
64631 	thr->callstack_top--;
64632 
64633 	/* Ideally we'd restore value stack reserve here to caller's value.
64634 	 * This doesn't work for current unwind call sites however, because
64635 	 * the current (unwound) value stack top may be above the reserve.
64636 	 * Thus value stack reserve is restored by the call sites.
64637 	 */
64638 
64639 	/* XXX: inline for performance builds? */
64640 	duk_hthread_activation_free(thr, act);
64641 
64642 	/* We could clear the book-keeping variables like retval_byteoff for
64643 	 * the topmost activation, but don't do so now as it's not necessary.
64644 	 */
64645 }
64646 
64647 DUK_INTERNAL void duk_hthread_activation_unwind_reuse_norz(duk_hthread *thr) {
64648 	duk__activation_unwind_nofree_norz(thr);
64649 }
64650 
64651 /* Get duk_activation for given callstack level or NULL if level is invalid
64652  * or deeper than the call stack.  Level -1 refers to current activation, -2
64653  * to its caller, etc.  Starting from Duktape 2.2 finding the activation is
64654  * a linked list scan which gets more expensive the deeper the lookup is.
64655  */
64656 DUK_INTERNAL duk_activation *duk_hthread_get_activation_for_level(duk_hthread *thr, duk_int_t level) {
64657 	duk_activation *act;
64658 
64659 	if (level >= 0) {
64660 		return NULL;
64661 	}
64662 	act = thr->callstack_curr;
64663 	for (;;) {
64664 		if (act == NULL) {
64665 			return act;
64666 		}
64667 		if (level == -1) {
64668 			return act;
64669 		}
64670 		level++;
64671 		act = act->parent;
64672 	}
64673 	/* never here */
64674 }
64675 
64676 #if defined(DUK_USE_FINALIZER_TORTURE)
64677 DUK_INTERNAL void duk_hthread_valstack_torture_realloc(duk_hthread *thr) {
64678 	duk_size_t alloc_size;
64679 	duk_tval *new_ptr;
64680 	duk_ptrdiff_t alloc_end_off;
64681 	duk_ptrdiff_t end_off;
64682 	duk_ptrdiff_t bottom_off;
64683 	duk_ptrdiff_t top_off;
64684 
64685 	if (thr->valstack == NULL) {
64686 		DUK_D(DUK_DPRINT("skip valstack torture realloc, valstack is NULL"));
64687 		return;
64688 	}
64689 
64690 	alloc_end_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_alloc_end - (duk_uint8_t *) thr->valstack);
64691 	end_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
64692 	bottom_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack);
64693 	top_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack);
64694 	alloc_size = (duk_size_t) alloc_end_off;
64695 	if (alloc_size == 0) {
64696 		DUK_D(DUK_DPRINT("skip valstack torture realloc, alloc_size is zero"));
64697 		return;
64698 	}
64699 
64700 	/* Use DUK_ALLOC_RAW() to avoid side effects. */
64701 	new_ptr = (duk_tval *) DUK_ALLOC_RAW(thr->heap, alloc_size);
64702 	if (new_ptr != NULL) {
64703 		duk_memcpy((void *) new_ptr, (const void *) thr->valstack, alloc_size);
64704 		duk_memset((void *) thr->valstack, 0x55, alloc_size);
64705 		DUK_FREE_CHECKED(thr, (void *) thr->valstack);
64706 		thr->valstack = new_ptr;
64707 		thr->valstack_alloc_end = (duk_tval *) ((duk_uint8_t *) new_ptr + alloc_end_off);
64708 		thr->valstack_end = (duk_tval *) ((duk_uint8_t *) new_ptr + end_off);
64709 		thr->valstack_bottom = (duk_tval *) ((duk_uint8_t *) new_ptr + bottom_off);
64710 		thr->valstack_top = (duk_tval *) ((duk_uint8_t *) new_ptr + top_off);
64711 	} else {
64712 		DUK_D(DUK_DPRINT("failed to realloc valstack for torture, ignore"));
64713 	}
64714 }
64715 #endif  /* DUK_USE_FINALIZER_TORTURE */
64716 /*
64717  *  Shared helpers for arithmetic operations
64718  */
64719 
64720 /* #include duk_internal.h -> already included */
64721 
64722 /* ECMAScript modulus ('%') does not match IEEE 754 "remainder" operation
64723  * (implemented by remainder() in C99) but does seem to match ANSI C fmod().
64724  * Compare E5 Section 11.5.3 and "man fmod".
64725  */
64726 DUK_INTERNAL double duk_js_arith_mod(double d1, double d2) {
64727 #if defined(DUK_USE_POW_WORKAROUNDS)
64728 	/* Specific fixes to common fmod() implementation issues:
64729 	 * - test-bug-mingw-math-issues.js
64730 	 */
64731 	if (DUK_ISINF(d2)) {
64732 		if (DUK_ISINF(d1)) {
64733 			return DUK_DOUBLE_NAN;
64734 		} else {
64735 			return d1;
64736 		}
64737 	} else if (duk_double_equals(d1, 0.0)) {
64738 		/* d1 +/-0 is returned as is (preserving sign) except when
64739 		 * d2 is zero or NaN.
64740 		 */
64741 		if (duk_double_equals(d2, 0.0) || DUK_ISNAN(d2)) {
64742 			return DUK_DOUBLE_NAN;
64743 		} else {
64744 			return d1;
64745 		}
64746 	}
64747 #else
64748 	/* Some ISO C assumptions. */
64749 	DUK_ASSERT(duk_double_equals(DUK_FMOD(1.0, DUK_DOUBLE_INFINITY), 1.0));
64750 	DUK_ASSERT(duk_double_equals(DUK_FMOD(-1.0, DUK_DOUBLE_INFINITY), -1.0));
64751 	DUK_ASSERT(duk_double_equals(DUK_FMOD(1.0, -DUK_DOUBLE_INFINITY), 1.0));
64752 	DUK_ASSERT(duk_double_equals(DUK_FMOD(-1.0, -DUK_DOUBLE_INFINITY), -1.0));
64753 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY)));
64754 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY)));
64755 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY)));
64756 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY)));
64757 	DUK_ASSERT(duk_double_equals(DUK_FMOD(0.0, 1.0), 0.0) && DUK_SIGNBIT(DUK_FMOD(0.0, 1.0)) == 0);
64758 	DUK_ASSERT(duk_double_equals(DUK_FMOD(-0.0, 1.0), 0.0) && DUK_SIGNBIT(DUK_FMOD(-0.0, 1.0)) != 0);
64759 	DUK_ASSERT(duk_double_equals(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY), 0.0) && DUK_SIGNBIT(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY)) == 0);
64760 	DUK_ASSERT(duk_double_equals(DUK_FMOD(-0.0, DUK_DOUBLE_INFINITY), 0.0) && DUK_SIGNBIT(DUK_FMOD(-0.0, DUK_DOUBLE_INFINITY)) != 0);
64761 	DUK_ASSERT(duk_double_equals(DUK_FMOD(0.0, -DUK_DOUBLE_INFINITY), 0.0) && DUK_SIGNBIT(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY)) == 0);
64762 	DUK_ASSERT(duk_double_equals(DUK_FMOD(-0.0, -DUK_DOUBLE_INFINITY), 0.0) && DUK_SIGNBIT(DUK_FMOD(-0.0, -DUK_DOUBLE_INFINITY)) != 0);
64763 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, 0.0)));
64764 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-0.0, 0.0)));
64765 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, -0.0)));
64766 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-0.0, -0.0)));
64767 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, DUK_DOUBLE_NAN)));
64768 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-0.0, DUK_DOUBLE_NAN)));
64769 #endif
64770 
64771 	return (duk_double_t) DUK_FMOD((double) d1, (double) d2);
64772 }
64773 
64774 /* Shared helper for Math.pow() and exponentiation operator. */
64775 DUK_INTERNAL double duk_js_arith_pow(double x, double y) {
64776 	/* The ANSI C pow() semantics differ from ECMAScript.
64777 	 *
64778 	 * E.g. when x==1 and y is +/- infinite, the ECMAScript required
64779 	 * result is NaN, while at least Linux pow() returns 1.
64780 	 */
64781 
64782 	duk_small_int_t cx, cy, sx;
64783 
64784 	DUK_UNREF(cx);
64785 	DUK_UNREF(sx);
64786 	cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
64787 
64788 	if (cy == DUK_FP_NAN) {
64789 		goto ret_nan;
64790 	}
64791 	if (duk_double_equals(DUK_FABS(x), 1.0) && cy == DUK_FP_INFINITE) {
64792 		goto ret_nan;
64793 	}
64794 
64795 #if defined(DUK_USE_POW_WORKAROUNDS)
64796 	/* Specific fixes to common pow() implementation issues:
64797 	 *   - test-bug-netbsd-math-pow.js: NetBSD 6.0 on x86 (at least)
64798 	 *   - test-bug-mingw-math-issues.js
64799 	 */
64800 	cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
64801 	if (cx == DUK_FP_ZERO && y < 0.0) {
64802 		sx = (duk_small_int_t) DUK_SIGNBIT(x);
64803 		if (sx == 0) {
64804 			/* Math.pow(+0,y) should be Infinity when y<0.  NetBSD pow()
64805 			 * returns -Infinity instead when y is <0 and finite.  The
64806 			 * if-clause also catches y == -Infinity (which works even
64807 			 * without the fix).
64808 			 */
64809 			return DUK_DOUBLE_INFINITY;
64810 		} else {
64811 			/* Math.pow(-0,y) where y<0 should be:
64812 			 *   - -Infinity if y<0 and an odd integer
64813 			 *   - Infinity if y<0 but not an odd integer
64814 			 * NetBSD pow() returns -Infinity for all finite y<0.  The
64815 			 * if-clause also catches y == -Infinity (which works even
64816 			 * without the fix).
64817 			 */
64818 
64819 			/* fmod() return value has same sign as input (negative) so
64820 			 * the result here will be in the range ]-2,0], -1 indicates
64821 			 * odd.  If x is -Infinity, NaN is returned and the odd check
64822 			 * always concludes "not odd" which results in desired outcome.
64823 			 */
64824 			double tmp = DUK_FMOD(y, 2);
64825 			if (tmp == -1.0) {
64826 				return -DUK_DOUBLE_INFINITY;
64827 			} else {
64828 				/* Not odd, or y == -Infinity */
64829 				return DUK_DOUBLE_INFINITY;
64830 			}
64831 		}
64832 	} else if (cx == DUK_FP_NAN) {
64833 		if (duk_double_equals(y, 0.0)) {
64834 			/* NaN ** +/- 0 should always be 1, but is NaN on
64835 			 * at least some Cygwin/MinGW versions.
64836 			 */
64837 			return 1.0;
64838 		}
64839 	}
64840 #else
64841 	/* Some ISO C assumptions. */
64842 	DUK_ASSERT(duk_double_equals(DUK_POW(DUK_DOUBLE_NAN, 0.0), 1.0));
64843 	DUK_ASSERT(DUK_ISINF(DUK_POW(0.0, -1.0)) && DUK_SIGNBIT(DUK_POW(0.0, -1.0)) == 0);
64844 	DUK_ASSERT(DUK_ISINF(DUK_POW(-0.0, -2.0)) && DUK_SIGNBIT(DUK_POW(-0.0, -2.0)) == 0);
64845 	DUK_ASSERT(DUK_ISINF(DUK_POW(-0.0, -3.0)) && DUK_SIGNBIT(DUK_POW(-0.0, -3.0)) != 0);
64846 #endif
64847 
64848 	return DUK_POW(x, y);
64849 
64850  ret_nan:
64851 	return DUK_DOUBLE_NAN;
64852 }
64853 /*
64854  *  Call handling.
64855  *
64856  *  duk_handle_call_unprotected():
64857  *
64858  *    - Unprotected call to ECMAScript or Duktape/C function, from native
64859  *      code or bytecode executor.
64860  *
64861  *    - Also handles Ecma-to-Ecma calls which reuses a currently running
64862  *      executor instance to avoid native recursion.  Call setup is done
64863  *      normally, but just before calling the bytecode executor a special
64864  *      return code is used to indicate that a calling executor is reused.
64865  *
64866  *    - Also handles tailcalls, i.e. reuse of current duk_activation.
64867  *
64868  *    - Also handles setup for initial Duktape.Thread.resume().
64869  *
64870  *  duk_handle_safe_call():
64871  *
64872  *    - Protected C call within current activation.
64873  *
64874  *  setjmp() and local variables have a nasty interaction, see execution.rst;
64875  *  non-volatile locals modified after setjmp() call are not guaranteed to
64876  *  keep their value and can cause compiler or compiler version specific
64877  *  difficult to replicate issues.
64878  *
64879  *  See 'execution.rst'.
64880  */
64881 
64882 /* #include duk_internal.h -> already included */
64883 
64884 /* XXX: heap->error_not_allowed for success path too? */
64885 
64886 /*
64887  *  Limit check helpers.
64888  */
64889 
64890 /* Check native stack space if DUK_USE_NATIVE_STACK_CHECK() defined. */
64891 DUK_INTERNAL void duk_native_stack_check(duk_hthread *thr) {
64892 #if defined(DUK_USE_NATIVE_STACK_CHECK)
64893 	if (DUK_USE_NATIVE_STACK_CHECK() != 0) {
64894 		DUK_ERROR_RANGE(thr, DUK_STR_NATIVE_STACK_LIMIT);
64895 	}
64896 #else
64897 	DUK_UNREF(thr);
64898 #endif
64899 }
64900 
64901 /* Allow headroom for calls during error augmentation (see GH-191).
64902  * We allow space for 10 additional recursions, with one extra
64903  * for, e.g. a print() call at the deepest level, and an extra
64904  * +1 for protected call wrapping.
64905  */
64906 #define DUK__AUGMENT_CALL_RELAX_COUNT  (10 + 2)
64907 
64908 /* Stack space required by call handling entry. */
64909 #define DUK__CALL_HANDLING_REQUIRE_STACK  8
64910 
64911 DUK_LOCAL DUK_NOINLINE void duk__call_c_recursion_limit_check_slowpath(duk_hthread *thr) {
64912 	/* When augmenting an error, the effective limit is a bit higher.
64913 	 * Check for it only if the fast path check fails.
64914 	 */
64915 #if defined(DUK_USE_AUGMENT_ERROR_THROW) || defined(DUK_USE_AUGMENT_ERROR_CREATE)
64916 	if (thr->heap->augmenting_error) {
64917 		if (thr->heap->call_recursion_depth < thr->heap->call_recursion_limit + DUK__AUGMENT_CALL_RELAX_COUNT) {
64918 			DUK_D(DUK_DPRINT("C recursion limit reached but augmenting error and within relaxed limit"));
64919 			return;
64920 		}
64921 	}
64922 #endif
64923 
64924 	DUK_D(DUK_DPRINT("call prevented because C recursion limit reached"));
64925 	DUK_ERROR_RANGE(thr, DUK_STR_NATIVE_STACK_LIMIT);
64926 	DUK_WO_NORETURN(return;);
64927 }
64928 
64929 DUK_LOCAL DUK_ALWAYS_INLINE void duk__call_c_recursion_limit_check(duk_hthread *thr) {
64930 	DUK_ASSERT(thr->heap->call_recursion_depth >= 0);
64931 	DUK_ASSERT(thr->heap->call_recursion_depth <= thr->heap->call_recursion_limit);
64932 
64933 	duk_native_stack_check(thr);
64934 
64935 	/* This check is forcibly inlined because it's very cheap and almost
64936 	 * always passes.  The slow path is forcibly noinline.
64937 	 */
64938 	if (DUK_LIKELY(thr->heap->call_recursion_depth < thr->heap->call_recursion_limit)) {
64939 		return;
64940 	}
64941 
64942 	duk__call_c_recursion_limit_check_slowpath(thr);
64943 }
64944 
64945 DUK_LOCAL DUK_NOINLINE void duk__call_callstack_limit_check_slowpath(duk_hthread *thr) {
64946 	/* When augmenting an error, the effective limit is a bit higher.
64947 	 * Check for it only if the fast path check fails.
64948 	 */
64949 #if defined(DUK_USE_AUGMENT_ERROR_THROW) || defined(DUK_USE_AUGMENT_ERROR_CREATE)
64950 	if (thr->heap->augmenting_error) {
64951 		if (thr->callstack_top < DUK_USE_CALLSTACK_LIMIT + DUK__AUGMENT_CALL_RELAX_COUNT) {
64952 			DUK_D(DUK_DPRINT("call stack limit reached but augmenting error and within relaxed limit"));
64953 			return;
64954 		}
64955 	}
64956 #endif
64957 
64958 	/* XXX: error message is a bit misleading: we reached a recursion
64959 	 * limit which is also essentially the same as a C callstack limit
64960 	 * (except perhaps with some relaxed threading assumptions).
64961 	 */
64962 	DUK_D(DUK_DPRINT("call prevented because call stack limit reached"));
64963 	DUK_ERROR_RANGE(thr, DUK_STR_CALLSTACK_LIMIT);
64964 	DUK_WO_NORETURN(return;);
64965 }
64966 
64967 DUK_LOCAL DUK_ALWAYS_INLINE void duk__call_callstack_limit_check(duk_hthread *thr) {
64968 	/* This check is forcibly inlined because it's very cheap and almost
64969 	 * always passes.  The slow path is forcibly noinline.
64970 	 */
64971 	if (DUK_LIKELY(thr->callstack_top < DUK_USE_CALLSTACK_LIMIT)) {
64972 		return;
64973 	}
64974 
64975 	duk__call_callstack_limit_check_slowpath(thr);
64976 }
64977 
64978 /*
64979  *  Interrupt counter fixup (for development only).
64980  */
64981 
64982 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
64983 DUK_LOCAL void duk__interrupt_fixup(duk_hthread *thr, duk_hthread *entry_curr_thread) {
64984 	/* Currently the bytecode executor and executor interrupt
64985 	 * instruction counts are off because we don't execute the
64986 	 * interrupt handler when we're about to exit from the initial
64987 	 * user call into Duktape.
64988 	 *
64989 	 * If we were to execute the interrupt handler here, the counts
64990 	 * would match.  You can enable this block manually to check
64991 	 * that this is the case.
64992 	 */
64993 
64994 	DUK_ASSERT(thr != NULL);
64995 	DUK_ASSERT(thr->heap != NULL);
64996 
64997 #if defined(DUK_USE_INTERRUPT_DEBUG_FIXUP)
64998 	if (entry_curr_thread == NULL) {
64999 		thr->interrupt_init = thr->interrupt_init - thr->interrupt_counter;
65000 		thr->heap->inst_count_interrupt += thr->interrupt_init;
65001 		DUK_DD(DUK_DDPRINT("debug test: updated interrupt count on exit to "
65002 		                   "user code, instruction counts: executor=%ld, interrupt=%ld",
65003 		                   (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt));
65004 		DUK_ASSERT(thr->heap->inst_count_exec == thr->heap->inst_count_interrupt);
65005 	}
65006 #else
65007 	DUK_UNREF(thr);
65008 	DUK_UNREF(entry_curr_thread);
65009 #endif
65010 }
65011 #endif
65012 
65013 /*
65014  *  Arguments object creation.
65015  *
65016  *  Creating arguments objects involves many small details, see E5 Section
65017  *  10.6 for the specific requirements.  Much of the arguments object exotic
65018  *  behavior is implemented in duk_hobject_props.c, and is enabled by the
65019  *  object flag DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS.
65020  */
65021 
65022 DUK_LOCAL void duk__create_arguments_object(duk_hthread *thr,
65023                                             duk_hobject *func,
65024                                             duk_hobject *varenv,
65025                                             duk_idx_t idx_args) {
65026 	duk_hobject *arg;          /* 'arguments' */
65027 	duk_hobject *formals;      /* formals for 'func' (may be NULL if func is a C function) */
65028 	duk_idx_t i_arg;
65029 	duk_idx_t i_map;
65030 	duk_idx_t i_mappednames;
65031 	duk_idx_t i_formals;
65032 	duk_idx_t i_argbase;
65033 	duk_idx_t n_formals;
65034 	duk_idx_t idx;
65035 	duk_idx_t num_stack_args;
65036 	duk_bool_t need_map;
65037 
65038 	DUK_ASSERT(thr != NULL);
65039 	DUK_ASSERT(func != NULL);
65040 	DUK_ASSERT(DUK_HOBJECT_IS_NONBOUND_FUNCTION(func));
65041 	DUK_ASSERT(varenv != NULL);
65042 
65043 	/* [ ... func this arg1(@idx_args) ... argN envobj ]
65044 	 * [ arg1(@idx_args) ... argN envobj ] (for tailcalls)
65045 	 */
65046 
65047 	need_map = 0;
65048 
65049 	i_argbase = idx_args;
65050 	num_stack_args = duk_get_top(thr) - i_argbase - 1;
65051 	DUK_ASSERT(i_argbase >= 0);
65052 	DUK_ASSERT(num_stack_args >= 0);
65053 
65054 	formals = (duk_hobject *) duk_hobject_get_formals(thr, (duk_hobject *) func);
65055 	if (formals) {
65056 		n_formals = (duk_idx_t) ((duk_harray *) formals)->length;
65057 		duk_push_hobject(thr, formals);
65058 	} else {
65059 		/* This shouldn't happen without tampering of internal
65060 		 * properties: if a function accesses 'arguments', _Formals
65061 		 * is kept.  Check for the case anyway in case internal
65062 		 * properties have been modified manually.
65063 		 */
65064 		DUK_D(DUK_DPRINT("_Formals is undefined when creating arguments, use n_formals == 0"));
65065 		n_formals = 0;
65066 		duk_push_undefined(thr);
65067 	}
65068 	i_formals = duk_require_top_index(thr);
65069 
65070 	DUK_ASSERT(n_formals >= 0);
65071 	DUK_ASSERT(formals != NULL || n_formals == 0);
65072 
65073 	DUK_DDD(DUK_DDDPRINT("func=%!O, formals=%!O, n_formals=%ld",
65074 	                     (duk_heaphdr *) func, (duk_heaphdr *) formals,
65075 	                     (long) n_formals));
65076 
65077 	/* [ ... formals ] */
65078 
65079 	/*
65080 	 *  Create required objects:
65081 	 *    - 'arguments' object: array-like, but not an array
65082 	 *    - 'map' object: internal object, tied to 'arguments' (bare)
65083 	 *    - 'mappedNames' object: temporary value used during construction (bare)
65084 	 */
65085 
65086 	arg = duk_push_object_helper(thr,
65087 	                             DUK_HOBJECT_FLAG_EXTENSIBLE |
65088 	                             DUK_HOBJECT_FLAG_FASTREFS |
65089 	                             DUK_HOBJECT_FLAG_ARRAY_PART |
65090 	                             DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARGUMENTS),
65091 	                             DUK_BIDX_OBJECT_PROTOTYPE);
65092 	DUK_ASSERT(arg != NULL);
65093 	(void) duk_push_object_helper(thr,
65094 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
65095 	                              DUK_HOBJECT_FLAG_FASTREFS |
65096 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
65097 	                              -1);  /* no prototype */
65098 	(void) duk_push_object_helper(thr,
65099 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
65100 	                              DUK_HOBJECT_FLAG_FASTREFS |
65101 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
65102 	                              -1);  /* no prototype */
65103 	i_arg = duk_get_top(thr) - 3;
65104 	i_map = i_arg + 1;
65105 	i_mappednames = i_arg + 2;
65106 	DUK_ASSERT(!duk_is_bare_object(thr, -3));  /* arguments */
65107 	DUK_ASSERT(duk_is_bare_object(thr, -2));  /* map */
65108 	DUK_ASSERT(duk_is_bare_object(thr, -1));  /* mappedNames */
65109 
65110 	/* [ ... formals arguments map mappedNames ] */
65111 
65112 	DUK_DDD(DUK_DDDPRINT("created arguments related objects: "
65113 	                     "arguments at index %ld -> %!O "
65114 	                     "map at index %ld -> %!O "
65115 	                     "mappednames at index %ld -> %!O",
65116 	                     (long) i_arg, (duk_heaphdr *) duk_get_hobject(thr, i_arg),
65117 	                     (long) i_map, (duk_heaphdr *) duk_get_hobject(thr, i_map),
65118 	                     (long) i_mappednames, (duk_heaphdr *) duk_get_hobject(thr, i_mappednames)));
65119 
65120 	/*
65121 	 *  Init arguments properties, map, etc.
65122 	 */
65123 
65124 	duk_push_int(thr, num_stack_args);
65125 	duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_WC);
65126 
65127 	/*
65128 	 *  Init argument related properties.
65129 	 */
65130 
65131 	/* step 11 */
65132 	idx = num_stack_args - 1;
65133 	while (idx >= 0) {
65134 		DUK_DDD(DUK_DDDPRINT("arg idx %ld, argbase=%ld, argidx=%ld",
65135 		                     (long) idx, (long) i_argbase, (long) (i_argbase + idx)));
65136 
65137 		DUK_DDD(DUK_DDDPRINT("define arguments[%ld]=arg", (long) idx));
65138 		duk_dup(thr, i_argbase + idx);
65139 		duk_xdef_prop_index_wec(thr, i_arg, (duk_uarridx_t) idx);
65140 		DUK_DDD(DUK_DDDPRINT("defined arguments[%ld]=arg", (long) idx));
65141 
65142 		/* step 11.c is relevant only if non-strict (checked in 11.c.ii) */
65143 		if (!DUK_HOBJECT_HAS_STRICT(func) && idx < n_formals) {
65144 			DUK_ASSERT(formals != NULL);
65145 
65146 			DUK_DDD(DUK_DDDPRINT("strict function, index within formals (%ld < %ld)",
65147 			                     (long) idx, (long) n_formals));
65148 
65149 			duk_get_prop_index(thr, i_formals, (duk_uarridx_t) idx);
65150 			DUK_ASSERT(duk_is_string(thr, -1));
65151 
65152 			duk_dup_top(thr);  /* [ ... name name ] */
65153 
65154 			if (!duk_has_prop(thr, i_mappednames)) {
65155 				/* steps 11.c.ii.1 - 11.c.ii.4, but our internal book-keeping
65156 				 * differs from the reference model
65157 				 */
65158 
65159 				/* [ ... name ] */
65160 
65161 				need_map = 1;
65162 
65163 				DUK_DDD(DUK_DDDPRINT("set mappednames[%s]=%ld",
65164 				                     (const char *) duk_get_string(thr, -1),
65165 				                     (long) idx));
65166 				duk_dup_top(thr);                      /* name */
65167 				(void) duk_push_uint_to_hstring(thr, (duk_uint_t) idx);  /* index */
65168 				duk_xdef_prop_wec(thr, i_mappednames);  /* out of spec, must be configurable */
65169 
65170 				DUK_DDD(DUK_DDDPRINT("set map[%ld]=%s",
65171 				                     (long) idx,
65172 				                     duk_get_string(thr, -1)));
65173 				duk_dup_top(thr);         /* name */
65174 				duk_xdef_prop_index_wec(thr, i_map, (duk_uarridx_t) idx);  /* out of spec, must be configurable */
65175 			} else {
65176 				/* duk_has_prop() popped the second 'name' */
65177 			}
65178 
65179 			/* [ ... name ] */
65180 			duk_pop(thr);  /* pop 'name' */
65181 		}
65182 
65183 		idx--;
65184 	}
65185 
65186 	DUK_DDD(DUK_DDDPRINT("actual arguments processed"));
65187 
65188 	/* step 12 */
65189 	if (need_map) {
65190 		DUK_DDD(DUK_DDDPRINT("adding 'map' and 'varenv' to arguments object"));
65191 
65192 		/* should never happen for a strict callee */
65193 		DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(func));
65194 
65195 		duk_dup(thr, i_map);
65196 		duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_INT_MAP, DUK_PROPDESC_FLAGS_NONE);  /* out of spec, don't care */
65197 
65198 		/* The variable environment for magic variable bindings needs to be
65199 		 * given by the caller and recorded in the arguments object.
65200 		 *
65201 		 * See E5 Section 10.6, the creation of setters/getters.
65202 		 *
65203 		 * The variable environment also provides access to the callee, so
65204 		 * an explicit (internal) callee property is not needed.
65205 		 */
65206 
65207 		duk_push_hobject(thr, varenv);
65208 		duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_INT_VARENV, DUK_PROPDESC_FLAGS_NONE);  /* out of spec, don't care */
65209 	}
65210 
65211 	/* steps 13-14 */
65212 	if (DUK_HOBJECT_HAS_STRICT(func)) {
65213 		/* Callee/caller are throwers and are not deletable etc.  They
65214 		 * could be implemented as virtual properties, but currently
65215 		 * there is no support for virtual properties which are accessors
65216 		 * (only plain virtual properties).  This would not be difficult
65217 		 * to change in duk_hobject_props, but we can make the throwers
65218 		 * normal, concrete properties just as easily.
65219 		 *
65220 		 * Note that the specification requires that the *same* thrower
65221 		 * built-in object is used here!  See E5 Section 10.6 main
65222 		 * algoritm, step 14, and Section 13.2.3 which describes the
65223 		 * thrower.  See test case test-arguments-throwers.js.
65224 		 */
65225 
65226 		DUK_DDD(DUK_DDDPRINT("strict function, setting caller/callee to throwers"));
65227 
65228 		/* In ES2017 .caller is no longer set at all. */
65229 		duk_xdef_prop_stridx_thrower(thr, i_arg, DUK_STRIDX_CALLEE);
65230 	} else {
65231 		DUK_DDD(DUK_DDDPRINT("non-strict function, setting callee to actual value"));
65232 		duk_push_hobject(thr, func);
65233 		duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_CALLEE, DUK_PROPDESC_FLAGS_WC);
65234 	}
65235 
65236 	/* set exotic behavior only after we're done */
65237 	if (need_map) {
65238 		/* Exotic behaviors are only enabled for arguments objects
65239 		 * which have a parameter map (see E5 Section 10.6 main
65240 		 * algorithm, step 12).
65241 		 *
65242 		 * In particular, a non-strict arguments object with no
65243 		 * mapped formals does *NOT* get exotic behavior, even
65244 		 * for e.g. "caller" property.  This seems counterintuitive
65245 		 * but seems to be the case.
65246 		 */
65247 
65248 		/* cannot be strict (never mapped variables) */
65249 		DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(func));
65250 
65251 		DUK_DDD(DUK_DDDPRINT("enabling exotic behavior for arguments object"));
65252 		DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(arg);
65253 	} else {
65254 		DUK_DDD(DUK_DDDPRINT("not enabling exotic behavior for arguments object"));
65255 	}
65256 
65257 	DUK_DDD(DUK_DDDPRINT("final arguments related objects: "
65258 	                     "arguments at index %ld -> %!O "
65259 	                     "map at index %ld -> %!O "
65260 	                     "mappednames at index %ld -> %!O",
65261 	                     (long) i_arg, (duk_heaphdr *) duk_get_hobject(thr, i_arg),
65262 	                     (long) i_map, (duk_heaphdr *) duk_get_hobject(thr, i_map),
65263 	                     (long) i_mappednames, (duk_heaphdr *) duk_get_hobject(thr, i_mappednames)));
65264 
65265 	/* [ args(n) envobj formals arguments map mappednames ] */
65266 
65267 	duk_pop_2(thr);
65268 	duk_remove_m2(thr);
65269 
65270 	/* [ args(n) envobj arguments ] */
65271 }
65272 
65273 /* Helper for creating the arguments object and adding it to the env record
65274  * on top of the value stack.
65275  */
65276 DUK_LOCAL void duk__handle_createargs_for_call(duk_hthread *thr,
65277                                                duk_hobject *func,
65278                                                duk_hobject *env,
65279                                                duk_idx_t idx_args) {
65280 	DUK_DDD(DUK_DDDPRINT("creating arguments object for function call"));
65281 
65282 	DUK_ASSERT(thr != NULL);
65283 	DUK_ASSERT(func != NULL);
65284 	DUK_ASSERT(env != NULL);
65285 	DUK_ASSERT(DUK_HOBJECT_HAS_CREATEARGS(func));
65286 
65287 	/* [ ... arg1 ... argN envobj ] */
65288 
65289 	duk__create_arguments_object(thr,
65290 	                             func,
65291 	                             env,
65292 	                             idx_args);
65293 
65294 	/* [ ... arg1 ... argN envobj argobj ] */
65295 
65296 	duk_xdef_prop_stridx_short(thr,
65297 	                           -2,
65298 	                           DUK_STRIDX_LC_ARGUMENTS,
65299 	                           DUK_HOBJECT_HAS_STRICT(func) ? DUK_PROPDESC_FLAGS_E :   /* strict: non-deletable, non-writable */
65300 	                                                          DUK_PROPDESC_FLAGS_WE);  /* non-strict: non-deletable, writable */
65301 	/* [ ... arg1 ... argN envobj ] */
65302 }
65303 
65304 /*
65305  *  Helpers for constructor call handling.
65306  *
65307  *  There are two [[Construct]] operations in the specification:
65308  *
65309  *    - E5 Section 13.2.2: for Function objects
65310  *    - E5 Section 15.3.4.5.2: for "bound" Function objects
65311  *
65312  *  The chain of bound functions is resolved in Section 15.3.4.5.2,
65313  *  with arguments "piling up" until the [[Construct]] internal
65314  *  method is called on the final, actual Function object.  Note
65315  *  that the "prototype" property is looked up *only* from the
65316  *  final object, *before* calling the constructor.
65317  *
65318  *  Since Duktape 2.2 bound functions are represented with the
65319  *  duk_hboundfunc internal type, and bound function chains are
65320  *  collapsed when a bound function is created.  As a result, the
65321  *  direct target of a duk_hboundfunc is always non-bound and the
65322  *  this/argument lists have been resolved.
65323  *
65324  *  When constructing new Array instances, an unnecessary object is
65325  *  created and discarded now: the standard [[Construct]] creates an
65326  *  object, and calls the Array constructor.  The Array constructor
65327  *  returns an Array instance, which is used as the result value for
65328  *  the "new" operation; the object created before the Array constructor
65329  *  call is discarded.
65330  *
65331  *  This would be easy to fix, e.g. by knowing that the Array constructor
65332  *  will always create a replacement object and skip creating the fallback
65333  *  object in that case.
65334  */
65335 
65336 /* Update default instance prototype for constructor call. */
65337 DUK_LOCAL void duk__update_default_instance_proto(duk_hthread *thr, duk_idx_t idx_func) {
65338 	duk_hobject *proto;
65339 	duk_hobject *fallback;
65340 
65341 	DUK_ASSERT(duk_is_constructable(thr, idx_func));
65342 
65343 	duk_get_prop_stridx_short(thr, idx_func, DUK_STRIDX_PROTOTYPE);
65344 	proto = duk_get_hobject(thr, -1);
65345 	if (proto == NULL) {
65346 		DUK_DDD(DUK_DDDPRINT("constructor has no 'prototype' property, or value not an object "
65347 		                     "-> leave standard Object prototype as fallback prototype"));
65348 	} else {
65349 		DUK_DDD(DUK_DDDPRINT("constructor has 'prototype' property with object value "
65350 		                     "-> set fallback prototype to that value: %!iO", (duk_heaphdr *) proto));
65351 		/* Original fallback (default instance) is untouched when
65352 		 * resolving bound functions etc.
65353 		 */
65354 		fallback = duk_known_hobject(thr, idx_func + 1);
65355 		DUK_ASSERT(fallback != NULL);
65356 		DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, fallback, proto);
65357 	}
65358 	duk_pop(thr);
65359 }
65360 
65361 /* Postprocess: return value special handling, error augmentation. */
65362 DUK_INTERNAL void duk_call_construct_postprocess(duk_hthread *thr, duk_small_uint_t proxy_invariant) {
65363 	/* Use either fallback (default instance) or retval depending
65364 	 * on retval type.  Needs to be called before unwind because
65365 	 * the default instance is read from the current (immutable)
65366 	 * 'this' binding.
65367 	 *
65368 	 * For Proxy 'construct' calls the return value must be an
65369 	 * Object (we accept object-like values like buffers and
65370 	 * lightfuncs too).  If not, TypeError.
65371 	 */
65372 	if (duk_check_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT |
65373 	                                 DUK_TYPE_MASK_BUFFER |
65374 	                                 DUK_TYPE_MASK_LIGHTFUNC)) {
65375 		DUK_DDD(DUK_DDDPRINT("replacement value"));
65376 	} else {
65377 		if (DUK_UNLIKELY(proxy_invariant != 0U)) {
65378 			/* Proxy 'construct' return value invariant violated. */
65379 			DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr);
65380 			DUK_WO_NORETURN(return;);
65381 		}
65382 		/* XXX: direct value stack access */
65383 		duk_pop(thr);
65384 		duk_push_this(thr);
65385 	}
65386 
65387 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
65388 	/* Augment created errors upon creation, not when they are thrown or
65389 	 * rethrown.  __FILE__ and __LINE__ are not desirable here; the call
65390 	 * stack reflects the caller which is correct.  Skip topmost, unwound
65391 	 * activation when creating a traceback.  If thr->ptr_curr_pc was !=
65392 	 * NULL we'd need to sync the current PC so that the traceback comes
65393 	 * out right; however it is always synced here so just assert for it.
65394 	 */
65395 	DUK_ASSERT(thr->ptr_curr_pc == NULL);
65396 	duk_err_augment_error_create(thr, thr, NULL, 0, DUK_AUGMENT_FLAG_NOBLAME_FILELINE |
65397 	                                                DUK_AUGMENT_FLAG_SKIP_ONE);
65398 #endif
65399 }
65400 
65401 /*
65402  *  Helper for handling a bound function when a call is being made.
65403  *
65404  *  Assumes that bound function chains have been "collapsed" so that either
65405  *  the target is non-bound or there is one bound function that points to a
65406  *  nonbound target.
65407  *
65408  *  Prepends the bound arguments to the value stack (at idx_func + 2).
65409  *  The 'this' binding is also updated if necessary (at idx_func + 1).
65410  *  Note that for constructor calls the 'this' binding is never updated by
65411  *  [[BoundThis]].
65412  */
65413 
65414 DUK_LOCAL void duk__handle_bound_chain_for_call(duk_hthread *thr,
65415                                                 duk_idx_t idx_func,
65416                                                 duk_bool_t is_constructor_call) {
65417 	duk_tval *tv_func;
65418 	duk_hobject *func;
65419 	duk_idx_t len;
65420 
65421 	DUK_ASSERT(thr != NULL);
65422 
65423 	/* On entry, item at idx_func is a bound, non-lightweight function,
65424 	 * but we don't rely on that below.
65425 	 */
65426 
65427 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
65428 
65429 	tv_func = duk_require_tval(thr, idx_func);
65430 	DUK_ASSERT(tv_func != NULL);
65431 
65432 	if (DUK_TVAL_IS_OBJECT(tv_func)) {
65433 		func = DUK_TVAL_GET_OBJECT(tv_func);
65434 
65435 		/* XXX: separate helper function, out of fast path? */
65436 		if (DUK_HOBJECT_HAS_BOUNDFUNC(func)) {
65437 			duk_hboundfunc *h_bound;
65438 			duk_tval *tv_args;
65439 			duk_tval *tv_gap;
65440 
65441 			h_bound = (duk_hboundfunc *) (void *) func;
65442 			tv_args = h_bound->args;
65443 			len = h_bound->nargs;
65444 			DUK_ASSERT(len == 0 || tv_args != NULL);
65445 
65446 			DUK_DDD(DUK_DDDPRINT("bound function encountered, ptr=%p: %!T",
65447 			                     (void *) DUK_TVAL_GET_OBJECT(tv_func), tv_func));
65448 
65449 			/* [ ... func this arg1 ... argN ] */
65450 
65451 			if (is_constructor_call) {
65452 				/* See: tests/ecmascript/test-spec-bound-constructor.js */
65453 				DUK_DDD(DUK_DDDPRINT("constructor call: don't update this binding"));
65454 			} else {
65455 				/* XXX: duk_replace_tval */
65456 				duk_push_tval(thr, &h_bound->this_binding);
65457 				duk_replace(thr, idx_func + 1);  /* idx_this = idx_func + 1 */
65458 			}
65459 
65460 			/* [ ... func this arg1 ... argN ] */
65461 
65462 			duk_require_stack(thr, len);
65463 
65464 			tv_gap = duk_reserve_gap(thr, idx_func + 2, len);
65465 			duk_copy_tvals_incref(thr, tv_gap, tv_args, (duk_size_t) len);
65466 
65467 			/* [ ... func this <bound args> arg1 ... argN ] */
65468 
65469 			duk_push_tval(thr, &h_bound->target);
65470 			duk_replace(thr, idx_func);  /* replace in stack */
65471 
65472 			DUK_DDD(DUK_DDDPRINT("bound function handled, idx_func=%ld, curr func=%!T",
65473 			                     (long) idx_func, duk_get_tval(thr, idx_func)));
65474 		}
65475 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
65476 		/* Lightweight function: never bound, so terminate. */
65477 		;
65478 	} else {
65479 		/* Shouldn't happen, so ugly error is enough. */
65480 		DUK_ERROR_INTERNAL(thr);
65481 		DUK_WO_NORETURN(return;);
65482 	}
65483 
65484 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
65485 
65486 	DUK_DDD(DUK_DDDPRINT("final non-bound function is: %!T", duk_get_tval(thr, idx_func)));
65487 
65488 #if defined(DUK_USE_ASSERTIONS)
65489 	tv_func = duk_require_tval(thr, idx_func);
65490 	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func) || DUK_TVAL_IS_OBJECT(tv_func));
65491 	if (DUK_TVAL_IS_OBJECT(tv_func)) {
65492 		func = DUK_TVAL_GET_OBJECT(tv_func);
65493 		DUK_ASSERT(func != NULL);
65494 		DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));
65495 		DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func) ||
65496 		           DUK_HOBJECT_HAS_NATFUNC(func) ||
65497 		           DUK_HOBJECT_IS_PROXY(func));
65498 	}
65499 #endif
65500 }
65501 
65502 /*
65503  *  Helper for inline handling of .call(), .apply(), and .construct().
65504  */
65505 
65506 DUK_LOCAL duk_bool_t duk__handle_specialfuncs_for_call(duk_hthread *thr, duk_idx_t idx_func, duk_hobject *func, duk_small_uint_t *call_flags, duk_bool_t first) {
65507 #if defined(DUK_USE_ASSERTIONS)
65508 	duk_c_function natfunc;
65509 #endif
65510 	duk_tval *tv_args;
65511 
65512 	DUK_ASSERT(func != NULL);
65513 	DUK_ASSERT((*call_flags & DUK_CALL_FLAG_CONSTRUCT) == 0);  /* Caller. */
65514 
65515 #if defined(DUK_USE_ASSERTIONS)
65516 	natfunc = ((duk_hnatfunc *) func)->func;
65517 	DUK_ASSERT(natfunc != NULL);
65518 #endif
65519 
65520 	/* On every round of function resolution at least target function and
65521 	 * 'this' binding are set.  We can assume that here, and must guarantee
65522 	 * it on exit.  Value stack reserve is extended for bound function and
65523 	 * .apply() unpacking so we don't need to extend it here when we need a
65524 	 * few slots.
65525 	 */
65526 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
65527 
65528 	/* Handle native 'eval' specially.  A direct eval check is only made
65529 	 * for the first resolution attempt; e.g. a bound eval call is -not-
65530 	 * a direct eval call.
65531 	 */
65532 	if (DUK_UNLIKELY(((duk_hnatfunc *) func)->magic == 15)) {
65533 		/* For now no special handling except for direct eval
65534 		 * detection.
65535 		 */
65536 		DUK_ASSERT(((duk_hnatfunc *) func)->func == duk_bi_global_object_eval);
65537 		if (first && (*call_flags & DUK_CALL_FLAG_CALLED_AS_EVAL)) {
65538 			*call_flags = (*call_flags & ~DUK_CALL_FLAG_CALLED_AS_EVAL) | DUK_CALL_FLAG_DIRECT_EVAL;
65539 		}
65540 		DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
65541 		return 1;  /* stop resolving */
65542 	}
65543 
65544 	/* Handle special functions based on the DUK_HOBJECT_FLAG_SPECIAL_CALL
65545 	 * flag; their magic value is used for switch-case.
65546 	 *
65547 	 * NOTE: duk_unpack_array_like() reserves value stack space
65548 	 * for the result values (unlike most other value stack calls).
65549 	 */
65550 	switch (((duk_hnatfunc *) func)->magic) {
65551 	case 0: {  /* 0=Function.prototype.call() */
65552 		/* Value stack:
65553 		 * idx_func + 0: Function.prototype.call()  [removed]
65554 		 * idx_func + 1: this binding for .call (target function)
65555 		 * idx_func + 2: 1st argument to .call, desired 'this' binding
65556 		 * idx_func + 3: 2nd argument to .call, desired 1st argument for ultimate target
65557 		 * ...
65558 		 *
65559 		 * Remove idx_func + 0 to get:
65560 		 * idx_func + 0: target function
65561 		 * idx_func + 1: this binding
65562 		 * idx_func + 2: call arguments
65563 		 * ...
65564 		 */
65565 		DUK_ASSERT(natfunc == duk_bi_function_prototype_call);
65566 		duk_remove_unsafe(thr, idx_func);
65567 		tv_args = thr->valstack_bottom + idx_func + 2;
65568 		if (thr->valstack_top < tv_args) {
65569 			DUK_ASSERT(tv_args <= thr->valstack_end);
65570 			thr->valstack_top = tv_args;  /* at least target function and 'this' binding present */
65571 		}
65572 		break;
65573 	}
65574 	case 1: {  /* 1=Function.prototype.apply() */
65575 		/* Value stack:
65576 		 * idx_func + 0: Function.prototype.apply()  [removed]
65577 		 * idx_func + 1: this binding for .apply (target function)
65578 		 * idx_func + 2: 1st argument to .apply, desired 'this' binding
65579 		 * idx_func + 3: 2nd argument to .apply, argArray
65580 		 * [anything after this MUST be ignored]
65581 		 *
65582 		 * Remove idx_func + 0 and unpack the argArray to get:
65583 		 * idx_func + 0: target function
65584 		 * idx_func + 1: this binding
65585 		 * idx_func + 2: call arguments
65586 		 * ...
65587 		 */
65588 		DUK_ASSERT(natfunc == duk_bi_function_prototype_apply);
65589 		duk_remove_unsafe(thr, idx_func);
65590 		goto apply_shared;
65591 	}
65592 #if defined(DUK_USE_REFLECT_BUILTIN)
65593 	case 2: {  /* 2=Reflect.apply() */
65594 		/* Value stack:
65595 		 * idx_func + 0: Reflect.apply()  [removed]
65596 		 * idx_func + 1: this binding for .apply (ignored, usually Reflect)  [removed]
65597 		 * idx_func + 2: 1st argument to .apply, target function
65598 		 * idx_func + 3: 2nd argument to .apply, desired 'this' binding
65599 		 * idx_func + 4: 3rd argument to .apply, argArray
65600 		 * [anything after this MUST be ignored]
65601 		 *
65602 		 * Remove idx_func + 0 and idx_func + 1, and unpack the argArray to get:
65603 		 * idx_func + 0: target function
65604 		 * idx_func + 1: this binding
65605 		 * idx_func + 2: call arguments
65606 		 * ...
65607 		 */
65608 		DUK_ASSERT(natfunc == duk_bi_reflect_apply);
65609 		duk_remove_n_unsafe(thr, idx_func, 2);
65610 		goto apply_shared;
65611 	}
65612 	case 3: {  /* 3=Reflect.construct() */
65613 		/* Value stack:
65614 		 * idx_func + 0: Reflect.construct()  [removed]
65615 		 * idx_func + 1: this binding for .construct (ignored, usually Reflect)  [removed]
65616 		 * idx_func + 2: 1st argument to .construct, target function
65617 		 * idx_func + 3: 2nd argument to .construct, argArray
65618 		 * idx_func + 4: 3rd argument to .construct, newTarget
65619 		 * [anything after this MUST be ignored]
65620 		 *
65621 		 * Remove idx_func + 0 and idx_func + 1, unpack the argArray,
65622 		 * and insert default instance (prototype not yet updated), to get:
65623 		 * idx_func + 0: target function
65624 		 * idx_func + 1: this binding (default instance)
65625 		 * idx_func + 2: constructor call arguments
65626 		 * ...
65627 		 *
65628 		 * Call flags must be updated to reflect the fact that we're
65629 		 * now dealing with a constructor call, and e.g. the 'this'
65630 		 * binding cannot be overwritten if the target is bound.
65631 		 *
65632 		 * newTarget is checked but not yet passed onwards.
65633 		 */
65634 
65635 		duk_idx_t top;
65636 
65637 		DUK_ASSERT(natfunc == duk_bi_reflect_construct);
65638 		*call_flags |= DUK_CALL_FLAG_CONSTRUCT;
65639 		duk_remove_n_unsafe(thr, idx_func, 2);
65640 		top = duk_get_top(thr);
65641 		if (!duk_is_constructable(thr, idx_func)) {
65642 			/* Target constructability must be checked before
65643 			 * unpacking argArray (which may cause side effects).
65644 			 * Just return; caller will throw the error.
65645 			 */
65646 			duk_set_top_unsafe(thr, idx_func + 2);  /* satisfy asserts */
65647 			break;
65648 		}
65649 		duk_push_object(thr);
65650 		duk_insert(thr, idx_func + 1);  /* default instance */
65651 
65652 		/* [ ... func default_instance argArray newTarget? ] */
65653 
65654 		top = duk_get_top(thr);
65655 		if (top < idx_func + 3) {
65656 			/* argArray is a mandatory argument for Reflect.construct(). */
65657 			DUK_ERROR_TYPE_INVALID_ARGS(thr);
65658 			DUK_WO_NORETURN(return 0;);
65659 		}
65660 		if (top > idx_func + 3) {
65661 			if (!duk_strict_equals(thr, idx_func, idx_func + 3)) {
65662 				/* XXX: [[Construct]] newTarget currently unsupported */
65663 				DUK_ERROR_UNSUPPORTED(thr);
65664 				DUK_WO_NORETURN(return 0;);
65665 			}
65666 			duk_set_top_unsafe(thr, idx_func + 3);  /* remove any args beyond argArray */
65667 		}
65668 		DUK_ASSERT(duk_get_top(thr) == idx_func + 3);
65669 		DUK_ASSERT(duk_is_valid_index(thr, idx_func + 2));
65670 		(void) duk_unpack_array_like(thr, idx_func + 2);  /* XXX: should also remove target to be symmetric with duk_pack()? */
65671 		duk_remove(thr, idx_func + 2);
65672 		DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
65673 		break;
65674 	}
65675 #endif  /* DUK_USE_REFLECT_BUILTIN */
65676 	default: {
65677 		DUK_ASSERT(0);
65678 		DUK_UNREACHABLE();
65679 	}
65680 	}
65681 
65682 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
65683 	return 0;  /* keep resolving */
65684 
65685  apply_shared:
65686 	tv_args = thr->valstack_bottom + idx_func + 2;
65687 	if (thr->valstack_top <= tv_args) {
65688 		DUK_ASSERT(tv_args <= thr->valstack_end);
65689 		thr->valstack_top = tv_args;  /* at least target func and 'this' binding present */
65690 		/* No need to check for argArray. */
65691 	} else {
65692 		DUK_ASSERT(duk_get_top(thr) >= idx_func + 3);  /* idx_func + 2 covered above */
65693 		if (thr->valstack_top > tv_args + 1) {
65694 			duk_set_top_unsafe(thr, idx_func + 3);  /* remove any args beyond argArray */
65695 		}
65696 		DUK_ASSERT(duk_is_valid_index(thr, idx_func + 2));
65697 		if (!duk_is_callable(thr, idx_func)) {
65698 			/* Avoid unpack side effects if the target isn't callable.
65699 			 * Calling code will throw the actual error.
65700 			 */
65701 		} else {
65702 			(void) duk_unpack_array_like(thr, idx_func + 2);
65703 			duk_remove(thr, idx_func + 2);
65704 		}
65705 	}
65706 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
65707 	return 0;  /* keep resolving */
65708 }
65709 
65710 /*
65711  *  Helper for Proxy handling.
65712  */
65713 
65714 #if defined(DUK_USE_ES6_PROXY)
65715 DUK_LOCAL void duk__handle_proxy_for_call(duk_hthread *thr, duk_idx_t idx_func, duk_hproxy *h_proxy, duk_small_uint_t *call_flags) {
65716 	duk_bool_t rc;
65717 
65718 	/* Value stack:
65719 	 * idx_func + 0: Proxy object
65720 	 * idx_func + 1: this binding for call
65721 	 * idx_func + 2: 1st argument for call
65722 	 * idx_func + 3: 2nd argument for call
65723 	 * ...
65724 	 *
65725 	 * If Proxy doesn't have a trap for the call ('apply' or 'construct'),
65726 	 * replace Proxy object with target object.
65727 	 *
65728 	 * If we're dealing with a normal call and the Proxy has an 'apply'
65729 	 * trap, manipulate value stack to:
65730 	 *
65731 	 * idx_func + 0: trap
65732 	 * idx_func + 1: Proxy's handler
65733 	 * idx_func + 2: Proxy's target
65734 	 * idx_func + 3: this binding for call (from idx_func + 1)
65735 	 * idx_func + 4: call arguments packed to an array
65736 	 *
65737 	 * If we're dealing with a constructor call and the Proxy has a
65738 	 * 'construct' trap, manipulate value stack to:
65739 	 *
65740 	 * idx_func + 0: trap
65741 	 * idx_func + 1: Proxy's handler
65742 	 * idx_func + 2: Proxy's target
65743 	 * idx_func + 3: call arguments packed to an array
65744 	 * idx_func + 4: newTarget == Proxy object here
65745 	 *
65746 	 * As we don't yet have proper newTarget support, the newTarget at
65747 	 * idx_func + 3 is just the original constructor being called, i.e.
65748 	 * the Proxy object (not the target).  Note that the default instance
65749 	 * (original 'this' binding) is dropped and ignored.
65750 	 */
65751 
65752 	duk_push_hobject(thr, h_proxy->handler);
65753 	rc = duk_get_prop_stridx_short(thr, -1, (*call_flags & DUK_CALL_FLAG_CONSTRUCT) ? DUK_STRIDX_CONSTRUCT : DUK_STRIDX_APPLY);
65754 	if (rc == 0) {
65755 		/* Not found, continue to target.  If this is a construct
65756 		 * call, update default instance prototype using the Proxy,
65757 		 * not the target.
65758 		 */
65759 		if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
65760 			if (!(*call_flags & DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED)) {
65761 				*call_flags |= DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED;
65762 				duk__update_default_instance_proto(thr, idx_func);
65763 			}
65764 		}
65765 		duk_pop_2(thr);
65766 		duk_push_hobject(thr, h_proxy->target);
65767 		duk_replace(thr, idx_func);
65768 		return;
65769 	}
65770 
65771 	/* Here we must be careful not to replace idx_func while
65772 	 * h_proxy is still needed, otherwise h_proxy may become
65773 	 * dangling.  This could be improved e.g. using a
65774 	 * duk_pack_slice() with a freeform slice.
65775 	 */
65776 
65777 	/* Here:
65778 	 * idx_func + 0: Proxy object
65779 	 * idx_func + 1: this binding for call
65780 	 * idx_func + 2: 1st argument for call
65781 	 * idx_func + 3: 2nd argument for call
65782 	 * ...
65783 	 * idx_func + N: handler
65784 	 * idx_func + N + 1: trap
65785 	 */
65786 
65787 	duk_insert(thr, idx_func + 1);
65788 	duk_insert(thr, idx_func + 2);
65789 	duk_push_hobject(thr, h_proxy->target);
65790 	duk_insert(thr, idx_func + 3);
65791 	duk_pack(thr, duk_get_top(thr) - (idx_func + 5));
65792 	DUK_ASSERT(!duk_is_bare_object(thr, -1));
65793 
65794 	/* Here:
65795 	 * idx_func + 0: Proxy object
65796 	 * idx_func + 1: trap
65797 	 * idx_func + 2: Proxy's handler
65798 	 * idx_func + 3: Proxy's target
65799 	 * idx_func + 4: this binding for call
65800 	 * idx_func + 5: arguments array
65801 	 */
65802 	DUK_ASSERT(duk_get_top(thr) == idx_func + 6);
65803 
65804 	if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
65805 		*call_flags |= DUK_CALL_FLAG_CONSTRUCT_PROXY;  /* Enable 'construct' trap return invariant check. */
65806 		*call_flags &= ~(DUK_CALL_FLAG_CONSTRUCT);     /* Resume as non-constructor call to the trap. */
65807 
65808 		/* 'apply' args: target, thisArg, argArray
65809 		 * 'construct' args: target, argArray, newTarget
65810 		 */
65811 		duk_remove(thr, idx_func + 4);
65812 		duk_push_hobject(thr, (duk_hobject *) h_proxy);
65813 	}
65814 
65815 	/* Finalize value stack layout by removing Proxy reference. */
65816 	duk_remove(thr, idx_func);
65817 	h_proxy = NULL;  /* invalidated */
65818 	DUK_ASSERT(duk_get_top(thr) == idx_func + 5);
65819 }
65820 #endif  /* DUK_USE_ES6_PROXY */
65821 
65822 /*
65823  *  Helper for setting up var_env and lex_env of an activation,
65824  *  assuming it does NOT have the DUK_HOBJECT_FLAG_NEWENV flag.
65825  */
65826 
65827 DUK_LOCAL void duk__handle_oldenv_for_call(duk_hthread *thr,
65828                                            duk_hobject *func,
65829                                            duk_activation *act) {
65830 	duk_hcompfunc *f;
65831 	duk_hobject *h_lex;
65832 	duk_hobject *h_var;
65833 
65834 	DUK_ASSERT(thr != NULL);
65835 	DUK_ASSERT(func != NULL);
65836 	DUK_ASSERT(act != NULL);
65837 	DUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV(func));
65838 	DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(func));
65839 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(func));
65840 	DUK_UNREF(thr);
65841 
65842 	f = (duk_hcompfunc *) func;
65843 	h_lex = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);
65844 	h_var = DUK_HCOMPFUNC_GET_VARENV(thr->heap, f);
65845 	DUK_ASSERT(h_lex != NULL);  /* Always true for closures (not for templates) */
65846 	DUK_ASSERT(h_var != NULL);
65847 	act->lex_env = h_lex;
65848 	act->var_env = h_var;
65849 	DUK_HOBJECT_INCREF(thr, h_lex);
65850 	DUK_HOBJECT_INCREF(thr, h_var);
65851 }
65852 
65853 /*
65854  *  Helper for updating callee 'caller' property.
65855  */
65856 
65857 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
65858 DUK_LOCAL void duk__update_func_caller_prop(duk_hthread *thr, duk_hobject *func) {
65859 	duk_tval *tv_caller;
65860 	duk_hobject *h_tmp;
65861 	duk_activation *act_callee;
65862 	duk_activation *act_caller;
65863 
65864 	DUK_ASSERT(thr != NULL);
65865 	DUK_ASSERT(func != NULL);
65866 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));  /* bound chain resolved */
65867 	DUK_ASSERT(thr->callstack_top >= 1);
65868 
65869 	if (DUK_HOBJECT_HAS_STRICT(func)) {
65870 		/* Strict functions don't get their 'caller' updated. */
65871 		return;
65872 	}
65873 
65874 	DUK_ASSERT(thr->callstack_top > 0);
65875 	act_callee = thr->callstack_curr;
65876 	DUK_ASSERT(act_callee != NULL);
65877 	act_caller = (thr->callstack_top >= 2 ? act_callee->parent : NULL);
65878 
65879 	/* XXX: check .caller writability? */
65880 
65881 	/* Backup 'caller' property and update its value. */
65882 	tv_caller = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, func, DUK_STRIDX_CALLER);
65883 	if (tv_caller) {
65884 		/* If caller is global/eval code, 'caller' should be set to
65885 		 * 'null'.
65886 		 *
65887 		 * XXX: there is no exotic flag to infer this correctly now.
65888 		 * The NEWENV flag is used now which works as intended for
65889 		 * everything (global code, non-strict eval code, and functions)
65890 		 * except strict eval code.  Bound functions are never an issue
65891 		 * because 'func' has been resolved to a non-bound function.
65892 		 */
65893 
65894 		if (act_caller != NULL) {
65895 			/* act_caller->func may be NULL in some finalization cases,
65896 			 * just treat like we don't know the caller.
65897 			 */
65898 			if (act_caller->func && !DUK_HOBJECT_HAS_NEWENV(act_caller->func)) {
65899 				/* Setting to NULL causes 'caller' to be set to
65900 				 * 'null' as desired.
65901 				 */
65902 				act_caller = NULL;
65903 			}
65904 		}
65905 
65906 		if (DUK_TVAL_IS_OBJECT(tv_caller)) {
65907 			h_tmp = DUK_TVAL_GET_OBJECT(tv_caller);
65908 			DUK_ASSERT(h_tmp != NULL);
65909 			act_callee->prev_caller = h_tmp;
65910 
65911 			/* Previous value doesn't need refcount changes because its ownership
65912 			 * is transferred to prev_caller.
65913 			 */
65914 
65915 			if (act_caller != NULL) {
65916 				DUK_ASSERT(act_caller->func != NULL);
65917 				DUK_TVAL_SET_OBJECT(tv_caller, act_caller->func);
65918 				DUK_TVAL_INCREF(thr, tv_caller);
65919 			} else {
65920 				DUK_TVAL_SET_NULL(tv_caller);  /* no incref */
65921 			}
65922 		} else {
65923 			/* 'caller' must only take on 'null' or function value */
65924 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_caller));
65925 			DUK_ASSERT(act_callee->prev_caller == NULL);
65926 			if (act_caller != NULL && act_caller->func) {
65927 				/* Tolerate act_caller->func == NULL which happens in
65928 				 * some finalization cases; treat like unknown caller.
65929 				 */
65930 				DUK_TVAL_SET_OBJECT(tv_caller, act_caller->func);
65931 				DUK_TVAL_INCREF(thr, tv_caller);
65932 			} else {
65933 				DUK_TVAL_SET_NULL(tv_caller);  /* no incref */
65934 			}
65935 		}
65936 	}
65937 }
65938 #endif  /* DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */
65939 
65940 /*
65941  *  Shared helpers for resolving the final, non-bound target function of the
65942  *  call and the effective 'this' binding.  Resolves bound functions and
65943  *  applies .call(), .apply(), and .construct() inline.
65944  *
65945  *  Proxy traps are also handled inline so that if the target is a Proxy with
65946  *  a 'call' or 'construct' trap, the trap handler is called with a modified
65947  *  argument list.
65948  *
65949  *  Once the bound function / .call() / .apply() / .construct() sequence has
65950  *  been resolved, the value at idx_func + 1 may need coercion described in
65951  *  E5 Section 10.4.3.
65952  *
65953  *  A call that begins as a non-constructor call may be converted into a
65954  *  constructor call during the resolution process if Reflect.construct()
65955  *  is invoked.  This is handled by updating the caller's call_flags.
65956  *
65957  *  For global and eval code (E5 Sections 10.4.1 and 10.4.2), we assume
65958  *  that the caller has provided the correct 'this' binding explicitly
65959  *  when calling, i.e.:
65960  *
65961  *    - global code: this=global object
65962  *    - direct eval: this=copy from eval() caller's this binding
65963  *    - other eval:  this=global object
65964  *
65965  *  The 'this' coercion may cause a recursive function call with arbitrary
65966  *  side effects, because ToObject() may be called.
65967  */
65968 
65969 DUK_LOCAL DUK_INLINE void duk__coerce_nonstrict_this_binding(duk_hthread *thr, duk_idx_t idx_this) {
65970 	duk_tval *tv_this;
65971 	duk_hobject *obj_global;
65972 
65973 	tv_this = thr->valstack_bottom + idx_this;
65974 	switch (DUK_TVAL_GET_TAG(tv_this)) {
65975 	case DUK_TAG_OBJECT:
65976 		DUK_DDD(DUK_DDDPRINT("this binding: non-strict, object -> use directly"));
65977 		break;
65978 	case DUK_TAG_UNDEFINED:
65979 	case DUK_TAG_NULL:
65980 		DUK_DDD(DUK_DDDPRINT("this binding: non-strict, undefined/null -> use global object"));
65981 		obj_global = thr->builtins[DUK_BIDX_GLOBAL];
65982 		/* XXX: avoid this check somehow */
65983 		if (DUK_LIKELY(obj_global != NULL)) {
65984 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this));  /* no need to decref previous value */
65985 			DUK_TVAL_SET_OBJECT(tv_this, obj_global);
65986 			DUK_HOBJECT_INCREF(thr, obj_global);
65987 		} else {
65988 			/* This may only happen if built-ins are being "torn down".
65989 			 * This behavior is out of specification scope.
65990 			 */
65991 			DUK_D(DUK_DPRINT("this binding: wanted to use global object, but it is NULL -> using undefined instead"));
65992 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this));  /* no need to decref previous value */
65993 			DUK_TVAL_SET_UNDEFINED(tv_this);  /* nothing to incref */
65994 		}
65995 		break;
65996 	default:
65997 		/* Plain buffers and lightfuncs are object coerced.  Lightfuncs
65998 		 * very rarely come here however, because the call target would
65999 		 * need to be a non-strict non-lightfunc (lightfuncs are considered
66000 		 * strict) with an explicit lightfunc 'this' binding.
66001 		 */
66002 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_this));
66003 		DUK_DDD(DUK_DDDPRINT("this binding: non-strict, not object/undefined/null -> use ToObject(value)"));
66004 		duk_to_object(thr, idx_this);  /* may have side effects */
66005 		break;
66006 	}
66007 }
66008 
66009 DUK_LOCAL DUK_ALWAYS_INLINE duk_bool_t duk__resolve_target_fastpath_check(duk_hthread *thr, duk_idx_t idx_func, duk_hobject **out_func, duk_small_uint_t call_flags) {
66010 #if defined(DUK_USE_PREFER_SIZE)
66011 	DUK_UNREF(thr);
66012 	DUK_UNREF(idx_func);
66013 	DUK_UNREF(out_func);
66014 	DUK_UNREF(call_flags);
66015 #else  /* DUK_USE_PREFER_SIZE */
66016 	duk_tval *tv_func;
66017 	duk_hobject *func;
66018 
66019 	if (DUK_UNLIKELY(call_flags & DUK_CALL_FLAG_CONSTRUCT)) {
66020 		return 0;
66021 	}
66022 
66023 	tv_func = DUK_GET_TVAL_POSIDX(thr, idx_func);
66024 	DUK_ASSERT(tv_func != NULL);
66025 
66026 	if (DUK_LIKELY(DUK_TVAL_IS_OBJECT(tv_func))) {
66027 		func = DUK_TVAL_GET_OBJECT(tv_func);
66028 		if (DUK_HOBJECT_IS_CALLABLE(func) &&
66029 		    !DUK_HOBJECT_HAS_BOUNDFUNC(func) &&
66030 		    !DUK_HOBJECT_HAS_SPECIAL_CALL(func)) {
66031 			*out_func = func;
66032 
66033 			if (DUK_HOBJECT_HAS_STRICT(func)) {
66034 				/* Strict function: no 'this' coercion. */
66035 				return 1;
66036 			}
66037 
66038 			duk__coerce_nonstrict_this_binding(thr, idx_func + 1);
66039 			return 1;
66040 		}
66041 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
66042 		*out_func = NULL;
66043 
66044 		/* Lightfuncs are considered strict, so 'this' binding is
66045 		 * used as is.  They're never bound, always constructable,
66046 		 * and never special functions.
66047 		 */
66048 		return 1;
66049 	}
66050 #endif  /* DUK_USE_PREFER_SIZE */
66051 	return 0;  /* let slow path deal with it */
66052 }
66053 
66054 DUK_LOCAL duk_hobject *duk__resolve_target_func_and_this_binding(duk_hthread *thr,
66055                                                                  duk_idx_t idx_func,
66056                                                                  duk_small_uint_t *call_flags) {
66057 	duk_tval *tv_func;
66058 	duk_hobject *func;
66059 	duk_bool_t first;
66060 
66061 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
66062 
66063 	for (first = 1;; first = 0) {
66064 		DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
66065 
66066 		tv_func = DUK_GET_TVAL_POSIDX(thr, idx_func);
66067 		DUK_ASSERT(tv_func != NULL);
66068 
66069 		DUK_DD(DUK_DDPRINT("target func: %!iT", tv_func));
66070 
66071 		if (DUK_TVAL_IS_OBJECT(tv_func)) {
66072 			func = DUK_TVAL_GET_OBJECT(tv_func);
66073 
66074 			if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
66075 				if (DUK_UNLIKELY(!DUK_HOBJECT_HAS_CONSTRUCTABLE(func))) {
66076 					goto not_constructable;
66077 				}
66078 			} else {
66079 				if (DUK_UNLIKELY(!DUK_HOBJECT_IS_CALLABLE(func))) {
66080 					goto not_callable;
66081 				}
66082 			}
66083 
66084 			if (DUK_LIKELY(!DUK_HOBJECT_HAS_BOUNDFUNC(func) &&
66085 			               !DUK_HOBJECT_HAS_SPECIAL_CALL(func) &&
66086 			               !DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(func))) {
66087 				/* Common case, so test for using a single bitfield test.
66088 				 * Break out to handle this coercion etc.
66089 				 */
66090 				break;
66091 			}
66092 
66093 			/* XXX: could set specialcall for boundfuncs too, simplify check above */
66094 
66095 			if (DUK_HOBJECT_HAS_BOUNDFUNC(func)) {
66096 				DUK_ASSERT(!DUK_HOBJECT_HAS_SPECIAL_CALL(func));
66097 				DUK_ASSERT(!DUK_HOBJECT_IS_NATFUNC(func));
66098 
66099 				/* Callable/constructable flags are the same
66100 				 * for the bound function and its target, so
66101 				 * we don't need to check them here, we can
66102 				 * check them from the target only.
66103 				 */
66104 				duk__handle_bound_chain_for_call(thr, idx_func, *call_flags & DUK_CALL_FLAG_CONSTRUCT);
66105 
66106 				DUK_ASSERT(DUK_TVAL_IS_OBJECT(duk_require_tval(thr, idx_func)) ||
66107 				           DUK_TVAL_IS_LIGHTFUNC(duk_require_tval(thr, idx_func)));
66108 			} else {
66109 				DUK_ASSERT(DUK_HOBJECT_HAS_SPECIAL_CALL(func));
66110 
66111 #if defined(DUK_USE_ES6_PROXY)
66112 				if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(func)) {
66113 					/* If no trap, resume processing from Proxy trap.
66114 					 * If trap exists, helper converts call into a trap
66115 					 * call; this may change a constructor call into a
66116 					 * normal (non-constructor) trap call.  We must
66117 					 * continue processing even when a trap is found as
66118 					 * the trap may be bound.
66119 					 */
66120 					duk__handle_proxy_for_call(thr, idx_func, (duk_hproxy *) func, call_flags);
66121 				}
66122 				else
66123 #endif
66124 				{
66125 					DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(func));
66126 					DUK_ASSERT(DUK_HOBJECT_HAS_CALLABLE(func));
66127 					DUK_ASSERT(!DUK_HOBJECT_HAS_CONSTRUCTABLE(func));
66128 					/* Constructable check already done above. */
66129 
66130 					if (duk__handle_specialfuncs_for_call(thr, idx_func, func, call_flags, first) != 0) {
66131 						/* Encountered native eval call, normal call
66132 						 * context.  Break out, handle this coercion etc.
66133 						 */
66134 						break;
66135 					}
66136 				}
66137 			}
66138 			/* Retry loop. */
66139 		} else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
66140 			/* Lightfuncs are:
66141 			 *   - Always strict, so no 'this' coercion.
66142 			 *   - Always callable.
66143 			 *   - Always constructable.
66144 			 *   - Never specialfuncs.
66145 			 */
66146 			func = NULL;
66147 			goto finished;
66148 		} else {
66149 			goto not_callable;
66150 		}
66151 	}
66152 
66153 	DUK_ASSERT(func != NULL);
66154 
66155 	if (!DUK_HOBJECT_HAS_STRICT(func)) {
66156 		/* Non-strict target needs 'this' coercion.
66157 		 * This has potential side effects invalidating
66158 		 * 'tv_func'.
66159 		 */
66160 		duk__coerce_nonstrict_this_binding(thr, idx_func + 1);
66161 	}
66162 	if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
66163 		if (!(*call_flags & DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED)) {
66164 			*call_flags |= DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED;
66165 			duk__update_default_instance_proto(thr, idx_func);
66166 		}
66167 	}
66168 
66169  finished:
66170 
66171 #if defined(DUK_USE_ASSERTIONS)
66172 	{
66173 		duk_tval *tv_tmp;
66174 
66175 		tv_tmp = duk_get_tval(thr, idx_func);
66176 		DUK_ASSERT(tv_tmp != NULL);
66177 
66178 		DUK_ASSERT((DUK_TVAL_IS_OBJECT(tv_tmp) && DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(tv_tmp))) ||
66179 		           DUK_TVAL_IS_LIGHTFUNC(tv_tmp));
66180 		DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));
66181 		DUK_ASSERT(func == NULL || (DUK_HOBJECT_IS_COMPFUNC(func) ||
66182 		                            DUK_HOBJECT_IS_NATFUNC(func)));
66183 		DUK_ASSERT(func == NULL || (DUK_HOBJECT_HAS_CONSTRUCTABLE(func) ||
66184 		                            (*call_flags & DUK_CALL_FLAG_CONSTRUCT) == 0));
66185 	}
66186 #endif
66187 
66188 	return func;
66189 
66190  not_callable:
66191 	DUK_ASSERT(tv_func != NULL);
66192 
66193 #if defined(DUK_USE_VERBOSE_ERRORS)
66194 	/* GETPROPC delayed error handling: when target is not callable,
66195 	 * GETPROPC replaces idx_func+0 with a non-callable wrapper object
66196 	 * with a hidden Symbol to signify it's to be handled here.  If
66197 	 * found, unwrap the original Error and throw it as is here.  The
66198 	 * hidden Symbol is only checked as an own property, not inherited
66199 	 * (which would be dangerous).
66200 	 */
66201 	if (DUK_TVAL_IS_OBJECT(tv_func)) {
66202 		duk_tval *tv_wrap = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, DUK_TVAL_GET_OBJECT(tv_func), DUK_STRIDX_INT_TARGET);
66203 		if (tv_wrap != NULL) {
66204 			DUK_DD(DUK_DDPRINT("delayed error from GETPROPC: %!T", tv_wrap));
66205 			duk_push_tval(thr, tv_wrap);
66206 			(void) duk_throw(thr);
66207 			DUK_WO_NORETURN(return NULL;);
66208 		}
66209 	}
66210 #endif
66211 
66212 #if defined(DUK_USE_VERBOSE_ERRORS)
66213 #if defined(DUK_USE_PARANOID_ERRORS)
66214 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not callable", duk_get_type_name(thr, idx_func));
66215 #else
66216 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not callable", duk_push_string_tval_readable(thr, tv_func));
66217 #endif
66218 #else
66219 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);
66220 #endif
66221 	DUK_WO_NORETURN(return NULL;);
66222 
66223  not_constructable:
66224 	/* For now GETPROPC delayed error not needed for constructor calls. */
66225 #if defined(DUK_USE_VERBOSE_ERRORS)
66226 #if defined(DUK_USE_PARANOID_ERRORS)
66227 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not constructable", duk_get_type_name(thr, idx_func));
66228 #else
66229 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not constructable", duk_push_string_tval_readable(thr, tv_func));
66230 #endif
66231 #else
66232 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONSTRUCTABLE);
66233 #endif
66234 	DUK_WO_NORETURN(return NULL;);
66235 }
66236 
66237 /*
66238  *  Manipulate value stack so that exactly 'num_stack_rets' return
66239  *  values are at 'idx_retbase' in every case, assuming there are
66240  *  'rc' return values on top of stack.
66241  *
66242  *  This is a bit tricky, because the called C function operates in
66243  *  the same activation record and may have e.g. popped the stack
66244  *  empty (below idx_retbase).
66245  */
66246 
66247 DUK_LOCAL void duk__safe_call_adjust_valstack(duk_hthread *thr, duk_idx_t idx_retbase, duk_idx_t num_stack_rets, duk_idx_t num_actual_rets) {
66248 	duk_idx_t idx_rcbase;
66249 
66250 	DUK_ASSERT(thr != NULL);
66251 	DUK_ASSERT(idx_retbase >= 0);
66252 	DUK_ASSERT(num_stack_rets >= 0);
66253 	DUK_ASSERT(num_actual_rets >= 0);
66254 
66255 	idx_rcbase = duk_get_top(thr) - num_actual_rets;  /* base of known return values */
66256 	if (DUK_UNLIKELY(idx_rcbase < 0)) {
66257 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_CFUNC_RC);
66258 		DUK_WO_NORETURN(return;);
66259 	}
66260 
66261 	DUK_DDD(DUK_DDDPRINT("adjust valstack after func call: "
66262 	                     "num_stack_rets=%ld, num_actual_rets=%ld, stack_top=%ld, idx_retbase=%ld, idx_rcbase=%ld",
66263 	                     (long) num_stack_rets, (long) num_actual_rets, (long) duk_get_top(thr),
66264 	                     (long) idx_retbase, (long) idx_rcbase));
66265 
66266 	DUK_ASSERT(idx_rcbase >= 0);  /* caller must check */
66267 
66268 	/* Space for num_stack_rets was reserved before the safe call.
66269 	 * Because value stack reserve cannot shrink except in call returns,
66270 	 * the reserve is still in place.  Adjust valstack, carefully
66271 	 * ensuring we don't overstep the reserve.
66272 	 */
66273 
66274 	/* Match idx_rcbase with idx_retbase so that the return values
66275 	 * start at the correct index.
66276 	 */
66277 	if (idx_rcbase > idx_retbase) {
66278 		duk_idx_t count = idx_rcbase - idx_retbase;
66279 
66280 		DUK_DDD(DUK_DDDPRINT("elements at/after idx_retbase have enough to cover func retvals "
66281 		                     "(idx_retbase=%ld, idx_rcbase=%ld)", (long) idx_retbase, (long) idx_rcbase));
66282 
66283 		/* Remove values between irc_rcbase (start of intended return
66284 		 * values) and idx_retbase to lower return values to idx_retbase.
66285 		 */
66286 		DUK_ASSERT(count > 0);
66287 		duk_remove_n(thr, idx_retbase, count);  /* may be NORZ */
66288 	} else {
66289 		duk_idx_t count = idx_retbase - idx_rcbase;
66290 
66291 		DUK_DDD(DUK_DDDPRINT("not enough elements at/after idx_retbase to cover func retvals "
66292 		                     "(idx_retbase=%ld, idx_rcbase=%ld)", (long) idx_retbase, (long) idx_rcbase));
66293 
66294 		/* Insert 'undefined' at idx_rcbase (start of intended return
66295 		 * values) to lift return values to idx_retbase.
66296 		 */
66297 		DUK_ASSERT(count >= 0);
66298 		DUK_ASSERT(thr->valstack_end - thr->valstack_top >= count);  /* reserve cannot shrink */
66299 		duk_insert_undefined_n(thr, idx_rcbase, count);
66300 	}
66301 
66302 	/* Chop extra retvals away / extend with undefined. */
66303 	duk_set_top_unsafe(thr, idx_retbase + num_stack_rets);
66304 }
66305 
66306 /*
66307  *  Activation setup for tailcalls and non-tailcalls.
66308  */
66309 
66310 #if defined(DUK_USE_TAILCALL)
66311 DUK_LOCAL duk_small_uint_t duk__call_setup_act_attempt_tailcall(duk_hthread *thr,
66312                                                                 duk_small_uint_t call_flags,
66313                                                                 duk_idx_t idx_func,
66314                                                                 duk_hobject *func,
66315                                                                 duk_size_t entry_valstack_bottom_byteoff,
66316                                                                 duk_size_t entry_valstack_end_byteoff,
66317                                                                 duk_idx_t *out_nargs,
66318                                                                 duk_idx_t *out_nregs,
66319                                                                 duk_size_t *out_vs_min_bytes,
66320                                                                 duk_activation **out_act) {
66321 	duk_activation *act;
66322 	duk_tval *tv1, *tv2;
66323 	duk_idx_t idx_args;
66324 	duk_small_uint_t flags1, flags2;
66325 #if defined(DUK_USE_DEBUGGER_SUPPORT)
66326 	duk_activation *prev_pause_act;
66327 #endif
66328 
66329 	DUK_UNREF(entry_valstack_end_byteoff);
66330 
66331 	/* Tailcall cannot be flagged to resume calls, and a
66332 	 * previous frame must exist.
66333 	 */
66334 	DUK_ASSERT(thr->callstack_top >= 1);
66335 
66336 	act = thr->callstack_curr;
66337 	DUK_ASSERT(act != NULL);
66338 	*out_act = act;
66339 
66340 	if (func == NULL || !DUK_HOBJECT_IS_COMPFUNC(func)) {
66341 		DUK_DDD(DUK_DDDPRINT("tail call prevented by target not being ecma function"));
66342 		return 0;
66343 	}
66344 	if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
66345 		DUK_DDD(DUK_DDDPRINT("tail call prevented by current activation having DUK_ACT_FLAG_PREVENT_YIELD"));
66346 		return 0;
66347 	}
66348 	/* Tailcall is only allowed if current and candidate
66349 	 * function have identical return value handling.  There
66350 	 * are three possible return value handling cases:
66351 	 *   1. Normal function call, no special return value handling.
66352 	 *   2. Constructor call, return value replacement object check.
66353 	 *   3. Proxy 'construct' trap call, return value invariant check.
66354 	 */
66355 	flags1 = (duk_small_uint_t) ((act->flags & DUK_ACT_FLAG_CONSTRUCT) ? 1 : 0)
66356 #if defined(DUK_USE_ES6_PROXY)
66357 	         | (duk_small_uint_t) ((act->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY) ? 2 : 0)
66358 #endif
66359 	         ;
66360 	flags2 = (duk_small_uint_t) ((call_flags & DUK_CALL_FLAG_CONSTRUCT) ? 1 : 0)
66361 #if defined(DUK_USE_ES6_PROXY)
66362 	         | (duk_small_uint_t) ((call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY) ? 2 : 0);
66363 #endif
66364 	         ;
66365 	if (flags1 != flags2) {
66366 		DUK_DDD(DUK_DDDPRINT("tail call prevented by incompatible return value handling"));
66367 		return 0;
66368 	}
66369 	DUK_ASSERT(((act->flags & DUK_ACT_FLAG_CONSTRUCT) && (call_flags & DUK_CALL_FLAG_CONSTRUCT)) ||
66370 	           (!(act->flags & DUK_ACT_FLAG_CONSTRUCT) && !(call_flags & DUK_CALL_FLAG_CONSTRUCT)));
66371 	DUK_ASSERT(((act->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY) && (call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY)) ||
66372 	           (!(act->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY) && !(call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY)));
66373 	if (DUK_HOBJECT_HAS_NOTAIL(func)) {
66374 		/* See: test-bug-tailcall-preventyield-assert.c. */
66375 		DUK_DDD(DUK_DDDPRINT("tail call prevented by function having a notail flag"));
66376 		return 0;
66377 	}
66378 
66379 	/*
66380 	 *  Tailcall handling
66381 	 *
66382 	 *  Although the callstack entry is reused, we need to explicitly unwind
66383 	 *  the current activation (or simulate an unwind).  In particular, the
66384 	 *  current activation must be closed, otherwise something like
66385 	 *  test-bug-reduce-judofyr.js results.  Also catchers need to be unwound
66386 	 *  because there may be non-error-catching label entries in valid tail calls.
66387 	 *
66388 	 *  Special attention is needed for debugger and pause behavior when
66389 	 *  reusing an activation.
66390 	 *    - Disable StepOut processing for the activation unwind because
66391 	 *      we reuse the activation, see:
66392 	 *      https://github.com/svaarala/duktape/issues/1684.
66393 	 *    - Disable line change pause flag permanently if act == dbg_pause_act
66394 	 *      (if set) because it would no longer be relevant, see:
66395 	 *      https://github.com/svaarala/duktape/issues/1726,
66396 	 *      https://github.com/svaarala/duktape/issues/1786.
66397 	 *    - Check for function entry (e.g. StepInto) pause flag here, because
66398 	 *      the executor pause check won't trigger due to shared activation, see:
66399 	 *      https://github.com/svaarala/duktape/issues/1726.
66400 	 */
66401 
66402 	DUK_DDD(DUK_DDDPRINT("is tail call, reusing activation at callstack top, at index %ld",
66403                              (long) (thr->callstack_top - 1)));
66404 
66405 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));
66406 	DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(func));
66407 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func));
66408 	DUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);
66409 	DUK_ASSERT(call_flags & DUK_CALL_FLAG_ALLOW_ECMATOECMA);
66410 
66411 	/* Unwind the topmost callstack entry before reusing it.  This
66412 	 * also unwinds the catchers related to the topmost entry.
66413 	 */
66414 	DUK_ASSERT(thr->callstack_top > 0);
66415 	DUK_ASSERT(thr->callstack_curr != NULL);
66416 #if defined(DUK_USE_DEBUGGER_SUPPORT)
66417 	if (act == thr->heap->dbg_pause_act) {
66418 		thr->heap->dbg_pause_flags &= ~DUK_PAUSE_FLAG_LINE_CHANGE;
66419 	}
66420 
66421 	prev_pause_act = thr->heap->dbg_pause_act;
66422 	thr->heap->dbg_pause_act = NULL;
66423 	if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_FUNC_ENTRY) {
66424 		DUK_D(DUK_DPRINT("PAUSE TRIGGERED by function entry (tailcall)"));
66425 		duk_debug_set_paused(thr->heap);
66426 	}
66427 #endif
66428 	duk_hthread_activation_unwind_reuse_norz(thr);
66429 #if defined(DUK_USE_DEBUGGER_SUPPORT)
66430 	thr->heap->dbg_pause_act = prev_pause_act;
66431 #endif
66432 	DUK_ASSERT(act == thr->callstack_curr);
66433 
66434 	/* XXX: We could restore the caller's value stack reserve
66435 	 * here, as if we did an actual unwind-and-call.  Without
66436 	 * the restoration, value stack reserve may remain higher
66437 	 * than would otherwise be possible until we return to a
66438 	 * non-tailcall.
66439 	 */
66440 
66441 	/* Then reuse the unwound activation. */
66442 	act->cat = NULL;
66443 	act->var_env = NULL;
66444 	act->lex_env = NULL;
66445 	DUK_ASSERT(func != NULL);
66446 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func));
66447 	act->func = func;  /* don't want an intermediate exposed state with func == NULL */
66448 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
66449 	act->prev_caller = NULL;
66450 #endif
66451 	/* don't want an intermediate exposed state with invalid pc */
66452 	act->curr_pc = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) func);
66453 #if defined(DUK_USE_DEBUGGER_SUPPORT)
66454 	act->prev_line = 0;
66455 #endif
66456 	DUK_TVAL_SET_OBJECT(&act->tv_func, func);  /* borrowed, no refcount */
66457 	DUK_HOBJECT_INCREF(thr, func);
66458 
66459 	act->flags = DUK_ACT_FLAG_TAILCALLED;
66460 	if (DUK_HOBJECT_HAS_STRICT(func)) {
66461 		act->flags |= DUK_ACT_FLAG_STRICT;
66462 	}
66463 	if (call_flags & DUK_CALL_FLAG_CONSTRUCT) {
66464 		act->flags |= DUK_ACT_FLAG_CONSTRUCT;
66465 	}
66466 #if defined(DUK_USE_ES6_PROXY)
66467 	if (call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY) {
66468 		act->flags |= DUK_ACT_FLAG_CONSTRUCT_PROXY;
66469 	}
66470 #endif
66471 
66472 	DUK_ASSERT(DUK_ACT_GET_FUNC(act) == func);      /* already updated */
66473 	DUK_ASSERT(act->var_env == NULL);
66474 	DUK_ASSERT(act->lex_env == NULL);
66475 	act->bottom_byteoff = entry_valstack_bottom_byteoff;  /* tail call -> reuse current "frame" */
66476 #if 0
66477 	/* Topmost activation retval_byteoff is considered garbage, no need to init. */
66478 	act->retval_byteoff = 0;
66479 #endif
66480 	/* Filled in when final reserve is known, dummy value doesn't matter
66481 	 * even in error unwind because reserve_byteoff is only used when
66482 	 * returning to -this- activation.
66483 	 */
66484 	act->reserve_byteoff = 0;
66485 
66486 	/*
66487 	 *  Manipulate valstack so that args are on the current bottom and the
66488 	 *  previous caller's 'this' binding (which is the value preceding the
66489 	 *  current bottom) is replaced with the new 'this' binding:
66490 	 *
66491 	 *       [ ... this_old | (crud) func this_new arg1 ... argN ]
66492 	 *  -->  [ ... this_new | arg1 ... argN ]
66493 	 *
66494 	 *  For tail calling to work properly, the valstack bottom must not grow
66495 	 *  here; otherwise crud would accumulate on the valstack.
66496 	 */
66497 
66498 	tv1 = thr->valstack_bottom - 1;
66499 	tv2 = thr->valstack_bottom + idx_func + 1;
66500 	DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);  /* tv1 is -below- valstack_bottom */
66501 	DUK_ASSERT(tv2 >= thr->valstack_bottom && tv2 < thr->valstack_top);
66502 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
66503 
66504 	idx_args = idx_func + 2;
66505 	duk_remove_n(thr, 0, idx_args);  /* may be NORZ */
66506 
66507 	idx_func = 0; DUK_UNREF(idx_func);  /* really 'not applicable' anymore, should not be referenced after this */
66508 	idx_args = 0;
66509 
66510 	*out_nargs = ((duk_hcompfunc *) func)->nargs;
66511 	*out_nregs = ((duk_hcompfunc *) func)->nregs;
66512 	DUK_ASSERT(*out_nregs >= 0);
66513 	DUK_ASSERT(*out_nregs >= *out_nargs);
66514 	*out_vs_min_bytes = entry_valstack_bottom_byteoff + sizeof(duk_tval) * ((duk_size_t) *out_nregs + DUK_VALSTACK_INTERNAL_EXTRA);
66515 
66516 
66517 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
66518 #if defined(DUK_USE_TAILCALL)
66519 #error incorrect options: tail calls enabled with function caller property
66520 #endif
66521 	/* XXX: This doesn't actually work properly for tail calls, so
66522 	 * tail calls are disabled when DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
66523 	 * is in use.
66524 	 */
66525 	duk__update_func_caller_prop(thr, func);
66526 #endif
66527 
66528 	/* [ ... this_new | arg1 ... argN ] */
66529 
66530 	return 1;
66531 }
66532 #endif  /* DUK_USE_TAILCALL */
66533 
66534 DUK_LOCAL void duk__call_setup_act_not_tailcall(duk_hthread *thr,
66535                                                 duk_small_uint_t call_flags,
66536                                                 duk_idx_t idx_func,
66537                                                 duk_hobject *func,
66538                                                 duk_size_t entry_valstack_bottom_byteoff,
66539                                                 duk_size_t entry_valstack_end_byteoff,
66540                                                 duk_idx_t *out_nargs,
66541                                                 duk_idx_t *out_nregs,
66542                                                 duk_size_t *out_vs_min_bytes,
66543                                                 duk_activation **out_act) {
66544 	duk_activation *act;
66545 	duk_activation *new_act;
66546 
66547 	DUK_UNREF(entry_valstack_end_byteoff);
66548 
66549 	DUK_DDD(DUK_DDDPRINT("not a tail call, pushing a new activation to callstack, to index %ld",
66550 	                     (long) (thr->callstack_top)));
66551 
66552 	duk__call_callstack_limit_check(thr);
66553 	new_act = duk_hthread_activation_alloc(thr);
66554 	DUK_ASSERT(new_act != NULL);
66555 
66556 	act = thr->callstack_curr;
66557 	if (act != NULL) {
66558 		/*
66559 		 *  Update return value stack index of current activation (if any).
66560 		 *
66561 		 *  Although it might seem this is not necessary (bytecode executor
66562 		 *  does this for ECMAScript-to-ECMAScript calls; other calls are
66563 		 *  handled here), this turns out to be necessary for handling yield
66564 		 *  and resume.  For them, an ECMAScript-to-native call happens, and
66565 		 *  the ECMAScript call's retval_byteoff must be set for things to work.
66566 		 */
66567 
66568 		act->retval_byteoff = entry_valstack_bottom_byteoff + (duk_size_t) idx_func * sizeof(duk_tval);
66569 	}
66570 
66571 	new_act->parent = act;
66572 	thr->callstack_curr = new_act;
66573 	thr->callstack_top++;
66574 	act = new_act;
66575 	*out_act = act;
66576 
66577 	DUK_ASSERT(thr->valstack_top > thr->valstack_bottom);  /* at least effective 'this' */
66578 	DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));
66579 
66580 	act->cat = NULL;
66581 
66582 	act->flags = 0;
66583 	if (call_flags & DUK_CALL_FLAG_CONSTRUCT) {
66584 		act->flags |= DUK_ACT_FLAG_CONSTRUCT;
66585 	}
66586 #if defined(DUK_USE_ES6_PROXY)
66587 	if (call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY) {
66588 		act->flags |= DUK_ACT_FLAG_CONSTRUCT_PROXY;
66589 	}
66590 #endif
66591 	if (call_flags & DUK_CALL_FLAG_DIRECT_EVAL) {
66592 		act->flags |= DUK_ACT_FLAG_DIRECT_EVAL;
66593 	}
66594 
66595 	/* start of arguments: idx_func + 2. */
66596 	act->func = func;  /* NULL for lightfunc */
66597 	if (DUK_LIKELY(func != NULL)) {
66598 		DUK_TVAL_SET_OBJECT(&act->tv_func, func);  /* borrowed, no refcount */
66599 		if (DUK_HOBJECT_HAS_STRICT(func)) {
66600 			act->flags |= DUK_ACT_FLAG_STRICT;
66601 		}
66602 		if (DUK_HOBJECT_IS_COMPFUNC(func)) {
66603 			*out_nargs = ((duk_hcompfunc *) func)->nargs;
66604 			*out_nregs = ((duk_hcompfunc *) func)->nregs;
66605 			DUK_ASSERT(*out_nregs >= 0);
66606 			DUK_ASSERT(*out_nregs >= *out_nargs);
66607 			*out_vs_min_bytes = entry_valstack_bottom_byteoff +
66608 				sizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nregs + DUK_VALSTACK_INTERNAL_EXTRA);
66609 		} else {
66610 			/* True because of call target lookup checks. */
66611 			DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(func));
66612 
66613 			*out_nargs = ((duk_hnatfunc *) func)->nargs;
66614 			*out_nregs = *out_nargs;
66615 			if (*out_nargs >= 0) {
66616 				*out_vs_min_bytes = entry_valstack_bottom_byteoff +
66617 					sizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nregs + DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
66618 			} else {
66619 				/* Vararg function. */
66620 				duk_size_t valstack_top_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - ((duk_uint8_t *) thr->valstack));
66621 				*out_vs_min_bytes = valstack_top_byteoff +
66622 					sizeof(duk_tval) * (DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
66623 			}
66624 		}
66625 	} else {
66626 		duk_small_uint_t lf_flags;
66627 		duk_tval *tv_func;
66628 
66629 		act->flags |= DUK_ACT_FLAG_STRICT;
66630 
66631 		tv_func = DUK_GET_TVAL_POSIDX(thr, idx_func);
66632 		DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func));
66633 		DUK_TVAL_SET_TVAL(&act->tv_func, tv_func);  /* borrowed, no refcount */
66634 
66635 		lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv_func);
66636 		*out_nargs = DUK_LFUNC_FLAGS_GET_NARGS(lf_flags);
66637 		if (*out_nargs != DUK_LFUNC_NARGS_VARARGS) {
66638 			*out_vs_min_bytes = entry_valstack_bottom_byteoff +
66639 				sizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nargs + DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
66640 		} else {
66641 			duk_size_t valstack_top_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - ((duk_uint8_t *) thr->valstack));
66642 			*out_vs_min_bytes = valstack_top_byteoff +
66643 				sizeof(duk_tval) * (DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
66644 			*out_nargs = -1;  /* vararg */
66645 		}
66646 		*out_nregs = *out_nargs;
66647 	}
66648 
66649 	act->var_env = NULL;
66650 	act->lex_env = NULL;
66651 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
66652 	act->prev_caller = NULL;
66653 #endif
66654 	act->curr_pc = NULL;
66655 #if defined(DUK_USE_DEBUGGER_SUPPORT)
66656 	act->prev_line = 0;
66657 #endif
66658 	act->bottom_byteoff = entry_valstack_bottom_byteoff + sizeof(duk_tval) * ((duk_size_t) idx_func + 2U);
66659 #if 0
66660 	act->retval_byteoff = 0;   /* topmost activation retval_byteoff is considered garbage, no need to init */
66661 #endif
66662 	/* Filled in when final reserve is known, dummy value doesn't matter
66663 	 * even in error unwind because reserve_byteoff is only used when
66664 	 * returning to -this- activation.
66665 	 */
66666 	act->reserve_byteoff = 0;  /* filled in by caller */
66667 
66668 	/* XXX: Is this INCREF necessary? 'func' is always a borrowed
66669 	 * reference reachable through the value stack?  If changed, stack
66670 	 * unwind code also needs to be fixed to match.
66671 	 */
66672 	DUK_HOBJECT_INCREF_ALLOWNULL(thr, func);  /* act->func */
66673 
66674 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
66675 	if (func) {
66676 		duk__update_func_caller_prop(thr, func);
66677 	}
66678 #endif
66679 }
66680 
66681 /*
66682  *  Environment setup.
66683  */
66684 
66685 DUK_LOCAL void duk__call_env_setup(duk_hthread *thr, duk_hobject *func, duk_activation *act, duk_idx_t idx_args) {
66686 	duk_hobject *env;
66687 
66688 	DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));  /* bound function has already been resolved */
66689 
66690 	if (DUK_LIKELY(func != NULL)) {
66691 		if (DUK_LIKELY(DUK_HOBJECT_HAS_NEWENV(func))) {
66692 			DUK_STATS_INC(thr->heap, stats_envrec_newenv);
66693 			if (DUK_LIKELY(!DUK_HOBJECT_HAS_CREATEARGS(func))) {
66694 				/* Use a new environment but there's no 'arguments' object;
66695 				 * delayed environment initialization.  This is the most
66696 				 * common case.
66697 				 */
66698 				DUK_ASSERT(act->lex_env == NULL);
66699 				DUK_ASSERT(act->var_env == NULL);
66700 			} else {
66701 				/* Use a new environment and there's an 'arguments' object.
66702 				 * We need to initialize it right now.
66703 				 */
66704 
66705 				/* third arg: absolute index (to entire valstack) of bottom_byteoff of new activation */
66706 				env = duk_create_activation_environment_record(thr, func, act->bottom_byteoff);
66707 				DUK_ASSERT(env != NULL);
66708 
66709 				/* [ ... func this arg1 ... argN envobj ] */
66710 
66711 				DUK_ASSERT(DUK_HOBJECT_HAS_CREATEARGS(func));
66712 				duk__handle_createargs_for_call(thr, func, env, idx_args);
66713 
66714 				/* [ ... func this arg1 ... argN envobj ] */
66715 
66716 				act->lex_env = env;
66717 				act->var_env = env;
66718 				DUK_HOBJECT_INCREF(thr, env);
66719 				DUK_HOBJECT_INCREF(thr, env);  /* XXX: incref by count (2) directly */
66720 				duk_pop(thr);
66721 			}
66722 		} else {
66723 			/* Use existing env (e.g. for non-strict eval); cannot have
66724 			 * an own 'arguments' object (but can refer to an existing one).
66725 			 */
66726 
66727 			DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(func));
66728 
66729 			DUK_STATS_INC(thr->heap, stats_envrec_oldenv);
66730 			duk__handle_oldenv_for_call(thr, func, act);
66731 
66732 			DUK_ASSERT(act->lex_env != NULL);
66733 			DUK_ASSERT(act->var_env != NULL);
66734 		}
66735 	} else {
66736 		/* Lightfuncs are always native functions and have "newenv". */
66737 		DUK_ASSERT(act->lex_env == NULL);
66738 		DUK_ASSERT(act->var_env == NULL);
66739 		DUK_STATS_INC(thr->heap, stats_envrec_newenv);
66740 	}
66741 }
66742 
66743 /*
66744  *  Misc shared helpers.
66745  */
66746 
66747 /* Check thread state, update current thread. */
66748 DUK_LOCAL void duk__call_thread_state_update(duk_hthread *thr) {
66749 	DUK_ASSERT(thr != NULL);
66750 
66751 	if (DUK_LIKELY(thr == thr->heap->curr_thread)) {
66752 		if (DUK_UNLIKELY(thr->state != DUK_HTHREAD_STATE_RUNNING)) {
66753 			/* Should actually never happen, but check anyway. */
66754 			goto thread_state_error;
66755 		}
66756 	} else {
66757 		DUK_ASSERT(thr->heap->curr_thread == NULL ||
66758 		           thr->heap->curr_thread->state == DUK_HTHREAD_STATE_RUNNING);
66759 		if (DUK_UNLIKELY(thr->state != DUK_HTHREAD_STATE_INACTIVE)) {
66760 			goto thread_state_error;
66761 		}
66762 		DUK_HEAP_SWITCH_THREAD(thr->heap, thr);
66763 		thr->state = DUK_HTHREAD_STATE_RUNNING;
66764 
66765 		/* Multiple threads may be simultaneously in the RUNNING
66766 		 * state, but not in the same "resume chain".
66767 		 */
66768 	}
66769 	DUK_ASSERT(thr->heap->curr_thread == thr);
66770 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
66771 	return;
66772 
66773  thread_state_error:
66774 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "invalid thread state (%ld)", (long) thr->state);
66775 	DUK_WO_NORETURN(return;);
66776 }
66777 
66778 /*
66779  *  Main unprotected call handler, handles:
66780  *
66781  *    - All combinations of native/ECMAScript caller and native/ECMAScript
66782  *      target.
66783  *
66784  *    - Optimized ECMAScript-to-ECMAScript call where call handling only
66785  *      sets up a new duk_activation but reuses an existing bytecode executor
66786  *      (the caller) without native recursion.
66787  *
66788  *    - Tailcalls, where an activation is reused without increasing call
66789  *      stack (duk_activation) depth.
66790  *
66791  *    - Setup for an initial Duktape.Thread.resume().
66792  *
66793  *  The call handler doesn't provide any protection guarantees, protected calls
66794  *  must be implemented e.g. by wrapping the call in a duk_safe_call().
66795  *  Call setup may fail at any stage, even when the new activation is in
66796  *  place; the only guarantee is that the state is consistent for unwinding.
66797  */
66798 
66799 DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr,
66800                                          duk_idx_t idx_func,
66801                                          duk_small_uint_t call_flags) {
66802 #if defined(DUK_USE_ASSERTIONS)
66803 	duk_activation *entry_act;
66804 	duk_size_t entry_callstack_top;
66805 #endif
66806 	duk_size_t entry_valstack_bottom_byteoff;
66807 	duk_size_t entry_valstack_end_byteoff;
66808 	duk_int_t entry_call_recursion_depth;
66809 	duk_hthread *entry_curr_thread;
66810 	duk_uint_fast8_t entry_thread_state;
66811 	duk_instr_t **entry_ptr_curr_pc;
66812 	duk_idx_t idx_args;
66813 	duk_idx_t nargs;            /* # argument registers target function wants (< 0 => "as is") */
66814 	duk_idx_t nregs;            /* # total registers target function wants on entry (< 0 => "as is") */
66815 	duk_size_t vs_min_bytes;    /* minimum value stack size (bytes) for handling call */
66816 	duk_hobject *func;          /* 'func' on stack (borrowed reference) */
66817 	duk_activation *act;
66818 	duk_ret_t rc;
66819 	duk_small_uint_t use_tailcall;
66820 
66821 	DUK_ASSERT(thr != NULL);
66822 	DUK_ASSERT(thr->heap != NULL);
66823 	/* Asserts for heap->curr_thread omitted: it may be NULL, 'thr', or
66824 	 * any other thread (e.g. when heap thread is used to run finalizers).
66825 	 */
66826 	DUK_CTX_ASSERT_VALID(thr);
66827 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
66828 	DUK_ASSERT(idx_func >= 0);
66829 
66830 	DUK_STATS_INC(thr->heap, stats_call_all);
66831 
66832 	/* If a tail call:
66833 	 *   - an ECMAScript activation must be on top of the callstack
66834 	 *   - there cannot be any catch stack entries that would catch
66835 	 *     a return
66836 	 */
66837 #if defined(DUK_USE_ASSERTIONS)
66838 	if (call_flags & DUK_CALL_FLAG_TAILCALL) {
66839 		duk_activation *tmp_act;
66840 		duk_catcher *tmp_cat;
66841 
66842 		DUK_ASSERT(thr->callstack_top >= 1);
66843 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);
66844 		DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
66845 
66846 		/* No entry in the catch stack which would actually catch a
66847 		 * throw can refer to the callstack entry being reused.
66848 		 * There *can* be catch stack entries referring to the current
66849 		 * callstack entry as long as they don't catch (e.g. label sites).
66850 		 */
66851 
66852 		tmp_act = thr->callstack_curr;
66853 		for (tmp_cat = tmp_act->cat; tmp_cat != NULL; tmp_cat = tmp_cat->parent) {
66854 			DUK_ASSERT(DUK_CAT_GET_TYPE(tmp_cat) == DUK_CAT_TYPE_LABEL); /* a non-catching entry */
66855 		}
66856 	}
66857 #endif  /* DUK_USE_ASSERTIONS */
66858 
66859 	/*
66860 	 *  Store entry state.
66861 	 */
66862 
66863 #if defined(DUK_USE_ASSERTIONS)
66864 	entry_act = thr->callstack_curr;
66865 	entry_callstack_top = thr->callstack_top;
66866 #endif
66867 	entry_valstack_bottom_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack);
66868 	entry_valstack_end_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
66869 	entry_call_recursion_depth = thr->heap->call_recursion_depth;
66870 	entry_curr_thread = thr->heap->curr_thread;  /* may be NULL if first call */
66871 	entry_thread_state = thr->state;
66872 	entry_ptr_curr_pc = thr->ptr_curr_pc;  /* may be NULL */
66873 
66874 	/* If thr->ptr_curr_pc is set, sync curr_pc to act->pc.  Then NULL
66875 	 * thr->ptr_curr_pc so that it's not accidentally used with an incorrect
66876 	 * activation when side effects occur.
66877 	 */
66878 	duk_hthread_sync_and_null_currpc(thr);
66879 	DUK_ASSERT(thr->ptr_curr_pc == NULL);
66880 
66881 	DUK_DD(DUK_DDPRINT("duk__handle_call_raw: thr=%p, idx_func=%ld, "
66882 	                   "call_flags=0x%08lx (constructor=%ld), "
66883 	                   "valstack_top=%ld, idx_func=%ld, idx_args=%ld, rec_depth=%ld/%ld, "
66884 	                   "entry_valstack_bottom_byteoff=%ld, entry_valstack_end_byteoff=%ld, "
66885 	                   "entry_call_recursion_depth=%ld, "
66886 	                   "entry_curr_thread=%p, entry_thread_state=%ld",
66887 	                   (void *) thr,
66888 	                   (long) idx_func,
66889 	                   (unsigned long) call_flags,
66890 	                   (long) ((call_flags & DUK_CALL_FLAG_CONSTRUCT) != 0 ? 1 : 0),
66891 	                   (long) duk_get_top(thr),
66892 	                   (long) idx_func,
66893 	                   (long) (idx_func + 2),
66894 	                   (long) thr->heap->call_recursion_depth,
66895 	                   (long) thr->heap->call_recursion_limit,
66896 	                   (long) entry_valstack_bottom_byteoff,
66897 	                   (long) entry_valstack_end_byteoff,
66898 	                   (long) entry_call_recursion_depth,
66899 	                   (void *) entry_curr_thread,
66900 	                   (long) entry_thread_state));
66901 
66902 	/*
66903 	 *  Thread state check and book-keeping.
66904 	 */
66905 
66906 	duk__call_thread_state_update(thr);
66907 
66908 	/*
66909 	 *  Increase call recursion depth as early as possible so that if we
66910 	 *  enter a recursive call for any reason there's a backstop to native
66911 	 *  recursion.  This can happen e.g. for almost any property read
66912 	 *  because it may cause a getter call or a Proxy trap (GC and finalizers
66913 	 *  are not an issue because they are not recursive).  If we end up
66914 	 *  doing an Ecma-to-Ecma call, revert the increase.  (See GH-2032.)
66915 	 *
66916 	 *  For similar reasons, ensure there is a known value stack spare
66917 	 *  even before we actually prepare the value stack for the target
66918 	 *  function.  If this isn't done, early recursion may consume the
66919 	 *  value stack space.
66920 	 *
66921 	 *  XXX: Should bump yield preventcount early, for the same reason.
66922 	 */
66923 
66924 	duk__call_c_recursion_limit_check(thr);
66925 	thr->heap->call_recursion_depth++;
66926 	duk_require_stack(thr, DUK__CALL_HANDLING_REQUIRE_STACK);
66927 
66928 	/*
66929 	 *  Resolve final target function; handle bound functions and special
66930 	 *  functions like .call() and .apply().  Also figure out the effective
66931 	 *  'this' binding, which replaces the current value at idx_func + 1.
66932 	 */
66933 
66934 	if (DUK_LIKELY(duk__resolve_target_fastpath_check(thr, idx_func, &func, call_flags) != 0U)) {
66935 		DUK_DDD(DUK_DDDPRINT("fast path target resolve"));
66936 	} else {
66937 		DUK_DDD(DUK_DDDPRINT("slow path target resolve"));
66938 		func = duk__resolve_target_func_and_this_binding(thr, idx_func, &call_flags);
66939 	}
66940 	DUK_ASSERT(duk_get_top(thr) - idx_func >= 2);  /* at least func and this present */
66941 
66942 	DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));
66943 	DUK_ASSERT(func == NULL || (DUK_HOBJECT_IS_COMPFUNC(func) ||
66944 	                            DUK_HOBJECT_IS_NATFUNC(func)));
66945 
66946 	/* [ ... func this arg1 ... argN ] */
66947 
66948 	/*
66949 	 *  Setup a preliminary activation and figure out nargs/nregs and
66950 	 *  value stack minimum size.
66951 	 *
66952 	 *  Don't touch valstack_bottom or valstack_top yet so that Duktape API
66953 	 *  calls work normally.
66954 	 *
66955 	 *  Because 'act' is not zeroed, all fields must be filled in.
66956 	 */
66957 
66958 	/* Should not be necessary, but initialize to silence warnings. */
66959 	act = NULL;
66960 	nargs = 0;
66961 	nregs = 0;
66962 	vs_min_bytes = 0;
66963 
66964 #if defined(DUK_USE_TAILCALL)
66965 	use_tailcall = (call_flags & DUK_CALL_FLAG_TAILCALL);
66966 	if (use_tailcall) {
66967 		use_tailcall = duk__call_setup_act_attempt_tailcall(thr,
66968 		                                                    call_flags,
66969 		                                                    idx_func,
66970 		                                                    func,
66971 		                                                    entry_valstack_bottom_byteoff,
66972 		                                                    entry_valstack_end_byteoff,
66973 		                                                    &nargs,
66974 		                                                    &nregs,
66975 		                                                    &vs_min_bytes,
66976 		                                                    &act);
66977 	}
66978 #else
66979 	DUK_ASSERT((call_flags & DUK_CALL_FLAG_TAILCALL) == 0);  /* compiler ensures this */
66980 	use_tailcall = 0;
66981 #endif
66982 
66983 	if (use_tailcall) {
66984 		idx_args = 0;
66985 		DUK_STATS_INC(thr->heap, stats_call_tailcall);
66986 	} else {
66987 		duk__call_setup_act_not_tailcall(thr,
66988 		                                 call_flags,
66989 		                                 idx_func,
66990 		                                 func,
66991 		                                 entry_valstack_bottom_byteoff,
66992 		                                 entry_valstack_end_byteoff,
66993 		                                 &nargs,
66994 		                                 &nregs,
66995 		                                 &vs_min_bytes,
66996 		                                 &act);
66997 		idx_args = idx_func + 2;
66998 	}
66999 	/* After this point idx_func is no longer valid for tailcalls. */
67000 
67001 	DUK_ASSERT(act != NULL);
67002 
67003 	/* [ ... func this arg1 ... argN ] */
67004 
67005 	/*
67006 	 *  Environment record creation and 'arguments' object creation.
67007 	 *  Named function expression name binding is handled by the
67008 	 *  compiler; the compiled function's parent env will contain
67009 	 *  the (immutable) binding already.
67010 	 *
67011 	 *  This handling is now identical for C and ECMAScript functions.
67012 	 *  C functions always have the 'NEWENV' flag set, so their
67013 	 *  environment record initialization is delayed (which is good).
67014 	 *
67015 	 *  Delayed creation (on demand) is handled in duk_js_var.c.
67016 	 */
67017 
67018 	duk__call_env_setup(thr, func, act, idx_args);
67019 
67020 	/* [ ... func this arg1 ... argN ] */
67021 
67022 	/*
67023 	 *  Setup value stack: clamp to 'nargs', fill up to 'nregs',
67024 	 *  ensure value stack size matches target requirements, and
67025 	 *  switch value stack bottom.  Valstack top is kept.
67026 	 *
67027 	 *  Value stack can only grow here.
67028 	 */
67029 
67030 	duk_valstack_grow_check_throw(thr, vs_min_bytes);
67031 	act->reserve_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
67032 
67033 	if (use_tailcall) {
67034 		DUK_ASSERT(nregs >= 0);
67035 		DUK_ASSERT(nregs >= nargs);
67036 		duk_set_top_and_wipe(thr, nregs, nargs);
67037 	} else {
67038 		if (nregs >= 0) {
67039 			DUK_ASSERT(nregs >= nargs);
67040 			duk_set_top_and_wipe(thr, idx_func + 2 + nregs, idx_func + 2 + nargs);
67041 		} else {
67042 			;
67043 		}
67044 		thr->valstack_bottom = thr->valstack_bottom + idx_func + 2;
67045 	}
67046 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
67047 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
67048 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
67049 
67050 	/*
67051 	 *  Make the actual call.  For Ecma-to-Ecma calls detect that
67052 	 *  setup is complete, then return with a status code that allows
67053 	 *  the caller to reuse the running executor.
67054 	 */
67055 
67056 	if (func != NULL && DUK_HOBJECT_IS_COMPFUNC(func)) {
67057 		/*
67058 		 *  ECMAScript call.
67059 		 */
67060 
67061 		DUK_ASSERT(func != NULL);
67062 		DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func));
67063 		act->curr_pc = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) func);
67064 
67065 		if (call_flags & DUK_CALL_FLAG_ALLOW_ECMATOECMA) {
67066 			DUK_DD(DUK_DDPRINT("avoid native call, use existing executor"));
67067 			DUK_STATS_INC(thr->heap, stats_call_ecmatoecma);
67068 			DUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);
67069 			DUK_REFZERO_CHECK_FAST(thr);
67070 			DUK_ASSERT(thr->ptr_curr_pc == NULL);
67071 			thr->heap->call_recursion_depth--;  /* No recursion increase for this case. */
67072 			return 1;  /* 1=reuse executor */
67073 		}
67074 		DUK_ASSERT(use_tailcall == 0);
67075 
67076 		/* duk_hthread_activation_unwind_norz() will decrease this on unwind */
67077 		DUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);
67078 		act->flags |= DUK_ACT_FLAG_PREVENT_YIELD;
67079 		thr->callstack_preventcount++;
67080 
67081 		/* [ ... func this | arg1 ... argN ] ('this' must precede new bottom) */
67082 
67083 		/*
67084 		 *  Bytecode executor call.
67085 		 *
67086 		 *  Execute bytecode, handling any recursive function calls and
67087 		 *  thread resumptions.  Returns when execution would return from
67088 		 *  the entry level activation.  When the executor returns, a
67089 		 *  single return value is left on the stack top.
67090 		 *
67091 		 *  The only possible longjmp() is an error (DUK_LJ_TYPE_THROW),
67092 		 *  other types are handled internally by the executor.
67093 		 */
67094 
67095 		/* thr->ptr_curr_pc is set by bytecode executor early on entry */
67096 		DUK_ASSERT(thr->ptr_curr_pc == NULL);
67097 		DUK_DDD(DUK_DDDPRINT("entering bytecode execution"));
67098 		duk_js_execute_bytecode(thr);
67099 		DUK_DDD(DUK_DDDPRINT("returned from bytecode execution"));
67100 	} else {
67101 		/*
67102 		 *  Native call.
67103 		 */
67104 
67105 		DUK_ASSERT(func == NULL || ((duk_hnatfunc *) func)->func != NULL);
67106 		DUK_ASSERT(use_tailcall == 0);
67107 
67108 		/* [ ... func this | arg1 ... argN ] ('this' must precede new bottom) */
67109 
67110 		/* duk_hthread_activation_unwind_norz() will decrease this on unwind */
67111 		DUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);
67112 		act->flags |= DUK_ACT_FLAG_PREVENT_YIELD;
67113 		thr->callstack_preventcount++;
67114 
67115 		/* For native calls must be NULL so we don't sync back */
67116 		DUK_ASSERT(thr->ptr_curr_pc == NULL);
67117 
67118 		/* XXX: native funcptr could come out of call setup. */
67119 		if (func) {
67120 			rc = ((duk_hnatfunc *) func)->func(thr);
67121 		} else {
67122 			duk_tval *tv_func;
67123 			duk_c_function funcptr;
67124 
67125 			tv_func = &act->tv_func;
67126 			DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func));
67127 			funcptr = DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv_func);
67128 			rc = funcptr(thr);
67129 		}
67130 
67131 		/* Automatic error throwing, retval check. */
67132 
67133 		if (rc == 0) {
67134 			DUK_ASSERT(thr->valstack < thr->valstack_end);
67135 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));
67136 			thr->valstack_top++;
67137 		} else if (rc == 1) {
67138 			;
67139 		} else if (rc < 0) {
67140 			duk_error_throw_from_negative_rc(thr, rc);
67141 			DUK_WO_NORETURN(return 0;);
67142 		} else {
67143 			DUK_ERROR_TYPE(thr, DUK_STR_INVALID_CFUNC_RC);
67144 			DUK_WO_NORETURN(return 0;);
67145 		}
67146 	}
67147 	DUK_ASSERT(thr->ptr_curr_pc == NULL);
67148 	DUK_ASSERT(use_tailcall == 0);
67149 
67150 	/*
67151 	 *  Constructor call post processing.
67152 	 */
67153 
67154 #if defined(DUK_USE_ES6_PROXY)
67155 	if (call_flags & (DUK_CALL_FLAG_CONSTRUCT | DUK_CALL_FLAG_CONSTRUCT_PROXY)) {
67156 		duk_call_construct_postprocess(thr, call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY);
67157 	}
67158 #else
67159 	if (call_flags & DUK_CALL_FLAG_CONSTRUCT) {
67160 		duk_call_construct_postprocess(thr, 0);
67161 	}
67162 #endif
67163 
67164 	/*
67165 	 *  Unwind, restore valstack bottom and other book-keeping.
67166 	 */
67167 
67168 	DUK_ASSERT(thr->callstack_curr != NULL);
67169 	DUK_ASSERT(thr->callstack_curr->parent == entry_act);
67170 	DUK_ASSERT(thr->callstack_top == entry_callstack_top + 1);
67171 	duk_hthread_activation_unwind_norz(thr);
67172 	DUK_ASSERT(thr->callstack_curr == entry_act);
67173 	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
67174 
67175 	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + entry_valstack_bottom_byteoff);
67176 	/* keep current valstack_top */
67177 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
67178 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
67179 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
67180 	DUK_ASSERT(thr->valstack_top - thr->valstack_bottom >= idx_func + 1);
67181 
67182 	/* Return value handling. */
67183 
67184 	/* [ ... func this (crud) retval ] */
67185 
67186 	{
67187 		duk_tval *tv_ret;
67188 		duk_tval *tv_funret;
67189 
67190 		tv_ret = thr->valstack_bottom + idx_func;
67191 		tv_funret = thr->valstack_top - 1;
67192 #if defined(DUK_USE_FASTINT)
67193 		/* Explicit check for fastint downgrade. */
67194 		DUK_TVAL_CHKFAST_INPLACE_FAST(tv_funret);
67195 #endif
67196 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, tv_funret);  /* side effects */
67197 	}
67198 
67199 	duk_set_top_unsafe(thr, idx_func + 1);
67200 
67201 	/* [ ... retval ] */
67202 
67203 	/* Restore caller's value stack reserve (cannot fail). */
67204 	DUK_ASSERT((duk_uint8_t *) thr->valstack + entry_valstack_end_byteoff >= (duk_uint8_t *) thr->valstack_top);
67205 	DUK_ASSERT((duk_uint8_t *) thr->valstack + entry_valstack_end_byteoff <= (duk_uint8_t *) thr->valstack_alloc_end);
67206 	thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + entry_valstack_end_byteoff);
67207 
67208 	/* XXX: Trial value stack shrink would be OK here, but we'd need
67209 	 * to prevent side effects of the potential realloc.
67210 	 */
67211 
67212 	/* Restore entry thread executor curr_pc stack frame pointer. */
67213 	thr->ptr_curr_pc = entry_ptr_curr_pc;
67214 
67215 	DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread);  /* may be NULL */
67216 	thr->state = (duk_uint8_t) entry_thread_state;
67217 
67218 	/* Disabled assert: triggered with some torture tests. */
67219 #if 0
67220 	DUK_ASSERT((thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread == NULL) ||  /* first call */
67221 	           (thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread != NULL) ||  /* other call */
67222 	           (thr->state == DUK_HTHREAD_STATE_RUNNING && thr->heap->curr_thread == thr));     /* current thread */
67223 #endif
67224 
67225 	thr->heap->call_recursion_depth = entry_call_recursion_depth;
67226 
67227 	/* If the debugger is active we need to force an interrupt so that
67228 	 * debugger breakpoints are rechecked.  This is important for function
67229 	 * calls caused by side effects (e.g. when doing a DUK_OP_GETPROP), see
67230 	 * GH-303.  Only needed for success path, error path always causes a
67231 	 * breakpoint recheck in the executor.  It would be enough to set this
67232 	 * only when returning to an ECMAScript activation, but setting the flag
67233 	 * on every return should have no ill effect.
67234 	 */
67235 #if defined(DUK_USE_DEBUGGER_SUPPORT)
67236 	if (duk_debug_is_attached(thr->heap)) {
67237 		DUK_DD(DUK_DDPRINT("returning with debugger enabled, force interrupt"));
67238 		DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);
67239 		thr->interrupt_init -= thr->interrupt_counter;
67240 		thr->interrupt_counter = 0;
67241 		thr->heap->dbg_force_restart = 1;
67242 	}
67243 #endif
67244 
67245 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
67246 	duk__interrupt_fixup(thr, entry_curr_thread);
67247 #endif
67248 
67249 	/* Restored by success path. */
67250 	DUK_ASSERT(thr->heap->call_recursion_depth == entry_call_recursion_depth);
67251 	DUK_ASSERT(thr->ptr_curr_pc == entry_ptr_curr_pc);
67252 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
67253 
67254 	DUK_REFZERO_CHECK_FAST(thr);
67255 
67256 	return 0;  /* 0=call handled inline */
67257 }
67258 
67259 DUK_INTERNAL duk_int_t duk_handle_call_unprotected_nargs(duk_hthread *thr,
67260                                                          duk_idx_t nargs,
67261                                                          duk_small_uint_t call_flags) {
67262 	duk_idx_t idx_func;
67263 	DUK_ASSERT(duk_get_top(thr) >= nargs + 2);
67264 	idx_func = duk_get_top(thr) - (nargs + 2);
67265 	DUK_ASSERT(idx_func >= 0);
67266 	return duk_handle_call_unprotected(thr, idx_func, call_flags);
67267 }
67268 
67269 DUK_INTERNAL duk_int_t duk_handle_call_unprotected(duk_hthread *thr,
67270                                                    duk_idx_t idx_func,
67271                                                    duk_small_uint_t call_flags) {
67272 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
67273 	DUK_ASSERT(idx_func >= 0);
67274 	return duk__handle_call_raw(thr, idx_func, call_flags);
67275 }
67276 
67277 /*
67278  *  duk_handle_safe_call(): make a "C protected call" within the
67279  *  current activation.
67280  *
67281  *  The allowed thread states for making a call are the same as for
67282  *  duk_handle_call_protected().
67283  *
67284  *  Even though this call is protected, errors are thrown for insane arguments
67285  *  and may result in a fatal error unless there's another protected call which
67286  *  catches such errors.
67287  *
67288  *  The error handling path should be error free, even for out-of-memory
67289  *  errors, to ensure safe sandboxing.  (As of Duktape 2.2.0 this is not
67290  *  yet the case for environment closing which may run out of memory, see
67291  *  XXX notes below.)
67292  */
67293 
67294 DUK_LOCAL void duk__handle_safe_call_inner(duk_hthread *thr,
67295                                            duk_safe_call_function func,
67296                                            void *udata,
67297 #if defined(DUK_USE_ASSERTIONS)
67298                                            duk_size_t entry_valstack_bottom_byteoff,
67299                                            duk_size_t entry_callstack_top,
67300 #endif
67301                                            duk_hthread *entry_curr_thread,
67302                                            duk_uint_fast8_t entry_thread_state,
67303                                            duk_idx_t idx_retbase,
67304                                            duk_idx_t num_stack_rets) {
67305 	duk_ret_t rc;
67306 
67307 	DUK_ASSERT(thr != NULL);
67308 	DUK_CTX_ASSERT_VALID(thr);
67309 
67310 	/*
67311 	 *  Thread state check and book-keeping.
67312 	 */
67313 
67314 	duk__call_thread_state_update(thr);
67315 
67316 	/*
67317 	 *  Recursion limit check.
67318 	 */
67319 
67320 	duk__call_c_recursion_limit_check(thr);
67321 	thr->heap->call_recursion_depth++;
67322 
67323 	/*
67324 	 *  Make the C call.
67325 	 */
67326 
67327 	rc = func(thr, udata);
67328 
67329 	DUK_DDD(DUK_DDDPRINT("safe_call, func rc=%ld", (long) rc));
67330 
67331 	/*
67332 	 *  Valstack manipulation for results.
67333 	 */
67334 
67335 	/* we're running inside the caller's activation, so no change in call/catch stack or valstack bottom */
67336 	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
67337 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
67338 	DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) == entry_valstack_bottom_byteoff);
67339 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
67340 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
67341 
67342 	if (DUK_UNLIKELY(rc < 0)) {
67343 		duk_error_throw_from_negative_rc(thr, rc);
67344 		DUK_WO_NORETURN(return;);
67345 	}
67346 	DUK_ASSERT(rc >= 0);
67347 
67348 	duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, rc);  /* throws for insane rc */
67349 
67350 	DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread);  /* may be NULL */
67351 	thr->state = (duk_uint8_t) entry_thread_state;
67352 }
67353 
67354 DUK_LOCAL void duk__handle_safe_call_error(duk_hthread *thr,
67355                                            duk_activation *entry_act,
67356 #if defined(DUK_USE_ASSERTIONS)
67357                                            duk_size_t entry_callstack_top,
67358 #endif
67359                                            duk_hthread *entry_curr_thread,
67360                                            duk_uint_fast8_t entry_thread_state,
67361                                            duk_idx_t idx_retbase,
67362                                            duk_idx_t num_stack_rets,
67363                                            duk_size_t entry_valstack_bottom_byteoff,
67364                                            duk_jmpbuf *old_jmpbuf_ptr) {
67365 	DUK_ASSERT(thr != NULL);
67366 	DUK_CTX_ASSERT_VALID(thr);
67367 
67368 	/*
67369 	 *  Error during call.  The error value is at heap->lj.value1.
67370 	 *
67371 	 *  The very first thing we do is restore the previous setjmp catcher.
67372 	 *  This means that any error in error handling will propagate outwards
67373 	 *  instead of causing a setjmp() re-entry above.
67374 	 */
67375 
67376 	DUK_DDD(DUK_DDDPRINT("error caught during protected duk_handle_safe_call()"));
67377 
67378 	/* Other longjmp types are handled by executor before propagating
67379 	 * the error here.
67380 	 */
67381 	DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW);
67382 	DUK_ASSERT_LJSTATE_SET(thr->heap);
67383 
67384 	/* Either pointer may be NULL (at entry), so don't assert. */
67385 	thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
67386 
67387 	/* XXX: callstack unwind may now throw an error when closing
67388 	 * scopes; this is a sandboxing issue, described in:
67389 	 * https://github.com/svaarala/duktape/issues/476
67390 	 */
67391 	/* XXX: "unwind to" primitive? */
67392 
67393 	DUK_ASSERT(thr->callstack_top >= entry_callstack_top);
67394 	while (thr->callstack_curr != entry_act) {
67395 		DUK_ASSERT(thr->callstack_curr != NULL);
67396 		duk_hthread_activation_unwind_norz(thr);
67397 	}
67398 	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
67399 
67400 	/* Switch active thread before any side effects to avoid a
67401 	 * dangling curr_thread pointer.
67402 	 */
67403 	DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread);  /* may be NULL */
67404 	thr->state = (duk_uint8_t) entry_thread_state;
67405 
67406 	DUK_ASSERT(thr->heap->curr_thread == entry_curr_thread);
67407 	DUK_ASSERT(thr->state == entry_thread_state);
67408 
67409 	/* Restore valstack bottom. */
67410 	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + entry_valstack_bottom_byteoff);
67411 
67412 	/* [ ... | (crud) ] */
67413 
67414 	/* XXX: ensure space in valstack (now relies on internal reserve)? */
67415 	duk_push_tval(thr, &thr->heap->lj.value1);
67416 
67417 	/* [ ... | (crud) errobj ] */
67418 
67419 	DUK_ASSERT(duk_get_top(thr) >= 1);  /* at least errobj must be on stack */
67420 
67421 	duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, 1);  /* 1 = num actual 'return values' */
67422 
67423 	/* [ ... | ] or [ ... | errobj (M * undefined)] where M = num_stack_rets - 1 */
67424 
67425 	/* Reset longjmp state. */
67426 	thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
67427 	thr->heap->lj.iserror = 0;
67428 	DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, &thr->heap->lj.value1);
67429 	DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, &thr->heap->lj.value2);
67430 
67431 	/* Error handling complete, remove side effect protections.  Caller
67432 	 * will process pending finalizers.
67433 	 */
67434 #if defined(DUK_USE_ASSERTIONS)
67435 	DUK_ASSERT(thr->heap->error_not_allowed == 1);
67436 	thr->heap->error_not_allowed = 0;
67437 #endif
67438 	DUK_ASSERT(thr->heap->pf_prevent_count > 0);
67439 	thr->heap->pf_prevent_count--;
67440 	DUK_DD(DUK_DDPRINT("safe call error handled, pf_prevent_count updated to %ld", (long) thr->heap->pf_prevent_count));
67441 
67442 	/* thr->ptr_curr_pc is restored by
67443 	 * duk__handle_safe_call_shared_unwind() which is also used for
67444 	 * success path.
67445 	 */
67446 }
67447 
67448 DUK_LOCAL void duk__handle_safe_call_shared_unwind(duk_hthread *thr,
67449                                                    duk_idx_t idx_retbase,
67450                                                    duk_idx_t num_stack_rets,
67451 #if defined(DUK_USE_ASSERTIONS)
67452                                                    duk_size_t entry_callstack_top,
67453 #endif
67454                                                    duk_int_t entry_call_recursion_depth,
67455                                                    duk_hthread *entry_curr_thread,
67456                                                    duk_instr_t **entry_ptr_curr_pc) {
67457 	DUK_ASSERT(thr != NULL);
67458 	DUK_CTX_ASSERT_VALID(thr);
67459 	DUK_UNREF(idx_retbase);
67460 	DUK_UNREF(num_stack_rets);
67461 	DUK_UNREF(entry_curr_thread);
67462 
67463 	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
67464 
67465 	/* Restore entry thread executor curr_pc stack frame pointer.
67466 	 * XXX: would be enough to do in error path only, should nest
67467 	 * cleanly in success path.
67468 	 */
67469 	thr->ptr_curr_pc = entry_ptr_curr_pc;
67470 
67471 	thr->heap->call_recursion_depth = entry_call_recursion_depth;
67472 
67473 	/* stack discipline consistency check */
67474 	DUK_ASSERT(duk_get_top(thr) == idx_retbase + num_stack_rets);
67475 
67476 	/* A debugger forced interrupt check is not needed here, as
67477 	 * problematic safe calls are not caused by side effects.
67478 	 */
67479 
67480 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
67481 	duk__interrupt_fixup(thr, entry_curr_thread);
67482 #endif
67483 }
67484 
67485 DUK_INTERNAL duk_int_t duk_handle_safe_call(duk_hthread *thr,
67486                                             duk_safe_call_function func,
67487                                             void *udata,
67488                                             duk_idx_t num_stack_args,
67489                                             duk_idx_t num_stack_rets) {
67490 	duk_activation *entry_act;
67491 	duk_size_t entry_valstack_bottom_byteoff;
67492 #if defined(DUK_USE_ASSERTIONS)
67493 	duk_size_t entry_valstack_end_byteoff;
67494 	duk_size_t entry_callstack_top;
67495 	duk_size_t entry_callstack_preventcount;
67496 #endif
67497 	duk_int_t entry_call_recursion_depth;
67498 	duk_hthread *entry_curr_thread;
67499 	duk_uint_fast8_t entry_thread_state;
67500 	duk_instr_t **entry_ptr_curr_pc;
67501 	duk_jmpbuf *old_jmpbuf_ptr = NULL;
67502 	duk_jmpbuf our_jmpbuf;
67503 	duk_idx_t idx_retbase;
67504 	duk_int_t retval;
67505 
67506 	DUK_ASSERT(thr != NULL);
67507 	DUK_ASSERT(duk_get_top(thr) >= num_stack_args);  /* Caller ensures. */
67508 
67509 	DUK_STATS_INC(thr->heap, stats_safecall_all);
67510 
67511 	/* Value stack reserve handling: safe call assumes caller has reserved
67512 	 * space for nrets (assuming optimal unwind processing).  Value stack
67513 	 * reserve is not stored/restored as for normal calls because a safe
67514 	 * call conceptually happens in the same activation.
67515 	 */
67516 
67517 	/* Careful with indices like '-x'; if 'x' is zero, it refers to bottom */
67518 	entry_act = thr->callstack_curr;
67519 	entry_valstack_bottom_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack);
67520 #if defined(DUK_USE_ASSERTIONS)
67521 	entry_valstack_end_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
67522 	entry_callstack_top = thr->callstack_top;
67523 	entry_callstack_preventcount = thr->callstack_preventcount;
67524 #endif
67525 	entry_call_recursion_depth = thr->heap->call_recursion_depth;
67526 	entry_curr_thread = thr->heap->curr_thread;  /* may be NULL if first call */
67527 	entry_thread_state = thr->state;
67528 	entry_ptr_curr_pc = thr->ptr_curr_pc;  /* may be NULL */
67529 	idx_retbase = duk_get_top(thr) - num_stack_args;  /* not a valid stack index if num_stack_args == 0 */
67530 	DUK_ASSERT(idx_retbase >= 0);
67531 
67532 	DUK_ASSERT((duk_idx_t) (thr->valstack_top - thr->valstack_bottom) >= num_stack_args);  /* Caller ensures. */
67533 	DUK_ASSERT((duk_idx_t) (thr->valstack_end - (thr->valstack_bottom + idx_retbase)) >= num_stack_rets);  /* Caller ensures. */
67534 
67535 	/* Cannot portably debug print a function pointer, hence 'func' not printed! */
67536 	DUK_DD(DUK_DDPRINT("duk_handle_safe_call: thr=%p, num_stack_args=%ld, num_stack_rets=%ld, "
67537 	                   "valstack_top=%ld, idx_retbase=%ld, rec_depth=%ld/%ld, "
67538 	                   "entry_act=%p, entry_valstack_bottom_byteoff=%ld, entry_call_recursion_depth=%ld, "
67539 	                   "entry_curr_thread=%p, entry_thread_state=%ld",
67540 	                   (void *) thr,
67541 	                   (long) num_stack_args,
67542 	                   (long) num_stack_rets,
67543 	                   (long) duk_get_top(thr),
67544 	                   (long) idx_retbase,
67545 	                   (long) thr->heap->call_recursion_depth,
67546 	                   (long) thr->heap->call_recursion_limit,
67547 	                   (void *) entry_act,
67548 	                   (long) entry_valstack_bottom_byteoff,
67549 	                   (long) entry_call_recursion_depth,
67550 	                   (void *) entry_curr_thread,
67551 	                   (long) entry_thread_state));
67552 
67553 	/* Setjmp catchpoint setup. */
67554 	old_jmpbuf_ptr = thr->heap->lj.jmpbuf_ptr;
67555 	thr->heap->lj.jmpbuf_ptr = &our_jmpbuf;
67556 
67557 	/* Prevent yields for the duration of the safe call.  This only
67558 	 * matters if the executor makes safe calls to functions that
67559 	 * yield, this doesn't currently happen.
67560 	 */
67561 	thr->callstack_preventcount++;
67562 
67563 #if defined(DUK_USE_CPP_EXCEPTIONS)
67564 	try {
67565 #else
67566 	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == &our_jmpbuf);
67567 	if (DUK_SETJMP(our_jmpbuf.jb) == 0) {
67568 		/* Success path. */
67569 #endif
67570 		DUK_DDD(DUK_DDDPRINT("safe_call setjmp catchpoint setup complete"));
67571 
67572 		duk__handle_safe_call_inner(thr,
67573 		                            func,
67574 		                            udata,
67575 #if defined(DUK_USE_ASSERTIONS)
67576 		                            entry_valstack_bottom_byteoff,
67577 		                            entry_callstack_top,
67578 #endif
67579 		                            entry_curr_thread,
67580 		                            entry_thread_state,
67581 		                            idx_retbase,
67582 		                            num_stack_rets);
67583 
67584 		DUK_STATS_INC(thr->heap, stats_safecall_nothrow);
67585 
67586 		/* Either pointer may be NULL (at entry), so don't assert */
67587 		thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
67588 
67589 		/* If calls happen inside the safe call, these are restored by
67590 		 * whatever calls are made.  Reserve cannot decrease.
67591 		 */
67592 		DUK_ASSERT(thr->callstack_curr == entry_act);
67593 		DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
67594 
67595 		retval = DUK_EXEC_SUCCESS;
67596 #if defined(DUK_USE_CPP_EXCEPTIONS)
67597 	} catch (duk_internal_exception &exc) {
67598 		DUK_UNREF(exc);
67599 #else
67600 	} else {
67601 		/* Error path. */
67602 #endif
67603 		DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
67604 
67605 		DUK_STATS_INC(thr->heap, stats_safecall_throw);
67606 
67607 		duk__handle_safe_call_error(thr,
67608 		                            entry_act,
67609 #if defined(DUK_USE_ASSERTIONS)
67610 		                            entry_callstack_top,
67611 #endif
67612 		                            entry_curr_thread,
67613 		                            entry_thread_state,
67614 		                            idx_retbase,
67615 		                            num_stack_rets,
67616 		                            entry_valstack_bottom_byteoff,
67617 		                            old_jmpbuf_ptr);
67618 
67619 		retval = DUK_EXEC_ERROR;
67620 	}
67621 #if defined(DUK_USE_CPP_EXCEPTIONS)
67622 	catch (duk_fatal_exception &exc) {
67623 		DUK_D(DUK_DPRINT("rethrow duk_fatal_exception"));
67624 		DUK_UNREF(exc);
67625 		throw;
67626 	} catch (std::exception &exc) {
67627 		const char *what = exc.what();
67628 		DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
67629 		DUK_STATS_INC(thr->heap, stats_safecall_throw);
67630 		if (!what) {
67631 			what = "unknown";
67632 		}
67633 		DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
67634 		try {
67635 			DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
67636 			DUK_WO_NORETURN(return 0;);
67637 		} catch (duk_internal_exception exc) {
67638 			DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
67639 			DUK_UNREF(exc);
67640 			duk__handle_safe_call_error(thr,
67641 			                            entry_act,
67642 #if defined(DUK_USE_ASSERTIONS)
67643 			                            entry_callstack_top,
67644 #endif
67645 			                            entry_curr_thread,
67646 			                            entry_thread_state,
67647 			                            idx_retbase,
67648 			                            num_stack_rets,
67649 			                            entry_valstack_bottom_byteoff,
67650 			                            old_jmpbuf_ptr);
67651 			retval = DUK_EXEC_ERROR;
67652 		}
67653 	} catch (...) {
67654 		DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
67655 		DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
67656 		DUK_STATS_INC(thr->heap, stats_safecall_throw);
67657 		try {
67658 			DUK_ERROR_TYPE(thr, "caught invalid c++ exception (perhaps thrown by user code)");
67659 			DUK_WO_NORETURN(return 0;);
67660 		} catch (duk_internal_exception exc) {
67661 			DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
67662 			DUK_UNREF(exc);
67663 			duk__handle_safe_call_error(thr,
67664 			                            entry_act,
67665 #if defined(DUK_USE_ASSERTIONS)
67666 			                            entry_callstack_top,
67667 #endif
67668 			                            entry_curr_thread,
67669 			                            entry_thread_state,
67670 			                            idx_retbase,
67671 			                            num_stack_rets,
67672 			                            entry_valstack_bottom_byteoff,
67673 			                            old_jmpbuf_ptr);
67674 			retval = DUK_EXEC_ERROR;
67675 		}
67676 	}
67677 #endif
67678 
67679 	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == old_jmpbuf_ptr);  /* success/error path both do this */
67680 
67681 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
67682 
67683 	DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
67684 	duk__handle_safe_call_shared_unwind(thr,
67685 	                                    idx_retbase,
67686 	                                    num_stack_rets,
67687 #if defined(DUK_USE_ASSERTIONS)
67688 	                                    entry_callstack_top,
67689 #endif
67690 	                                    entry_call_recursion_depth,
67691 	                                    entry_curr_thread,
67692 	                                    entry_ptr_curr_pc);
67693 
67694 	/* Restore preventcount. */
67695 	thr->callstack_preventcount--;
67696 	DUK_ASSERT(thr->callstack_preventcount == entry_callstack_preventcount);
67697 
67698 	/* Final asserts. */
67699 	DUK_ASSERT(thr->callstack_curr == entry_act);
67700 	DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) == entry_valstack_bottom_byteoff);
67701 	DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
67702 	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
67703 	DUK_ASSERT(thr->heap->call_recursion_depth == entry_call_recursion_depth);
67704 	DUK_ASSERT(thr->heap->curr_thread == entry_curr_thread);
67705 	DUK_ASSERT(thr->state == entry_thread_state);
67706 	DUK_ASSERT(thr->ptr_curr_pc == entry_ptr_curr_pc);
67707 	DUK_ASSERT(duk_get_top(thr) == idx_retbase + num_stack_rets);
67708 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
67709 
67710 	/* Pending side effects. */
67711 	DUK_REFZERO_CHECK_FAST(thr);
67712 
67713 	return retval;
67714 }
67715 
67716 /*
67717  *  Property-based call (foo.noSuch()) error setup: replace target function
67718  *  on stack top with a hidden Symbol tagged non-callable wrapper object
67719  *  holding the error.  The error gets thrown in call handling at the
67720  *  proper spot to follow ECMAScript semantics.
67721  */
67722 
67723 #if defined(DUK_USE_VERBOSE_ERRORS)
67724 DUK_INTERNAL DUK_NOINLINE DUK_COLD void duk_call_setup_propcall_error(duk_hthread *thr, duk_tval *tv_base, duk_tval *tv_key) {
67725 	const char *str_targ, *str_key, *str_base;
67726 	duk_idx_t entry_top;
67727 
67728 	entry_top = duk_get_top(thr);
67729 
67730 	/* [ <nargs> target ] */
67731 
67732 	/* Must stabilize pointers first.  tv_targ is already on stack top. */
67733 	duk_push_tval(thr, tv_base);
67734 	duk_push_tval(thr, tv_key);
67735 
67736 	DUK_GC_TORTURE(thr->heap);
67737 
67738 	duk_push_bare_object(thr);
67739 
67740 	/* [ <nargs> target base key {} ] */
67741 
67742 	/* We only push a wrapped error, replacing the call target (at
67743 	 * idx_func) with the error to ensure side effects come out
67744 	 * correctly:
67745 	 * - Property read
67746 	 * - Call argument evaluation
67747 	 * - Callability check and error thrown
67748 	 *
67749 	 * A hidden Symbol on the wrapper object pushed above is used by
67750 	 * call handling to figure out the error is to be thrown as is.
67751 	 * It is CRITICAL that the hidden Symbol can never occur on a
67752 	 * user visible object that may get thrown.
67753 	 */
67754 
67755 #if defined(DUK_USE_PARANOID_ERRORS)
67756 	str_targ = duk_get_type_name(thr, -4);
67757 	str_key = duk_get_type_name(thr, -2);
67758 	str_base = duk_get_type_name(thr, -3);
67759 	duk_push_error_object(thr,
67760 	                      DUK_ERR_TYPE_ERROR | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
67761 	                      "%s not callable (property %s of %s)", str_targ, str_key, str_base);
67762 	duk_xdef_prop_stridx(thr, -2, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);  /* Marker property, reuse _Target. */
67763 	/* [ <nargs> target base key { _Target: error } ] */
67764 	duk_replace(thr, entry_top - 1);
67765 #else
67766 	str_targ = duk_push_string_readable(thr, -4);
67767 	str_key = duk_push_string_readable(thr, -3);
67768 	str_base = duk_push_string_readable(thr, -5);
67769 	duk_push_error_object(thr,
67770 	                      DUK_ERR_TYPE_ERROR | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
67771 	                      "%s not callable (property %s of %s)", str_targ, str_key, str_base);
67772 	/* [ <nargs> target base key {} str_targ str_key str_base error ] */
67773 	duk_xdef_prop_stridx(thr, -5, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);  /* Marker property, reuse _Target. */
67774 	/* [ <nargs> target base key { _Target: error } str_targ str_key str_base ] */
67775 	duk_swap(thr, -4, entry_top - 1);
67776 	/* [ <nargs> { _Target: error } base key target str_targ str_key str_base ] */
67777 #endif
67778 
67779 	/* [ <nregs> { _Target: error } <variable> */
67780 	duk_set_top(thr, entry_top);
67781 
67782 	/* [ <nregs> { _Target: error } */
67783 	DUK_ASSERT(!duk_is_callable(thr, -1));  /* Critical so that call handling will throw the error. */
67784 }
67785 #endif  /* DUK_USE_VERBOSE_ERRORS */
67786 
67787 /* automatic undefs */
67788 #undef DUK__AUGMENT_CALL_RELAX_COUNT
67789 #undef DUK__CALL_HANDLING_REQUIRE_STACK
67790 /*
67791  *  ECMAScript compiler.
67792  *
67793  *  Parses an input string and generates a function template result.
67794  *  Compilation may happen in multiple contexts (global code, eval
67795  *  code, function code).
67796  *
67797  *  The parser uses a traditional top-down recursive parsing for the
67798  *  statement level, and an operator precedence based top-down approach
67799  *  for the expression level.  The attempt is to minimize the C stack
67800  *  depth.  Bytecode is generated directly without an intermediate
67801  *  representation (tree), at the cost of needing two (and sometimes
67802  *  three) passes over each function.
67803  *
67804  *  The top-down recursive parser functions are named "duk__parse_XXX".
67805  *
67806  *  Recursion limits are in key functions to prevent arbitrary C recursion:
67807  *  function body parsing, statement parsing, and expression parsing.
67808  *
67809  *  See doc/compiler.rst for discussion on the design.
67810  *
67811  *  A few typing notes:
67812  *
67813  *    - duk_regconst_t: signed, highest bit set (< 0) means constant,
67814  *      some call sites use -1 for "none" (equivalent to constant 0x7fffffff)
67815  *    - PC values: duk_int_t, negative values used as markers
67816  */
67817 
67818 /* #include duk_internal.h -> already included */
67819 
67820 /* If highest bit of a register number is set, it refers to a constant instead.
67821  * When interpreted as a signed value, this means const values are always
67822  * negative (when interpreted as two's complement).  For example DUK__ISREG_TEMP()
67823  * uses this approach to avoid an explicit DUK__ISREG() check (the condition is
67824  * logically "'x' is a register AND 'x' >= temp_first").
67825  */
67826 #define DUK__CONST_MARKER                   DUK_REGCONST_CONST_MARKER
67827 #define DUK__REMOVECONST(x)                 ((x) & ~DUK__CONST_MARKER)
67828 #define DUK__ISREG(x)                       ((x) >= 0)
67829 #define DUK__ISCONST(x)                     ((x) < 0)
67830 #define DUK__ISREG_TEMP(comp_ctx,x)         ((duk_int32_t) (x) >= (duk_int32_t) ((comp_ctx)->curr_func.temp_first))   /* Check for x >= temp_first && x >= 0 by comparing as signed. */
67831 #define DUK__ISREG_NOTTEMP(comp_ctx,x)      ((duk_uint32_t) (x) < (duk_uint32_t) ((comp_ctx)->curr_func.temp_first))  /* Check for x >= 0 && x < temp_first by interpreting as unsigned. */
67832 #define DUK__GETTEMP(comp_ctx)              ((comp_ctx)->curr_func.temp_next)
67833 #define DUK__SETTEMP(comp_ctx,x)            ((comp_ctx)->curr_func.temp_next = (x))  /* dangerous: must only lower (temp_max not updated) */
67834 #define DUK__SETTEMP_CHECKMAX(comp_ctx,x)   duk__settemp_checkmax((comp_ctx),(x))
67835 #define DUK__ALLOCTEMP(comp_ctx)            duk__alloctemp((comp_ctx))
67836 #define DUK__ALLOCTEMPS(comp_ctx,count)     duk__alloctemps((comp_ctx),(count))
67837 
67838 /* Init value set size for array and object literals. */
67839 #define DUK__MAX_ARRAY_INIT_VALUES        20
67840 #define DUK__MAX_OBJECT_INIT_PAIRS        10
67841 
67842 /* XXX: hack, remove when const lookup is not O(n) */
67843 #define DUK__GETCONST_MAX_CONSTS_CHECK    256
67844 
67845 /* These limits are based on bytecode limits.  Max temps is limited
67846  * by duk_hcompfunc nargs/nregs fields being 16 bits.
67847  */
67848 #define DUK__MAX_CONSTS                   DUK_BC_BC_MAX
67849 #define DUK__MAX_FUNCS                    DUK_BC_BC_MAX
67850 #define DUK__MAX_TEMPS                    0xffffL
67851 
67852 /* Initial bytecode size allocation. */
67853 #if defined(DUK_USE_PREFER_SIZE)
67854 #define DUK__BC_INITIAL_INSTS             16
67855 #else
67856 #define DUK__BC_INITIAL_INSTS             256
67857 #endif
67858 
67859 #define DUK__RECURSION_INCREASE(comp_ctx,thr)  do { \
67860 		DUK_DDD(DUK_DDDPRINT("RECURSION INCREASE: %s:%ld", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \
67861 		duk__comp_recursion_increase((comp_ctx)); \
67862 	} while (0)
67863 
67864 #define DUK__RECURSION_DECREASE(comp_ctx,thr)  do { \
67865 		DUK_DDD(DUK_DDDPRINT("RECURSION DECREASE: %s:%ld", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \
67866 		duk__comp_recursion_decrease((comp_ctx)); \
67867 	} while (0)
67868 
67869 /* Value stack slot limits: these are quite approximate right now, and
67870  * because they overlap in control flow, some could be eliminated.
67871  */
67872 #define DUK__COMPILE_ENTRY_SLOTS          8
67873 #define DUK__FUNCTION_INIT_REQUIRE_SLOTS  16
67874 #define DUK__FUNCTION_BODY_REQUIRE_SLOTS  16
67875 #define DUK__PARSE_STATEMENTS_SLOTS       16
67876 #define DUK__PARSE_EXPR_SLOTS             16
67877 
67878 /* Temporary structure used to pass a stack allocated region through
67879  * duk_safe_call().
67880  */
67881 typedef struct {
67882 	duk_small_uint_t flags;
67883 	duk_compiler_ctx comp_ctx_alloc;
67884 	duk_lexer_point lex_pt_alloc;
67885 } duk__compiler_stkstate;
67886 
67887 /*
67888  *  Prototypes
67889  */
67890 
67891 /* lexing */
67892 DUK_LOCAL_DECL void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t expect);
67893 DUK_LOCAL_DECL void duk__advance_expect(duk_compiler_ctx *comp_ctx, duk_small_int_t expect);
67894 DUK_LOCAL_DECL void duk__advance(duk_compiler_ctx *ctx);
67895 
67896 /* function helpers */
67897 DUK_LOCAL_DECL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx);
67898 DUK_LOCAL_DECL void duk__reset_func_for_pass2(duk_compiler_ctx *comp_ctx);
67899 DUK_LOCAL_DECL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx, duk_regconst_t *out_stmt_value_reg);
67900 DUK_LOCAL_DECL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx);
67901 DUK_LOCAL_DECL duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx);
67902 
67903 /* code emission */
67904 DUK_LOCAL_DECL duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx);
67905 DUK_LOCAL_DECL duk_compiler_instr *duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc);
67906 DUK_LOCAL_DECL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins);
67907 DUK_LOCAL_DECL void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op);
67908 DUK_LOCAL_DECL void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t b, duk_regconst_t c);
67909 DUK_LOCAL_DECL void duk__emit_a_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t b);
67910 DUK_LOCAL_DECL void duk__emit_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b, duk_regconst_t c);
67911 #if 0  /* unused */
67912 DUK_LOCAL_DECL void duk__emit_a(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a);
67913 DUK_LOCAL_DECL void duk__emit_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b);
67914 #endif
67915 DUK_LOCAL_DECL void duk__emit_a_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t bc);
67916 DUK_LOCAL_DECL void duk__emit_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t bc);
67917 DUK_LOCAL_DECL void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t abc);
67918 DUK_LOCAL_DECL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val);
67919 DUK_LOCAL_DECL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val);
67920 DUK_LOCAL_DECL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc);
67921 DUK_LOCAL_DECL duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx);
67922 DUK_LOCAL_DECL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc);
67923 DUK_LOCAL_DECL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc);
67924 DUK_LOCAL_DECL void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc);
67925 DUK_LOCAL_DECL void duk__patch_trycatch(duk_compiler_ctx *comp_ctx, duk_int_t ldconst_pc, duk_int_t trycatch_pc, duk_regconst_t reg_catch, duk_regconst_t const_varname, duk_small_uint_t flags);
67926 DUK_LOCAL_DECL void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst);
67927 DUK_LOCAL_DECL void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst);
67928 DUK_LOCAL_DECL void duk__emit_invalid(duk_compiler_ctx *comp_ctx);
67929 
67930 /* ivalue/ispec helpers */
67931 DUK_LOCAL_DECL void duk__ivalue_regconst(duk_ivalue *x, duk_regconst_t regconst);
67932 DUK_LOCAL_DECL void duk__ivalue_plain_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
67933 DUK_LOCAL_DECL void duk__ivalue_var_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
67934 DUK_LOCAL_DECL void duk__ivalue_var_hstring(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_hstring *h);
67935 DUK_LOCAL_DECL void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst);
67936 DUK_LOCAL_DECL void duk__copy_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *src, duk_ivalue *dst);
67937 DUK_LOCAL_DECL duk_regconst_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_int_t num);
67938 DUK_LOCAL_DECL duk_regconst_t duk__alloctemp(duk_compiler_ctx *comp_ctx);
67939 DUK_LOCAL_DECL void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_regconst_t temp_next);
67940 DUK_LOCAL_DECL duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx);
67941 DUK_LOCAL_DECL
67942 duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
67943                                          duk_ispec *x,
67944                                          duk_regconst_t forced_reg,
67945                                          duk_small_uint_t flags);
67946 DUK_LOCAL_DECL void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_regconst_t forced_reg);
67947 DUK_LOCAL_DECL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_regconst_t forced_reg);
67948 DUK_LOCAL_DECL void duk__ivalue_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
67949 DUK_LOCAL_DECL void duk__ivalue_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
67950 DUK_LOCAL_DECL
67951 duk_regconst_t duk__ivalue_toregconst_raw(duk_compiler_ctx *comp_ctx,
67952                                           duk_ivalue *x,
67953                                           duk_regconst_t forced_reg,
67954                                           duk_small_uint_t flags);
67955 DUK_LOCAL_DECL duk_regconst_t duk__ivalue_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
67956 #if 0  /* unused */
67957 DUK_LOCAL_DECL duk_regconst_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
67958 #endif
67959 DUK_LOCAL_DECL void duk__ivalue_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_int_t forced_reg);
67960 DUK_LOCAL_DECL duk_regconst_t duk__ivalue_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
67961 DUK_LOCAL_DECL duk_regconst_t duk__ivalue_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
67962 
67963 /* identifier handling */
67964 DUK_LOCAL_DECL duk_regconst_t duk__lookup_active_register_binding(duk_compiler_ctx *comp_ctx);
67965 DUK_LOCAL_DECL duk_bool_t duk__lookup_lhs(duk_compiler_ctx *ctx, duk_regconst_t *out_reg_varbind, duk_regconst_t *out_rc_varname);
67966 
67967 /* label handling */
67968 DUK_LOCAL_DECL void duk__add_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk_int_t pc_label, duk_int_t label_id);
67969 DUK_LOCAL_DECL void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t label_id, duk_small_uint_t flags);
67970 DUK_LOCAL_DECL void duk__lookup_active_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk_bool_t is_break, duk_int_t *out_label_id, duk_int_t *out_label_catch_depth, duk_int_t *out_label_pc, duk_bool_t *out_is_closest);
67971 DUK_LOCAL_DECL void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_size_t len);
67972 
67973 /* top-down expression parser */
67974 DUK_LOCAL_DECL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
67975 DUK_LOCAL_DECL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ivalue *res);
67976 DUK_LOCAL_DECL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx);
67977 DUK_LOCAL_DECL duk_bool_t duk__expr_is_empty(duk_compiler_ctx *comp_ctx);
67978 
67979 /* exprtop is the top level variant which resets nud/led counts */
67980 DUK_LOCAL_DECL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
67981 DUK_LOCAL_DECL void duk__exprtop(duk_compiler_ctx *ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
67982 
67983 /* convenience helpers */
67984 #if 0  /* unused */
67985 DUK_LOCAL_DECL duk_regconst_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
67986 #endif
67987 #if 0  /* unused */
67988 DUK_LOCAL_DECL duk_regconst_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
67989 #endif
67990 DUK_LOCAL_DECL void duk__expr_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_regconst_t forced_reg);
67991 DUK_LOCAL_DECL duk_regconst_t duk__expr_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
67992 #if 0  /* unused */
67993 DUK_LOCAL_DECL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
67994 #endif
67995 DUK_LOCAL_DECL void duk__expr_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
67996 DUK_LOCAL_DECL void duk__expr_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
67997 DUK_LOCAL_DECL duk_regconst_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
67998 #if 0  /* unused */
67999 DUK_LOCAL_DECL duk_regconst_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
68000 #endif
68001 DUK_LOCAL_DECL void duk__exprtop_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_regconst_t forced_reg);
68002 DUK_LOCAL_DECL duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
68003 #if 0  /* unused */
68004 DUK_LOCAL_DECL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
68005 #endif
68006 
68007 /* expression parsing helpers */
68008 DUK_LOCAL_DECL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
68009 DUK_LOCAL_DECL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
68010 DUK_LOCAL_DECL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
68011 
68012 /* statement parsing */
68013 DUK_LOCAL_DECL void duk__parse_var_decl(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags, duk_regconst_t *out_reg_varbind, duk_regconst_t *out_rc_varname);
68014 DUK_LOCAL_DECL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags);
68015 DUK_LOCAL_DECL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
68016 DUK_LOCAL_DECL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
68017 DUK_LOCAL_DECL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
68018 DUK_LOCAL_DECL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
68019 DUK_LOCAL_DECL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
68020 DUK_LOCAL_DECL void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
68021 DUK_LOCAL_DECL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
68022 DUK_LOCAL_DECL void duk__parse_throw_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
68023 DUK_LOCAL_DECL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
68024 DUK_LOCAL_DECL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
68025 DUK_LOCAL_DECL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem);
68026 DUK_LOCAL_DECL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id);
68027 DUK_LOCAL_DECL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof, duk_bool_t regexp_after);
68028 
68029 DUK_LOCAL_DECL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_eof, duk_bool_t implicit_return_value, duk_bool_t regexp_after, duk_small_int_t expect_token);
68030 DUK_LOCAL_DECL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx);
68031 DUK_LOCAL_DECL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags);
68032 DUK_LOCAL_DECL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags);
68033 
68034 #define DUK__FUNC_FLAG_DECL            (1 << 0)   /* Parsing a function declaration. */
68035 #define DUK__FUNC_FLAG_GETSET          (1 << 1)   /* Parsing an object literal getter/setter. */
68036 #define DUK__FUNC_FLAG_METDEF          (1 << 2)   /* Parsing an object literal method definition shorthand. */
68037 #define DUK__FUNC_FLAG_PUSHNAME_PASS1  (1 << 3)   /* Push function name when creating template (first pass only). */
68038 #define DUK__FUNC_FLAG_USE_PREVTOKEN   (1 << 4)   /* Use prev_token to start function parsing (workaround for object literal). */
68039 
68040 /*
68041  *  Parser control values for tokens.  The token table is ordered by the
68042  *  DUK_TOK_XXX defines.
68043  *
68044  *  The binding powers are for lbp() use (i.e. for use in led() context).
68045  *  Binding powers are positive for typing convenience, and bits at the
68046  *  top should be reserved for flags.  Binding power step must be higher
68047  *  than 1 so that binding power "lbp - 1" can be used for right associative
68048  *  operators.  Currently a step of 2 is used (which frees one more bit for
68049  *  flags).
68050  */
68051 
68052 /* XXX: actually single step levels would work just fine, clean up */
68053 
68054 /* binding power "levels" (see doc/compiler.rst) */
68055 #define DUK__BP_INVALID                0             /* always terminates led() */
68056 #define DUK__BP_EOF                    2
68057 #define DUK__BP_CLOSING                4             /* token closes expression, e.g. ')', ']' */
68058 #define DUK__BP_FOR_EXPR               DUK__BP_CLOSING    /* bp to use when parsing a top level Expression */
68059 #define DUK__BP_COMMA                  6
68060 #define DUK__BP_ASSIGNMENT             8
68061 #define DUK__BP_CONDITIONAL            10
68062 #define DUK__BP_LOR                    12
68063 #define DUK__BP_LAND                   14
68064 #define DUK__BP_BOR                    16
68065 #define DUK__BP_BXOR                   18
68066 #define DUK__BP_BAND                   20
68067 #define DUK__BP_EQUALITY               22
68068 #define DUK__BP_RELATIONAL             24
68069 #define DUK__BP_SHIFT                  26
68070 #define DUK__BP_ADDITIVE               28
68071 #define DUK__BP_MULTIPLICATIVE         30
68072 #define DUK__BP_EXPONENTIATION         32
68073 #define DUK__BP_POSTFIX                34
68074 #define DUK__BP_CALL                   36
68075 #define DUK__BP_MEMBER                 38
68076 
68077 #define DUK__TOKEN_LBP_BP_MASK         0x1f
68078 #define DUK__TOKEN_LBP_FLAG_NO_REGEXP  (1 << 5)   /* regexp literal must not follow this token */
68079 #define DUK__TOKEN_LBP_FLAG_TERMINATES (1 << 6)   /* terminates expression; e.g. post-increment/-decrement */
68080 #define DUK__TOKEN_LBP_FLAG_UNUSED     (1 << 7)   /* unused */
68081 
68082 #define DUK__TOKEN_LBP_GET_BP(x)       ((duk_small_uint_t) (((x) & DUK__TOKEN_LBP_BP_MASK) * 2))
68083 
68084 #define DUK__MK_LBP(bp)                ((bp) >> 1)    /* bp is assumed to be even */
68085 #define DUK__MK_LBP_FLAGS(bp,flags)    (((bp) >> 1) | (flags))
68086 
68087 DUK_LOCAL const duk_uint8_t duk__token_lbp[] = {
68088 	DUK__MK_LBP(DUK__BP_EOF),                                 /* DUK_TOK_EOF */
68089 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_IDENTIFIER */
68090 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_BREAK */
68091 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CASE */
68092 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CATCH */
68093 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CONTINUE */
68094 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DEBUGGER */
68095 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DEFAULT */
68096 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DELETE */
68097 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DO */
68098 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_ELSE */
68099 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_FINALLY */
68100 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_FOR */
68101 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_FUNCTION */
68102 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_IF */
68103 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_IN */
68104 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_INSTANCEOF */
68105 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_NEW */
68106 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_RETURN */
68107 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SWITCH */
68108 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_THIS */
68109 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_THROW */
68110 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_TRY */
68111 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_TYPEOF */
68112 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_VAR */
68113 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CONST */
68114 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_VOID */
68115 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_WHILE */
68116 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_WITH */
68117 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CLASS */
68118 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_ENUM */
68119 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_EXPORT */
68120 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_EXTENDS */
68121 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_IMPORT */
68122 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SUPER */
68123 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_NULL */
68124 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_TRUE */
68125 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_FALSE */
68126 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_GET */
68127 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SET */
68128 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_IMPLEMENTS */
68129 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_INTERFACE */
68130 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_LET */
68131 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PACKAGE */
68132 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PRIVATE */
68133 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PROTECTED */
68134 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PUBLIC */
68135 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_STATIC */
68136 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_YIELD */
68137 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_LCURLY */
68138 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_RCURLY */
68139 	DUK__MK_LBP(DUK__BP_MEMBER),                              /* DUK_TOK_LBRACKET */
68140 	DUK__MK_LBP_FLAGS(DUK__BP_CLOSING, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_RBRACKET */
68141 	DUK__MK_LBP(DUK__BP_CALL),                                /* DUK_TOK_LPAREN */
68142 	DUK__MK_LBP_FLAGS(DUK__BP_CLOSING, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_RPAREN */
68143 	DUK__MK_LBP(DUK__BP_MEMBER),                              /* DUK_TOK_PERIOD */
68144 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SEMICOLON */
68145 	DUK__MK_LBP(DUK__BP_COMMA),                               /* DUK_TOK_COMMA */
68146 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_LT */
68147 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_GT */
68148 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_LE */
68149 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_GE */
68150 	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_EQ */
68151 	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_NEQ */
68152 	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_SEQ */
68153 	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_SNEQ */
68154 	DUK__MK_LBP(DUK__BP_ADDITIVE),                            /* DUK_TOK_ADD */
68155 	DUK__MK_LBP(DUK__BP_ADDITIVE),                            /* DUK_TOK_SUB */
68156 	DUK__MK_LBP(DUK__BP_MULTIPLICATIVE),                      /* DUK_TOK_MUL */
68157 	DUK__MK_LBP(DUK__BP_MULTIPLICATIVE),                      /* DUK_TOK_DIV */
68158 	DUK__MK_LBP(DUK__BP_MULTIPLICATIVE),                      /* DUK_TOK_MOD */
68159 	DUK__MK_LBP(DUK__BP_EXPONENTIATION),                      /* DUK_TOK_EXP */
68160 	DUK__MK_LBP_FLAGS(DUK__BP_POSTFIX, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_INCREMENT */
68161 	DUK__MK_LBP_FLAGS(DUK__BP_POSTFIX, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_DECREMENT */
68162 	DUK__MK_LBP(DUK__BP_SHIFT),                               /* DUK_TOK_ALSHIFT */
68163 	DUK__MK_LBP(DUK__BP_SHIFT),                               /* DUK_TOK_ARSHIFT */
68164 	DUK__MK_LBP(DUK__BP_SHIFT),                               /* DUK_TOK_RSHIFT */
68165 	DUK__MK_LBP(DUK__BP_BAND),                                /* DUK_TOK_BAND */
68166 	DUK__MK_LBP(DUK__BP_BOR),                                 /* DUK_TOK_BOR */
68167 	DUK__MK_LBP(DUK__BP_BXOR),                                /* DUK_TOK_BXOR */
68168 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_LNOT */
68169 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_BNOT */
68170 	DUK__MK_LBP(DUK__BP_LAND),                                /* DUK_TOK_LAND */
68171 	DUK__MK_LBP(DUK__BP_LOR),                                 /* DUK_TOK_LOR */
68172 	DUK__MK_LBP(DUK__BP_CONDITIONAL),                         /* DUK_TOK_QUESTION */
68173 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_COLON */
68174 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_EQUALSIGN */
68175 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_ADD_EQ */
68176 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_SUB_EQ */
68177 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_MUL_EQ */
68178 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_DIV_EQ */
68179 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_MOD_EQ */
68180 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_EXP_EQ */
68181 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_ALSHIFT_EQ */
68182 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_ARSHIFT_EQ */
68183 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_RSHIFT_EQ */
68184 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_BAND_EQ */
68185 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_BOR_EQ */
68186 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_BXOR_EQ */
68187 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_NUMBER */
68188 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_STRING */
68189 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_REGEXP */
68190 };
68191 
68192 /*
68193  *  Misc helpers
68194  */
68195 
68196 DUK_LOCAL void duk__comp_recursion_increase(duk_compiler_ctx *comp_ctx) {
68197 	DUK_ASSERT(comp_ctx != NULL);
68198 	DUK_ASSERT(comp_ctx->recursion_depth >= 0);
68199 	if (comp_ctx->recursion_depth >= comp_ctx->recursion_limit) {
68200 		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_COMPILER_RECURSION_LIMIT);
68201 		DUK_WO_NORETURN(return;);
68202 	}
68203 	comp_ctx->recursion_depth++;
68204 }
68205 
68206 DUK_LOCAL void duk__comp_recursion_decrease(duk_compiler_ctx *comp_ctx) {
68207 	DUK_ASSERT(comp_ctx != NULL);
68208 	DUK_ASSERT(comp_ctx->recursion_depth > 0);
68209 	comp_ctx->recursion_depth--;
68210 }
68211 
68212 DUK_LOCAL duk_bool_t duk__hstring_is_eval_or_arguments(duk_compiler_ctx *comp_ctx, duk_hstring *h) {
68213 	DUK_UNREF(comp_ctx);
68214 	DUK_ASSERT(h != NULL);
68215 	return DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(h);
68216 }
68217 
68218 DUK_LOCAL duk_bool_t duk__hstring_is_eval_or_arguments_in_strict_mode(duk_compiler_ctx *comp_ctx, duk_hstring *h) {
68219 	DUK_ASSERT(h != NULL);
68220 	return (comp_ctx->curr_func.is_strict &&
68221 	        DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(h));
68222 }
68223 
68224 /*
68225  *  Parser duk__advance() token eating functions
68226  */
68227 
68228 /* XXX: valstack handling is awkward.  Add a valstack helper which
68229  * avoids dup():ing; valstack_copy(src, dst)?
68230  */
68231 
68232 DUK_LOCAL void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t expect) {
68233 	duk_hthread *thr = comp_ctx->thr;
68234 	duk_bool_t regexp;
68235 
68236 	DUK_ASSERT_DISABLE(comp_ctx->curr_token.t >= 0);  /* unsigned */
68237 	DUK_ASSERT(comp_ctx->curr_token.t <= DUK_TOK_MAXVAL);  /* MAXVAL is inclusive */
68238 
68239 	/*
68240 	 *  Use current token to decide whether a RegExp can follow.
68241 	 *
68242 	 *  We can use either 't' or 't_nores'; the latter would not
68243 	 *  recognize keywords.  Some keywords can be followed by a
68244 	 *  RegExp (e.g. "return"), so using 't' is better.  This is
68245 	 *  not trivial, see doc/compiler.rst.
68246 	 */
68247 
68248 	regexp = 1;
68249 	if (duk__token_lbp[comp_ctx->curr_token.t] & DUK__TOKEN_LBP_FLAG_NO_REGEXP) {
68250 		regexp = 0;
68251 	}
68252 	if (comp_ctx->curr_func.reject_regexp_in_adv) {
68253 		comp_ctx->curr_func.reject_regexp_in_adv = 0;
68254 		regexp = 0;
68255 	}
68256 	if (comp_ctx->curr_func.allow_regexp_in_adv) {
68257 		comp_ctx->curr_func.allow_regexp_in_adv = 0;
68258 		regexp = 1;
68259 	}
68260 
68261 	if (expect >= 0 && comp_ctx->curr_token.t != (duk_small_uint_t) expect) {
68262 		DUK_D(DUK_DPRINT("parse error: expect=%ld, got=%ld",
68263 		                 (long) expect, (long) comp_ctx->curr_token.t));
68264 		DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);
68265 		DUK_WO_NORETURN(return;);
68266 	}
68267 
68268 	/* make current token the previous; need to fiddle with valstack "backing store" */
68269 	duk_memcpy(&comp_ctx->prev_token, &comp_ctx->curr_token, sizeof(duk_token));
68270 	duk_copy(thr, comp_ctx->tok11_idx, comp_ctx->tok21_idx);
68271 	duk_copy(thr, comp_ctx->tok12_idx, comp_ctx->tok22_idx);
68272 
68273 	/* parse new token */
68274 	duk_lexer_parse_js_input_element(&comp_ctx->lex,
68275 	                                 &comp_ctx->curr_token,
68276 	                                 comp_ctx->curr_func.is_strict,
68277 	                                 regexp);
68278 
68279 	DUK_DDD(DUK_DDDPRINT("advance: curr: tok=%ld/%ld,%ld,term=%ld,%!T,%!T "
68280 	                     "prev: tok=%ld/%ld,%ld,term=%ld,%!T,%!T",
68281 	                     (long) comp_ctx->curr_token.t,
68282 	                     (long) comp_ctx->curr_token.t_nores,
68283 	                     (long) comp_ctx->curr_token.start_line,
68284 	                     (long) comp_ctx->curr_token.lineterm,
68285 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok11_idx),
68286 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok12_idx),
68287 	                     (long) comp_ctx->prev_token.t,
68288 	                     (long) comp_ctx->prev_token.t_nores,
68289 	                     (long) comp_ctx->prev_token.start_line,
68290 	                     (long) comp_ctx->prev_token.lineterm,
68291 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok21_idx),
68292 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok22_idx)));
68293 }
68294 
68295 /* advance, expecting current token to be a specific token; parse next token in regexp context */
68296 DUK_LOCAL void duk__advance_expect(duk_compiler_ctx *comp_ctx, duk_small_int_t expect) {
68297 	duk__advance_helper(comp_ctx, expect);
68298 }
68299 
68300 /* advance, whatever the current token is; parse next token in regexp context */
68301 DUK_LOCAL void duk__advance(duk_compiler_ctx *comp_ctx) {
68302 	duk__advance_helper(comp_ctx, -1);
68303 }
68304 
68305 /*
68306  *  Helpers for duk_compiler_func.
68307  */
68308 
68309 /* init function state: inits valstack allocations */
68310 DUK_LOCAL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx) {
68311 	duk_compiler_func *func = &comp_ctx->curr_func;
68312 	duk_hthread *thr = comp_ctx->thr;
68313 	duk_idx_t entry_top;
68314 
68315 	entry_top = duk_get_top(thr);
68316 
68317 	duk_memzero(func, sizeof(*func));  /* intentional overlap with earlier memzero */
68318 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
68319 	func->h_name = NULL;
68320 	func->h_consts = NULL;
68321 	func->h_funcs = NULL;
68322 	func->h_decls = NULL;
68323 	func->h_labelnames = NULL;
68324 	func->h_labelinfos = NULL;
68325 	func->h_argnames = NULL;
68326 	func->h_varmap = NULL;
68327 #endif
68328 
68329 	duk_require_stack(thr, DUK__FUNCTION_INIT_REQUIRE_SLOTS);
68330 
68331 	DUK_BW_INIT_PUSHBUF(thr, &func->bw_code, DUK__BC_INITIAL_INSTS * sizeof(duk_compiler_instr));
68332 	/* code_idx = entry_top + 0 */
68333 
68334 	duk_push_bare_array(thr);
68335 	func->consts_idx = entry_top + 1;
68336 	func->h_consts = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 1);
68337 	DUK_ASSERT(func->h_consts != NULL);
68338 
68339 	duk_push_bare_array(thr);
68340 	func->funcs_idx = entry_top + 2;
68341 	func->h_funcs = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 2);
68342 	DUK_ASSERT(func->h_funcs != NULL);
68343 	DUK_ASSERT(func->fnum_next == 0);
68344 
68345 	duk_push_bare_array(thr);
68346 	func->decls_idx = entry_top + 3;
68347 	func->h_decls = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 3);
68348 	DUK_ASSERT(func->h_decls != NULL);
68349 
68350 	duk_push_bare_array(thr);
68351 	func->labelnames_idx = entry_top + 4;
68352 	func->h_labelnames = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 4);
68353 	DUK_ASSERT(func->h_labelnames != NULL);
68354 
68355 	duk_push_dynamic_buffer(thr, 0);
68356 	func->labelinfos_idx = entry_top + 5;
68357 	func->h_labelinfos = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, entry_top + 5);
68358 	DUK_ASSERT(func->h_labelinfos != NULL);
68359 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(func->h_labelinfos) && !DUK_HBUFFER_HAS_EXTERNAL(func->h_labelinfos));
68360 
68361 	duk_push_bare_array(thr);
68362 	func->argnames_idx = entry_top + 6;
68363 	func->h_argnames = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 6);
68364 	DUK_ASSERT(func->h_argnames != NULL);
68365 
68366 	duk_push_bare_object(thr);
68367 	func->varmap_idx = entry_top + 7;
68368 	func->h_varmap = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 7);
68369 	DUK_ASSERT(func->h_varmap != NULL);
68370 }
68371 
68372 /* reset function state (prepare for pass 2) */
68373 DUK_LOCAL void duk__reset_func_for_pass2(duk_compiler_ctx *comp_ctx) {
68374 	duk_compiler_func *func = &comp_ctx->curr_func;
68375 	duk_hthread *thr = comp_ctx->thr;
68376 
68377 	/* reset bytecode buffer but keep current size; pass 2 will
68378 	 * require same amount or more.
68379 	 */
68380 	DUK_BW_RESET_SIZE(thr, &func->bw_code);
68381 
68382 	duk_set_length(thr, func->consts_idx, 0);
68383 	/* keep func->h_funcs; inner functions are not reparsed to avoid O(depth^2) parsing */
68384 	func->fnum_next = 0;
68385 	/* duk_set_length(thr, func->funcs_idx, 0); */
68386 	duk_set_length(thr, func->labelnames_idx, 0);
68387 	duk_hbuffer_reset(thr, func->h_labelinfos);
68388 	/* keep func->h_argnames; it is fixed for all passes */
68389 
68390 	/* truncated in case pass 3 needed */
68391 	duk_push_bare_object(thr);
68392 	duk_replace(thr, func->varmap_idx);
68393 	func->h_varmap = DUK_GET_HOBJECT_POSIDX(thr, func->varmap_idx);
68394 	DUK_ASSERT(func->h_varmap != NULL);
68395 }
68396 
68397 /* cleanup varmap from any null entries, compact it, etc; returns number
68398  * of final entries after cleanup.
68399  */
68400 DUK_LOCAL duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx) {
68401 	duk_hthread *thr = comp_ctx->thr;
68402 	duk_hobject *h_varmap;
68403 	duk_hstring *h_key;
68404 	duk_tval *tv;
68405 	duk_uint32_t i, e_next;
68406 	duk_int_t ret;
68407 
68408 	/* [ ... varmap ] */
68409 
68410 	h_varmap = DUK_GET_HOBJECT_NEGIDX(thr, -1);
68411 	DUK_ASSERT(h_varmap != NULL);
68412 
68413 	ret = 0;
68414 	e_next = DUK_HOBJECT_GET_ENEXT(h_varmap);
68415 	for (i = 0; i < e_next; i++) {
68416 		h_key = DUK_HOBJECT_E_GET_KEY(thr->heap, h_varmap, i);
68417 		if (!h_key) {
68418 			continue;
68419 		}
68420 
68421 		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h_varmap, i));
68422 
68423 		/* The entries can either be register numbers or 'null' values.
68424 		 * Thus, no need to DECREF them and get side effects.  DECREF'ing
68425 		 * the keys (strings) can cause memory to be freed but no side
68426 		 * effects as strings don't have finalizers.  This is why we can
68427 		 * rely on the object properties not changing from underneath us.
68428 		 */
68429 
68430 		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h_varmap, i);
68431 		if (!DUK_TVAL_IS_NUMBER(tv)) {
68432 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv));
68433 			DUK_HOBJECT_E_SET_KEY(thr->heap, h_varmap, i, NULL);
68434 			DUK_HSTRING_DECREF(thr, h_key);
68435 			/* when key is NULL, value is garbage so no need to set */
68436 		} else {
68437 			ret++;
68438 		}
68439 	}
68440 
68441 	duk_compact_m1(thr);
68442 
68443 	return ret;
68444 }
68445 
68446 /* Convert duk_compiler_func into a function template, leaving the result
68447  * on top of stack.
68448  */
68449 /* XXX: awkward and bloated asm -- use faster internal accesses */
68450 DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
68451 	duk_compiler_func *func = &comp_ctx->curr_func;
68452 	duk_hthread *thr = comp_ctx->thr;
68453 	duk_hcompfunc *h_res;
68454 	duk_hbuffer_fixed *h_data;
68455 	duk_size_t consts_count;
68456 	duk_size_t funcs_count;
68457 	duk_size_t code_count;
68458 	duk_size_t code_size;
68459 	duk_size_t data_size;
68460 	duk_size_t i;
68461 	duk_tval *p_const;
68462 	duk_hobject **p_func;
68463 	duk_instr_t *p_instr;
68464 	duk_compiler_instr *q_instr;
68465 	duk_tval *tv;
68466 	duk_bool_t keep_varmap;
68467 	duk_bool_t keep_formals;
68468 #if !defined(DUK_USE_DEBUGGER_SUPPORT)
68469 	duk_size_t formals_length;
68470 #endif
68471 
68472 	DUK_DDD(DUK_DDDPRINT("converting duk_compiler_func to function/template"));
68473 
68474 	/*
68475 	 *  Push result object and init its flags
68476 	 */
68477 
68478 	/* Valstack should suffice here, required on function valstack init */
68479 
68480 	h_res = duk_push_hcompfunc(thr);
68481 	DUK_ASSERT(h_res != NULL);
68482 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_res) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
68483 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) h_res, NULL);  /* Function templates are "bare objects". */
68484 
68485 	if (func->is_function) {
68486 		DUK_DDD(DUK_DDDPRINT("function -> set NEWENV"));
68487 		DUK_HOBJECT_SET_NEWENV((duk_hobject *) h_res);
68488 
68489 		if (!func->is_arguments_shadowed) {
68490 			/* arguments object would be accessible; note that shadowing
68491 			 * bindings are arguments or function declarations, neither
68492 			 * of which are deletable, so this is safe.
68493 			 */
68494 
68495 			if (func->id_access_arguments || func->may_direct_eval) {
68496 				DUK_DDD(DUK_DDDPRINT("function may access 'arguments' object directly or "
68497 				                     "indirectly -> set CREATEARGS"));
68498 				DUK_HOBJECT_SET_CREATEARGS((duk_hobject *) h_res);
68499 			}
68500 		}
68501 	} else if (func->is_eval && func->is_strict) {
68502 		DUK_DDD(DUK_DDDPRINT("strict eval code -> set NEWENV"));
68503 		DUK_HOBJECT_SET_NEWENV((duk_hobject *) h_res);
68504 	} else {
68505 		/* non-strict eval: env is caller's env or global env (direct vs. indirect call)
68506 		 * global code: env is is global env
68507 		 */
68508 		DUK_DDD(DUK_DDDPRINT("non-strict eval code or global code -> no NEWENV"));
68509 		DUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV((duk_hobject *) h_res));
68510 	}
68511 
68512 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
68513 	if (func->is_function && func->is_namebinding && func->h_name != NULL) {
68514 		/* Object literal set/get functions have a name (property
68515 		 * name) but must not have a lexical name binding, see
68516 		 * test-bug-getset-func-name.js.
68517 		 */
68518 		DUK_DDD(DUK_DDDPRINT("function expression with a name -> set NAMEBINDING"));
68519 		DUK_HOBJECT_SET_NAMEBINDING((duk_hobject *) h_res);
68520 	}
68521 #endif
68522 
68523 	if (func->is_strict) {
68524 		DUK_DDD(DUK_DDDPRINT("function is strict -> set STRICT"));
68525 		DUK_HOBJECT_SET_STRICT((duk_hobject *) h_res);
68526 	}
68527 
68528 	if (func->is_notail) {
68529 		DUK_DDD(DUK_DDDPRINT("function is notail -> set NOTAIL"));
68530 		DUK_HOBJECT_SET_NOTAIL((duk_hobject *) h_res);
68531 	}
68532 
68533 	if (func->is_constructable) {
68534 		DUK_DDD(DUK_DDDPRINT("function is constructable -> set CONSTRUCTABLE"));
68535 		DUK_HOBJECT_SET_CONSTRUCTABLE((duk_hobject *) h_res);
68536 	}
68537 
68538 	/*
68539 	 *  Build function fixed size 'data' buffer, which contains bytecode,
68540 	 *  constants, and inner function references.
68541 	 *
68542 	 *  During the building phase 'data' is reachable but incomplete.
68543 	 *  Only incref's occur during building (no refzero or GC happens),
68544 	 *  so the building process is atomic.
68545 	 */
68546 
68547 	consts_count = duk_hobject_get_length(thr, func->h_consts);
68548 	funcs_count = duk_hobject_get_length(thr, func->h_funcs) / 3;
68549 	code_count = DUK_BW_GET_SIZE(thr, &func->bw_code) / sizeof(duk_compiler_instr);
68550 	code_size = code_count * sizeof(duk_instr_t);
68551 
68552 	data_size = consts_count * sizeof(duk_tval) +
68553 	            funcs_count * sizeof(duk_hobject *) +
68554 	            code_size;
68555 
68556 	DUK_DDD(DUK_DDDPRINT("consts_count=%ld, funcs_count=%ld, code_size=%ld -> "
68557 	                     "data_size=%ld*%ld + %ld*%ld + %ld = %ld",
68558 	                     (long) consts_count, (long) funcs_count, (long) code_size,
68559 	                     (long) consts_count, (long) sizeof(duk_tval),
68560 	                     (long) funcs_count, (long) sizeof(duk_hobject *),
68561 	                     (long) code_size, (long) data_size));
68562 
68563 	duk_push_fixed_buffer_nozero(thr, data_size);
68564 	h_data = (duk_hbuffer_fixed *) (void *) duk_known_hbuffer(thr, -1);
68565 
68566 	DUK_HCOMPFUNC_SET_DATA(thr->heap, h_res, (duk_hbuffer *) h_data);
68567 	DUK_HEAPHDR_INCREF(thr, h_data);
68568 
68569 	p_const = (duk_tval *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data);
68570 	for (i = 0; i < consts_count; i++) {
68571 		DUK_ASSERT(i <= DUK_UARRIDX_MAX);  /* const limits */
68572 		tv = duk_hobject_find_array_entry_tval_ptr(thr->heap, func->h_consts, (duk_uarridx_t) i);
68573 		DUK_ASSERT(tv != NULL);
68574 		DUK_TVAL_SET_TVAL(p_const, tv);
68575 		p_const++;
68576 		DUK_TVAL_INCREF(thr, tv);  /* may be a string constant */
68577 
68578 		DUK_DDD(DUK_DDDPRINT("constant: %!T", (duk_tval *) tv));
68579 	}
68580 
68581 	p_func = (duk_hobject **) p_const;
68582 	DUK_HCOMPFUNC_SET_FUNCS(thr->heap, h_res, p_func);
68583 	for (i = 0; i < funcs_count; i++) {
68584 		duk_hobject *h;
68585 		DUK_ASSERT(i * 3 <= DUK_UARRIDX_MAX);  /* func limits */
68586 		tv = duk_hobject_find_array_entry_tval_ptr(thr->heap, func->h_funcs, (duk_uarridx_t) (i * 3));
68587 		DUK_ASSERT(tv != NULL);
68588 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
68589 		h = DUK_TVAL_GET_OBJECT(tv);
68590 		DUK_ASSERT(h != NULL);
68591 		DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(h));
68592 		*p_func++ = h;
68593 		DUK_HOBJECT_INCREF(thr, h);
68594 
68595 		DUK_DDD(DUK_DDDPRINT("inner function: %p -> %!iO",
68596 		                     (void *) h, (duk_heaphdr *) h));
68597 	}
68598 
68599 	p_instr = (duk_instr_t *) p_func;
68600 	DUK_HCOMPFUNC_SET_BYTECODE(thr->heap, h_res, p_instr);
68601 
68602 	/* copy bytecode instructions one at a time */
68603 	q_instr = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(thr, &func->bw_code);
68604 	for (i = 0; i < code_count; i++) {
68605 		p_instr[i] = q_instr[i].ins;
68606 	}
68607 	/* Note: 'q_instr' is still used below */
68608 
68609 	DUK_ASSERT((duk_uint8_t *) (p_instr + code_count) == DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data) + data_size);
68610 
68611 	duk_pop(thr);  /* 'data' (and everything in it) is reachable through h_res now */
68612 
68613 	/*
68614 	 *  Init non-property result fields
68615 	 *
68616 	 *  'nregs' controls how large a register frame is allocated.
68617 	 *
68618 	 *  'nargs' controls how many formal arguments are written to registers:
68619 	 *  r0, ... r(nargs-1).  The remaining registers are initialized to
68620 	 *  undefined.
68621 	 */
68622 
68623 	DUK_ASSERT(func->temp_max >= 0);
68624 	h_res->nregs = (duk_uint16_t) func->temp_max;
68625 	h_res->nargs = (duk_uint16_t) duk_hobject_get_length(thr, func->h_argnames);
68626 	DUK_ASSERT(h_res->nregs >= h_res->nargs);  /* pass2 allocation handles this */
68627 #if defined(DUK_USE_DEBUGGER_SUPPORT)
68628 	h_res->start_line = (duk_uint32_t) func->min_line;
68629 	h_res->end_line = (duk_uint32_t) func->max_line;
68630 #endif
68631 
68632 	/*
68633 	 *  Init object properties
68634 	 *
68635 	 *  Properties should be added in decreasing order of access frequency.
68636 	 *  (Not very critical for function templates.)
68637 	 */
68638 
68639 	DUK_DDD(DUK_DDDPRINT("init function properties"));
68640 
68641 	/* [ ... res ] */
68642 
68643 	/* _Varmap: omitted if function is guaranteed not to do a slow path
68644 	 * identifier access that might be caught by locally declared variables.
68645 	 * The varmap can also be omitted if it turns out empty of actual
68646 	 * register mappings after a cleanup.  When debugging is enabled, we
68647 	 * always need the varmap to be able to lookup variables at any point.
68648 	 */
68649 
68650 #if defined(DUK_USE_DEBUGGER_SUPPORT)
68651 	DUK_DD(DUK_DDPRINT("keeping _Varmap because debugger support is enabled"));
68652 	keep_varmap = 1;
68653 #else
68654 	if (func->id_access_slow_own ||   /* directly uses slow accesses that may match own variables */
68655 	    func->id_access_arguments ||  /* accesses 'arguments' directly */
68656 	    func->may_direct_eval ||      /* may indirectly slow access through a direct eval */
68657 	    funcs_count > 0) {            /* has inner functions which may slow access (XXX: this can be optimized by looking at the inner functions) */
68658 		DUK_DD(DUK_DDPRINT("keeping _Varmap because of direct eval, slow path access that may match local variables, or presence of inner functions"));
68659 		keep_varmap = 1;
68660 	} else {
68661 		DUK_DD(DUK_DDPRINT("dropping _Varmap"));
68662 		keep_varmap = 0;
68663 	}
68664 #endif
68665 
68666 	if (keep_varmap) {
68667 		duk_int_t num_used;
68668 		duk_dup(thr, func->varmap_idx);
68669 		num_used = duk__cleanup_varmap(comp_ctx);
68670 		DUK_DDD(DUK_DDDPRINT("cleaned up varmap: %!T (num_used=%ld)",
68671 		                     (duk_tval *) duk_get_tval(thr, -1), (long) num_used));
68672 
68673 		if (num_used > 0) {
68674 			duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VARMAP, DUK_PROPDESC_FLAGS_NONE);
68675 		} else {
68676 			DUK_DD(DUK_DDPRINT("varmap is empty after cleanup -> no need to add"));
68677 			duk_pop(thr);
68678 		}
68679 	}
68680 
68681 	/* _Formals: omitted if function is guaranteed not to need a (non-strict)
68682 	 * arguments object, and _Formals.length matches nargs exactly.
68683 	 *
68684 	 * Non-arrow functions can't see an outer function's 'argument' binding
68685 	 * (because they have their own), but arrow functions can.  When arrow
68686 	 * functions are added, this condition would need to be added:
68687 	 *     inner_arrow_funcs_count > 0   inner arrow functions may access 'arguments'
68688 	 */
68689 #if defined(DUK_USE_DEBUGGER_SUPPORT)
68690 	DUK_DD(DUK_DDPRINT("keeping _Formals because debugger support is enabled"));
68691 	keep_formals = 1;
68692 #else
68693 	formals_length = duk_get_length(thr, func->argnames_idx);
68694 	if (formals_length != (duk_size_t) h_res->nargs) {
68695 		/* Nargs not enough for closure .length: keep _Formals regardless
68696 		 * of its length.  Shouldn't happen in practice at the moment.
68697 		 */
68698 		DUK_DD(DUK_DDPRINT("keeping _Formals because _Formals.length != nargs"));
68699 		keep_formals = 1;
68700 	} else if ((func->id_access_arguments || func->may_direct_eval) &&
68701 	           (formals_length > 0)) {
68702 		/* Direct eval (may access 'arguments') or accesses 'arguments'
68703 		 * explicitly: keep _Formals unless it is zero length.
68704 		 */
68705 		DUK_DD(DUK_DDPRINT("keeping _Formals because of direct eval or explicit access to 'arguments', and _Formals.length != 0"));
68706 		keep_formals = 1;
68707 	} else {
68708 		DUK_DD(DUK_DDPRINT("omitting _Formals, nargs matches _Formals.length, so no properties added"));
68709 		keep_formals = 0;
68710 	}
68711 #endif
68712 
68713 	if (keep_formals) {
68714 		duk_dup(thr, func->argnames_idx);
68715 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_FORMALS, DUK_PROPDESC_FLAGS_NONE);
68716 	}
68717 
68718 	/* name */
68719 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
68720 	if (func->h_name) {
68721 		duk_push_hstring(thr, func->h_name);
68722 		DUK_DD(DUK_DDPRINT("setting function template .name to %!T", duk_get_tval(thr, -1)));
68723 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);
68724 	}
68725 #endif  /* DUK_USE_FUNC_NAME_PROPERTY */
68726 
68727 	/* _Source */
68728 #if defined(DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY)
68729 	if (0) {
68730 		/* XXX: Currently function source code is not stored, as it is not
68731 		 * required by the standard.  Source code should not be stored by
68732 		 * default (user should enable it explicitly), and the source should
68733 		 * probably be compressed with a trivial text compressor; average
68734 		 * compression of 20-30% is quite easy to achieve even with a trivial
68735 		 * compressor (RLE + backwards lookup).
68736 		 *
68737 		 * Debugging needs source code to be useful: sometimes input code is
68738 		 * not found in files as it may be generated and then eval()'d, given
68739 		 * by dynamic C code, etc.
68740 		 *
68741 		 * Other issues:
68742 		 *
68743 		 *   - Need tokenizer indices for start and end to substring
68744 		 *   - Always normalize function declaration part?
68745 		 *   - If we keep _Formals, only need to store body
68746 		 */
68747 
68748 		/*
68749 		 *  For global or eval code this is straightforward.  For functions
68750 		 *  created with the Function constructor we only get the source for
68751 		 *  the body and must manufacture the "function ..." part.
68752 		 *
68753 		 *  For instance, for constructed functions (v8):
68754 		 *
68755 		 *    > a = new Function("foo", "bar", "print(foo)");
68756 		 *    [Function]
68757 		 *    > a.toString()
68758 		 *    'function anonymous(foo,bar) {\nprint(foo)\n}'
68759 		 *
68760 		 *  Similarly for e.g. getters (v8):
68761 		 *
68762 		 *    > x = { get a(foo,bar) { print(foo); } }
68763 		 *    { a: [Getter] }
68764 		 *    > Object.getOwnPropertyDescriptor(x, 'a').get.toString()
68765 		 *    'function a(foo,bar) { print(foo); }'
68766 		 */
68767 
68768 #if 0
68769 		duk_push_literal(thr, "XXX");
68770 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_SOURCE, DUK_PROPDESC_FLAGS_NONE);
68771 #endif
68772 	}
68773 #endif  /* DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY */
68774 
68775 	/* _Pc2line */
68776 #if defined(DUK_USE_PC2LINE)
68777 	if (1) {
68778 		/*
68779 		 *  Size-optimized pc->line mapping.
68780 		 */
68781 
68782 		DUK_ASSERT(code_count <= DUK_COMPILER_MAX_BYTECODE_LENGTH);
68783 		duk_hobject_pc2line_pack(thr, q_instr, (duk_uint_fast32_t) code_count);  /* -> pushes fixed buffer */
68784 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_PC2LINE, DUK_PROPDESC_FLAGS_NONE);
68785 
68786 		/* XXX: if assertions enabled, walk through all valid PCs
68787 		 * and check line mapping.
68788 		 */
68789 	}
68790 #endif  /* DUK_USE_PC2LINE */
68791 
68792 	/* fileName */
68793 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
68794 	if (comp_ctx->h_filename) {
68795 		/*
68796 		 *  Source filename (or equivalent), for identifying thrown errors.
68797 		 */
68798 
68799 		duk_push_hstring(thr, comp_ctx->h_filename);
68800 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_NONE);
68801 	}
68802 #endif
68803 
68804 	DUK_DD(DUK_DDPRINT("converted function: %!ixT",
68805 	                   (duk_tval *) duk_get_tval(thr, -1)));
68806 
68807 	/*
68808 	 *  Compact the function template.
68809 	 */
68810 
68811 	duk_compact_m1(thr);
68812 
68813 	/*
68814 	 *  Debug dumping
68815 	 */
68816 
68817 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
68818 	{
68819 		duk_hcompfunc *h;
68820 		duk_instr_t *p, *p_start, *p_end;
68821 
68822 		h = (duk_hcompfunc *) duk_get_hobject(thr, -1);
68823 		p_start = (duk_instr_t *) DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, h);
68824 		p_end = (duk_instr_t *) DUK_HCOMPFUNC_GET_CODE_END(thr->heap, h);
68825 
68826 		p = p_start;
68827 		while (p < p_end) {
68828 			DUK_DDD(DUK_DDDPRINT("BC %04ld: %!I        ; 0x%08lx op=%ld (%!X) a=%ld b=%ld c=%ld",
68829 			                     (long) (p - p_start),
68830 			                     (duk_instr_t) (*p),
68831 			                     (unsigned long) (*p),
68832 			                     (long) DUK_DEC_OP(*p),
68833 			                     (long) DUK_DEC_OP(*p),
68834 			                     (long) DUK_DEC_A(*p),
68835 			                     (long) DUK_DEC_B(*p),
68836 			                     (long) DUK_DEC_C(*p)));
68837 			p++;
68838 		}
68839 	}
68840 #endif
68841 }
68842 
68843 /*
68844  *  Code emission helpers
68845  *
68846  *  Some emission helpers understand the range of target and source reg/const
68847  *  values and automatically emit shuffling code if necessary.  This is the
68848  *  case when the slot in question (A, B, C) is used in the standard way and
68849  *  for opcodes the emission helpers explicitly understand (like DUK_OP_MPUTOBJ).
68850  *
68851  *  The standard way is that:
68852  *    - slot A is a target register
68853  *    - slot B is a source register/constant
68854  *    - slot C is a source register/constant
68855  *
68856  *  If a slot is used in a non-standard way the caller must indicate this
68857  *  somehow.  If a slot is used as a target instead of a source (or vice
68858  *  versa), this can be indicated with a flag to trigger proper shuffling
68859  *  (e.g. DUK__EMIT_FLAG_B_IS_TARGET).  If the value in the slot is not
68860  *  register/const related at all, the caller must ensure that the raw value
68861  *  fits into the corresponding slot so as to not trigger shuffling.  The
68862  *  caller must set a "no shuffle" flag to ensure compilation fails if
68863  *  shuffling were to be triggered because of an internal error.
68864  *
68865  *  For slots B and C the raw slot size is 9 bits but one bit is reserved for
68866  *  the reg/const indicator.  To use the full 9-bit range for a raw value,
68867  *  shuffling must be disabled with the DUK__EMIT_FLAG_NO_SHUFFLE_{B,C} flag.
68868  *  Shuffling is only done for A, B, and C slots, not the larger BC or ABC slots.
68869  *
68870  *  There is call handling specific understanding in the A-B-C emitter to
68871  *  convert call setup and call instructions into indirect ones if necessary.
68872  */
68873 
68874 /* Code emission flags, passed in the 'opcode' field.  Opcode + flags
68875  * fit into 16 bits for now, so use duk_small_uint_t.
68876  */
68877 #define DUK__EMIT_FLAG_NO_SHUFFLE_A      (1 << 8)
68878 #define DUK__EMIT_FLAG_NO_SHUFFLE_B      (1 << 9)
68879 #define DUK__EMIT_FLAG_NO_SHUFFLE_C      (1 << 10)
68880 #define DUK__EMIT_FLAG_A_IS_SOURCE       (1 << 11)  /* slot A is a source (default: target) */
68881 #define DUK__EMIT_FLAG_B_IS_TARGET       (1 << 12)  /* slot B is a target (default: source) */
68882 #define DUK__EMIT_FLAG_C_IS_TARGET       (1 << 13)  /* slot C is a target (default: source) */
68883 #define DUK__EMIT_FLAG_BC_REGCONST       (1 << 14)  /* slots B and C are reg/const */
68884 #define DUK__EMIT_FLAG_RESERVE_JUMPSLOT  (1 << 15)  /* reserve a jumpslot after instr before target spilling, used for NEXTENUM */
68885 
68886 /* XXX: macro smaller than call? */
68887 DUK_LOCAL duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx) {
68888 	duk_compiler_func *func;
68889 	func = &comp_ctx->curr_func;
68890 	return (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &func->bw_code) / sizeof(duk_compiler_instr));
68891 }
68892 
68893 DUK_LOCAL duk_compiler_instr *duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc) {
68894 	DUK_ASSERT(pc >= 0);
68895 	DUK_ASSERT((duk_size_t) pc < (duk_size_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr)));
68896 	return ((duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code)) + pc;
68897 }
68898 
68899 /* emit instruction; could return PC but that's not needed in the majority
68900  * of cases.
68901  */
68902 DUK_LOCAL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins) {
68903 #if defined(DUK_USE_PC2LINE)
68904 	duk_int_t line;
68905 #endif
68906 	duk_compiler_instr *instr;
68907 
68908 	DUK_DDD(DUK_DDDPRINT("duk__emit: 0x%08lx curr_token.start_line=%ld prev_token.start_line=%ld pc=%ld --> %!I",
68909 	                     (unsigned long) ins,
68910 	                     (long) comp_ctx->curr_token.start_line,
68911 	                     (long) comp_ctx->prev_token.start_line,
68912 	                     (long) duk__get_current_pc(comp_ctx),
68913 	                     (duk_instr_t) ins));
68914 
68915 	instr = (duk_compiler_instr *) (void *) DUK_BW_ENSURE_GETPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
68916 	DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
68917 
68918 #if defined(DUK_USE_PC2LINE)
68919 	/* The line number tracking is a bit inconsistent right now, which
68920 	 * affects debugger accuracy.  Mostly call sites emit opcodes when
68921 	 * they have parsed a token (say a terminating semicolon) and called
68922 	 * duk__advance().  In this case the line number of the previous
68923 	 * token is the most accurate one (except in prologue where
68924 	 * prev_token.start_line is 0).  This is probably not 100% correct
68925 	 * right now.
68926 	 */
68927 	/* approximation, close enough */
68928 	line = comp_ctx->prev_token.start_line;
68929 	if (line == 0) {
68930 		line = comp_ctx->curr_token.start_line;
68931 	}
68932 #endif
68933 
68934 	instr->ins = ins;
68935 #if defined(DUK_USE_PC2LINE)
68936 	instr->line = (duk_uint32_t) line;
68937 #endif
68938 #if defined(DUK_USE_DEBUGGER_SUPPORT)
68939 	if (line < comp_ctx->curr_func.min_line) {
68940 		comp_ctx->curr_func.min_line = line;
68941 	}
68942 	if (line > comp_ctx->curr_func.max_line) {
68943 		comp_ctx->curr_func.max_line = line;
68944 	}
68945 #endif
68946 
68947 	/* Limit checks for bytecode byte size and line number. */
68948 	if (DUK_UNLIKELY(DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) > DUK_USE_ESBC_MAX_BYTES)) {
68949 		goto fail_bc_limit;
68950 	}
68951 #if defined(DUK_USE_PC2LINE) && defined(DUK_USE_ESBC_LIMITS)
68952 #if defined(DUK_USE_BUFLEN16)
68953 	/* Buffer length is bounded to 0xffff automatically, avoid compile warning. */
68954 	if (DUK_UNLIKELY(line > DUK_USE_ESBC_MAX_LINENUMBER)) {
68955 		goto fail_bc_limit;
68956 	}
68957 #else
68958 	if (DUK_UNLIKELY(line > DUK_USE_ESBC_MAX_LINENUMBER)) {
68959 		goto fail_bc_limit;
68960 	}
68961 #endif
68962 #endif
68963 
68964 	return;
68965 
68966   fail_bc_limit:
68967 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_BYTECODE_LIMIT);
68968 	DUK_WO_NORETURN(return;);
68969 }
68970 
68971 /* Update function min/max line from current token.  Needed to improve
68972  * function line range information for debugging, so that e.g. opening
68973  * curly brace is covered by line range even when no opcodes are emitted
68974  * for the line containing the brace.
68975  */
68976 DUK_LOCAL void duk__update_lineinfo_currtoken(duk_compiler_ctx *comp_ctx) {
68977 #if defined(DUK_USE_DEBUGGER_SUPPORT)
68978 	duk_int_t line;
68979 
68980 	line = comp_ctx->curr_token.start_line;
68981 	if (line == 0) {
68982 		return;
68983 	}
68984 	if (line < comp_ctx->curr_func.min_line) {
68985 		comp_ctx->curr_func.min_line = line;
68986 	}
68987 	if (line > comp_ctx->curr_func.max_line) {
68988 		comp_ctx->curr_func.max_line = line;
68989 	}
68990 #else
68991 	DUK_UNREF(comp_ctx);
68992 #endif
68993 }
68994 
68995 DUK_LOCAL void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op) {
68996 	duk__emit(comp_ctx, DUK_ENC_OP_ABC(op, 0));
68997 }
68998 
68999 /* Important main primitive. */
69000 DUK_LOCAL void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t b, duk_regconst_t c) {
69001 	duk_instr_t ins = 0;
69002 	duk_int_t a_out = -1;
69003 	duk_int_t b_out = -1;
69004 	duk_int_t c_out = -1;
69005 	duk_int_t tmp;
69006 	duk_small_uint_t op = op_flags & 0xffU;
69007 
69008 	DUK_DDD(DUK_DDDPRINT("emit: op_flags=%04lx, a=%ld, b=%ld, c=%ld",
69009 	                     (unsigned long) op_flags, (long) a, (long) b, (long) c));
69010 
69011 	/* We could rely on max temp/const checks: if they don't exceed BC
69012 	 * limit, nothing here can either (just asserts would be enough).
69013 	 * Currently we check for the limits, which provides additional
69014 	 * protection against creating invalid bytecode due to compiler
69015 	 * bugs.
69016 	 */
69017 
69018 	DUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN);  /* unsigned */
69019 	DUK_ASSERT((op_flags & 0xff) <= DUK_BC_OP_MAX);
69020 	DUK_ASSERT(DUK__ISREG(a));
69021 	DUK_ASSERT(b != -1);  /* Not 'none'. */
69022 	DUK_ASSERT(c != -1);  /* Not 'none'. */
69023 
69024 	/* Input shuffling happens before the actual operation, while output
69025 	 * shuffling happens afterwards.  Output shuffling decisions are still
69026 	 * made at the same time to reduce branch clutter; output shuffle decisions
69027 	 * are recorded into X_out variables.
69028 	 */
69029 
69030 	/* Slot A: currently no support for reg/const. */
69031 
69032 #if defined(DUK_USE_SHUFFLE_TORTURE)
69033 	if (a <= DUK_BC_A_MAX && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A)) {
69034 #else
69035 	if (a <= DUK_BC_A_MAX) {
69036 #endif
69037 		;
69038 	} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A) {
69039 		DUK_D(DUK_DPRINT("out of regs: 'a' (reg) needs shuffling but shuffle prohibited, a: %ld", (long) a));
69040 		goto error_outofregs;
69041 	} else if (a <= DUK_BC_BC_MAX) {
69042 		comp_ctx->curr_func.needs_shuffle = 1;
69043 		tmp = comp_ctx->curr_func.shuffle1;
69044 		if (op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) {
69045 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, a));
69046 		} else {
69047 			/* Output shuffle needed after main operation */
69048 			a_out = a;
69049 
69050 			/* The DUK_OP_CSVAR output shuffle assumes shuffle registers are
69051 			 * consecutive.
69052 			 */
69053 			DUK_ASSERT((comp_ctx->curr_func.shuffle1 == 0 && comp_ctx->curr_func.shuffle2 == 0) ||
69054 			           (comp_ctx->curr_func.shuffle2 == comp_ctx->curr_func.shuffle1 + 1));
69055 			if (op == DUK_OP_CSVAR) {
69056 				/* For CSVAR the limit is one smaller because output shuffle
69057 				 * must be able to express 'a + 1' in BC.
69058 				 */
69059 				if (a + 1 > DUK_BC_BC_MAX) {
69060 					goto error_outofregs;
69061 				}
69062 			}
69063 		}
69064 		a = tmp;
69065 	} else {
69066 		DUK_D(DUK_DPRINT("out of regs: 'a' (reg) needs shuffling but does not fit into BC, a: %ld", (long) a));
69067 		goto error_outofregs;
69068 	}
69069 
69070 	/* Slot B: reg/const support, mapped to bit 0 of opcode. */
69071 
69072 	if ((b & DUK__CONST_MARKER) != 0) {
69073 		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B) == 0);
69074 		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_B_IS_TARGET) == 0);
69075 		b = b & ~DUK__CONST_MARKER;
69076 #if defined(DUK_USE_SHUFFLE_TORTURE)
69077 		if (0) {
69078 #else
69079 		if (b <= 0xff) {
69080 #endif
69081 			if (op_flags & DUK__EMIT_FLAG_BC_REGCONST) {
69082 				/* Opcode follows B/C reg/const convention. */
69083 				DUK_ASSERT((op & 0x01) == 0);
69084 				ins |= DUK_ENC_OP_A_B_C(0x01, 0, 0, 0);  /* const flag for B */
69085 			} else {
69086 				DUK_D(DUK_DPRINT("B is const, opcode is not B/C reg/const: %x", op_flags));
69087 			}
69088 		} else if (b <= DUK_BC_BC_MAX) {
69089 			comp_ctx->curr_func.needs_shuffle = 1;
69090 			tmp = comp_ctx->curr_func.shuffle2;
69091 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDCONST, tmp, b));
69092 			b = tmp;
69093 		} else {
69094 			DUK_D(DUK_DPRINT("out of regs: 'b' (const) needs shuffling but does not fit into BC, b: %ld", (long) b));
69095 			goto error_outofregs;
69096 		}
69097 	} else {
69098 #if defined(DUK_USE_SHUFFLE_TORTURE)
69099 		if (b <= 0xff && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B)) {
69100 #else
69101 		if (b <= 0xff) {
69102 #endif
69103 			;
69104 		} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B) {
69105 			if (b > DUK_BC_B_MAX) {
69106 				/* Note: 0xff != DUK_BC_B_MAX */
69107 				DUK_D(DUK_DPRINT("out of regs: 'b' (reg) needs shuffling but shuffle prohibited, b: %ld", (long) b));
69108 				goto error_outofregs;
69109 			}
69110 		} else if (b <= DUK_BC_BC_MAX) {
69111 			comp_ctx->curr_func.needs_shuffle = 1;
69112 			tmp = comp_ctx->curr_func.shuffle2;
69113 			if (op_flags & DUK__EMIT_FLAG_B_IS_TARGET) {
69114 				/* Output shuffle needed after main operation */
69115 				b_out = b;
69116 			}
69117 			if (!(op_flags & DUK__EMIT_FLAG_B_IS_TARGET)) {
69118 				if (op == DUK_OP_MPUTOBJ || op == DUK_OP_MPUTARR) {
69119 					/* Special handling for MPUTOBJ/MPUTARR shuffling.
69120 					 * For each, slot B identifies the first register of a range
69121 					 * of registers, so normal shuffling won't work.  Instead,
69122 					 * an indirect version of the opcode is used.
69123 					 */
69124 					DUK_ASSERT((op_flags & DUK__EMIT_FLAG_B_IS_TARGET) == 0);
69125 					duk__emit_load_int32_noshuffle(comp_ctx, tmp, b);
69126 					DUK_ASSERT(DUK_OP_MPUTOBJI == DUK_OP_MPUTOBJ + 1);
69127 					DUK_ASSERT(DUK_OP_MPUTARRI == DUK_OP_MPUTARR + 1);
69128 					op_flags++;  /* indirect opcode follows direct */
69129 				} else {
69130 					duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, b));
69131 				}
69132 			}
69133 			b = tmp;
69134 		} else {
69135 			DUK_D(DUK_DPRINT("out of regs: 'b' (reg) needs shuffling but does not fit into BC, b: %ld", (long) b));
69136 			goto error_outofregs;
69137 		}
69138 	}
69139 
69140 	/* Slot C: reg/const support, mapped to bit 1 of opcode. */
69141 
69142 	if ((c & DUK__CONST_MARKER) != 0) {
69143 		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C) == 0);
69144 		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_C_IS_TARGET) == 0);
69145 		c = c & ~DUK__CONST_MARKER;
69146 #if defined(DUK_USE_SHUFFLE_TORTURE)
69147 		if (0) {
69148 #else
69149 		if (c <= 0xff) {
69150 #endif
69151 			if (op_flags & DUK__EMIT_FLAG_BC_REGCONST) {
69152 				/* Opcode follows B/C reg/const convention. */
69153 				DUK_ASSERT((op & 0x02) == 0);
69154 				ins |= DUK_ENC_OP_A_B_C(0x02, 0, 0, 0);  /* const flag for C */
69155 			} else {
69156 				DUK_D(DUK_DPRINT("C is const, opcode is not B/C reg/const: %x", op_flags));
69157 			}
69158 		} else if (c <= DUK_BC_BC_MAX) {
69159 			comp_ctx->curr_func.needs_shuffle = 1;
69160 			tmp = comp_ctx->curr_func.shuffle3;
69161 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDCONST, tmp, c));
69162 			c = tmp;
69163 		} else {
69164 			DUK_D(DUK_DPRINT("out of regs: 'c' (const) needs shuffling but does not fit into BC, c: %ld", (long) c));
69165 			goto error_outofregs;
69166 		}
69167 	} else {
69168 #if defined(DUK_USE_SHUFFLE_TORTURE)
69169 		if (c <= 0xff && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C)) {
69170 #else
69171 		if (c <= 0xff) {
69172 #endif
69173 			;
69174 		} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C) {
69175 			if (c > DUK_BC_C_MAX) {
69176 				/* Note: 0xff != DUK_BC_C_MAX */
69177 				DUK_D(DUK_DPRINT("out of regs: 'c' (reg) needs shuffling but shuffle prohibited, c: %ld", (long) c));
69178 				goto error_outofregs;
69179 			}
69180 		} else if (c <= DUK_BC_BC_MAX) {
69181 			comp_ctx->curr_func.needs_shuffle = 1;
69182 			tmp = comp_ctx->curr_func.shuffle3;
69183 			if (op_flags & DUK__EMIT_FLAG_C_IS_TARGET) {
69184 				/* Output shuffle needed after main operation */
69185 				c_out = c;
69186 			} else {
69187 				duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, c));
69188 			}
69189 			c = tmp;
69190 		} else {
69191 			DUK_D(DUK_DPRINT("out of regs: 'c' (reg) needs shuffling but does not fit into BC, c: %ld", (long) c));
69192 			goto error_outofregs;
69193 		}
69194 	}
69195 
69196 	/* Main operation */
69197 
69198 	DUK_ASSERT(a >= DUK_BC_A_MIN);
69199 	DUK_ASSERT(a <= DUK_BC_A_MAX);
69200 	DUK_ASSERT(b >= DUK_BC_B_MIN);
69201 	DUK_ASSERT(b <= DUK_BC_B_MAX);
69202 	DUK_ASSERT(c >= DUK_BC_C_MIN);
69203 	DUK_ASSERT(c <= DUK_BC_C_MAX);
69204 
69205 	ins |= DUK_ENC_OP_A_B_C(op_flags & 0xff, a, b, c);
69206 	duk__emit(comp_ctx, ins);
69207 
69208 	/* NEXTENUM needs a jump slot right after the main instruction.
69209 	 * When the JUMP is taken, output spilling is not needed so this
69210 	 * workaround is possible.  The jump slot PC is exceptionally
69211 	 * plumbed through comp_ctx to minimize call sites.
69212 	 */
69213 	if (op_flags & DUK__EMIT_FLAG_RESERVE_JUMPSLOT) {
69214 		comp_ctx->emit_jumpslot_pc = duk__get_current_pc(comp_ctx);
69215 		duk__emit_abc(comp_ctx, DUK_OP_JUMP, 0);
69216 	}
69217 
69218 	/* Output shuffling: only one output register is realistically possible.
69219 	 *
69220 	 * (Zero would normally be an OK marker value: if the target register
69221 	 * was zero, it would never be shuffled.  But with DUK_USE_SHUFFLE_TORTURE
69222 	 * this is no longer true, so use -1 as a marker instead.)
69223 	 */
69224 
69225 	if (a_out >= 0) {
69226 		DUK_ASSERT(b_out < 0);
69227 		DUK_ASSERT(c_out < 0);
69228 		duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, a, a_out));
69229 
69230 		if (op == DUK_OP_CSVAR) {
69231 			/* Special handling for CSVAR shuffling.  The variable lookup
69232 			 * results in a <value, this binding> pair in successive
69233 			 * registers so use two shuffle registers and two output
69234 			 * loads.  (In practice this is dead code because temp/const
69235 			 * limit is reached first.)
69236 			 */
69237 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, a + 1, a_out + 1));
69238 		}
69239 	} else if (b_out >= 0) {
69240 		DUK_ASSERT(a_out < 0);
69241 		DUK_ASSERT(c_out < 0);
69242 		duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, b, b_out));
69243 	} else if (c_out >= 0) {
69244 		DUK_ASSERT(b_out < 0);
69245 		DUK_ASSERT(c_out < 0);
69246 		duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, c, c_out));
69247 	}
69248 
69249 	return;
69250 
69251  error_outofregs:
69252 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
69253 	DUK_WO_NORETURN(return;);
69254 }
69255 
69256 /* For many of the helpers below it'd be technically correct to add
69257  * "no shuffle" flags for parameters passed in as zero.  For example,
69258  * duk__emit_a_b() should call duk__emit_a_b_c() with C set to 0, and
69259  * DUK__EMIT_FLAG_NO_SHUFFLE_C added to op_flags.  However, since the
69260  * C value is 0, it'll never get shuffled so adding the flag is just
69261  * unnecessary additional code.  This is unfortunately not true for
69262  * "shuffle torture" mode which needs special handling.
69263  */
69264 
69265 DUK_LOCAL void duk__emit_a_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t b) {
69266 #if defined(DUK_USE_SHUFFLE_TORTURE)
69267 	op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_C;
69268 #endif
69269 	duk__emit_a_b_c(comp_ctx, op_flags, a, b, 0);
69270 }
69271 
69272 DUK_LOCAL void duk__emit_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b, duk_regconst_t c) {
69273 #if defined(DUK_USE_SHUFFLE_TORTURE)
69274 	op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_A;
69275 #endif
69276 	duk__emit_a_b_c(comp_ctx, op_flags, 0, b, c);
69277 }
69278 
69279 #if 0  /* unused */
69280 DUK_LOCAL void duk__emit_a(duk_compiler_ctx *comp_ctx, int op_flags, int a) {
69281 #if defined(DUK_USE_SHUFFLE_TORTURE)
69282 	op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_B | DUK__EMIT_FLAG_NO_SHUFFLE_C;
69283 #endif
69284 	duk__emit_a_b_c(comp_ctx, op_flags, a, 0, 0);
69285 }
69286 #endif
69287 
69288 #if 0  /* unused */
69289 DUK_LOCAL void duk__emit_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b) {
69290 #if defined(DUK_USE_SHUFFLE_TORTURE)
69291 	op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_NO_SHUFFLE_C;
69292 #endif
69293 	duk__emit_a_b_c(comp_ctx, op_flags, 0, b, 0);
69294 }
69295 #endif
69296 
69297 DUK_LOCAL void duk__emit_a_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t bc) {
69298 	duk_instr_t ins;
69299 	duk_int_t tmp;
69300 
69301 	/* allow caller to give a const number with the DUK__CONST_MARKER */
69302 	DUK_ASSERT(bc != -1);  /* Not 'none'. */
69303 	bc = bc & (~DUK__CONST_MARKER);
69304 
69305 	DUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN);  /* unsigned */
69306 	DUK_ASSERT((op_flags & 0xff) <= DUK_BC_OP_MAX);
69307 	DUK_ASSERT(bc >= DUK_BC_BC_MIN);
69308 	DUK_ASSERT(bc <= DUK_BC_BC_MAX);
69309 	DUK_ASSERT((bc & DUK__CONST_MARKER) == 0);
69310 
69311 	if (bc <= DUK_BC_BC_MAX) {
69312 		;
69313 	} else {
69314 		/* No BC shuffling now. */
69315 		goto error_outofregs;
69316 	}
69317 
69318 #if defined(DUK_USE_SHUFFLE_TORTURE)
69319 	if (a <= DUK_BC_A_MAX && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A)) {
69320 #else
69321 	if (a <= DUK_BC_A_MAX) {
69322 #endif
69323 		ins = DUK_ENC_OP_A_BC(op_flags & 0xff, a, bc);
69324 		duk__emit(comp_ctx, ins);
69325 	} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A) {
69326 		goto error_outofregs;
69327 	} else if ((op_flags & 0xf0U) == DUK_OP_CALL0) {
69328 		comp_ctx->curr_func.needs_shuffle = 1;
69329 		tmp = comp_ctx->curr_func.shuffle1;
69330 		duk__emit_load_int32_noshuffle(comp_ctx, tmp, a);
69331 		op_flags |= DUK_BC_CALL_FLAG_INDIRECT;
69332 		ins = DUK_ENC_OP_A_BC(op_flags & 0xff, tmp, bc);
69333 		duk__emit(comp_ctx, ins);
69334 	} else if (a <= DUK_BC_BC_MAX) {
69335 		comp_ctx->curr_func.needs_shuffle = 1;
69336 		tmp = comp_ctx->curr_func.shuffle1;
69337 		ins = DUK_ENC_OP_A_BC(op_flags & 0xff, tmp, bc);
69338 		if (op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) {
69339 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, a));
69340 			duk__emit(comp_ctx, ins);
69341 		} else {
69342 			duk__emit(comp_ctx, ins);
69343 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, tmp, a));
69344 		}
69345 	} else {
69346 		goto error_outofregs;
69347 	}
69348 	return;
69349 
69350  error_outofregs:
69351 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
69352 	DUK_WO_NORETURN(return;);
69353 }
69354 
69355 DUK_LOCAL void duk__emit_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t bc) {
69356 #if defined(DUK_USE_SHUFFLE_TORTURE)
69357 	op |= DUK__EMIT_FLAG_NO_SHUFFLE_A;
69358 #endif
69359 	duk__emit_a_bc(comp_ctx, op, 0, bc);
69360 }
69361 
69362 DUK_LOCAL void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t abc) {
69363 	duk_instr_t ins;
69364 
69365 	DUK_ASSERT_DISABLE(op >= DUK_BC_OP_MIN);  /* unsigned */
69366 	DUK_ASSERT(op <= DUK_BC_OP_MAX);
69367 	DUK_ASSERT_DISABLE(abc >= DUK_BC_ABC_MIN);  /* unsigned */
69368 	DUK_ASSERT(abc <= DUK_BC_ABC_MAX);
69369 	DUK_ASSERT((abc & DUK__CONST_MARKER) == 0);
69370 	DUK_ASSERT(abc != -1);  /* Not 'none'. */
69371 
69372 	if (abc <= DUK_BC_ABC_MAX) {
69373 		;
69374 	} else {
69375 		goto error_outofregs;
69376 	}
69377 	ins = DUK_ENC_OP_ABC(op, abc);
69378 	DUK_DDD(DUK_DDDPRINT("duk__emit_abc: 0x%08lx line=%ld pc=%ld op=%ld (%!X) abc=%ld (%!I)",
69379 	                     (unsigned long) ins, (long) comp_ctx->curr_token.start_line,
69380 	                     (long) duk__get_current_pc(comp_ctx), (long) op, (long) op,
69381 	                     (long) abc, (duk_instr_t) ins));
69382 	duk__emit(comp_ctx, ins);
69383 	return;
69384 
69385  error_outofregs:
69386 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
69387 	DUK_WO_NORETURN(return;);
69388 }
69389 
69390 DUK_LOCAL void duk__emit_load_int32_raw(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val, duk_small_uint_t op_flags) {
69391 	/* XXX: Shuffling support could be implemented here so that LDINT+LDINTX
69392 	 * would only shuffle once (instead of twice).  The current code works
69393 	 * though, and has a smaller compiler footprint.
69394 	 */
69395 
69396 	if ((val >= (duk_int32_t) DUK_BC_BC_MIN - (duk_int32_t) DUK_BC_LDINT_BIAS) &&
69397 	    (val <= (duk_int32_t) DUK_BC_BC_MAX - (duk_int32_t) DUK_BC_LDINT_BIAS)) {
69398 		DUK_DDD(DUK_DDDPRINT("emit LDINT to reg %ld for %ld", (long) reg, (long) val));
69399 		duk__emit_a_bc(comp_ctx, DUK_OP_LDINT | op_flags, reg, (duk_regconst_t) (val + (duk_int32_t) DUK_BC_LDINT_BIAS));
69400 	} else {
69401 		duk_int32_t hi = val >> DUK_BC_LDINTX_SHIFT;
69402 		duk_int32_t lo = val & ((((duk_int32_t) 1) << DUK_BC_LDINTX_SHIFT) - 1);
69403 		DUK_ASSERT(lo >= 0);
69404 		DUK_DDD(DUK_DDDPRINT("emit LDINT+LDINTX to reg %ld for %ld -> hi %ld, lo %ld",
69405 		                     (long) reg, (long) val, (long) hi, (long) lo));
69406 		duk__emit_a_bc(comp_ctx, DUK_OP_LDINT | op_flags, reg, (duk_regconst_t) (hi + (duk_int32_t) DUK_BC_LDINT_BIAS));
69407 		duk__emit_a_bc(comp_ctx, DUK_OP_LDINTX | op_flags, reg, (duk_regconst_t) lo);
69408 	}
69409 }
69410 
69411 DUK_LOCAL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val) {
69412 	duk__emit_load_int32_raw(comp_ctx, reg, val, 0 /*op_flags*/);
69413 }
69414 
69415 #if defined(DUK_USE_SHUFFLE_TORTURE)
69416 /* Used by duk__emit*() calls so that we don't shuffle the loadints that
69417  * are needed to handle indirect opcodes.
69418  */
69419 DUK_LOCAL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val) {
69420 	duk__emit_load_int32_raw(comp_ctx, reg, val, DUK__EMIT_FLAG_NO_SHUFFLE_A /*op_flags*/);
69421 }
69422 #else
69423 DUK_LOCAL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val) {
69424 	/* When torture not enabled, can just use the same helper because
69425 	 * 'reg' won't get spilled.
69426 	 */
69427 	DUK_ASSERT(reg <= DUK_BC_A_MAX);
69428 	duk__emit_load_int32(comp_ctx, reg, val);
69429 }
69430 #endif
69431 
69432 DUK_LOCAL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc) {
69433 	duk_int_t curr_pc;
69434 	duk_int_t offset;
69435 
69436 	curr_pc = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr));
69437 	offset = (duk_int_t) target_pc - (duk_int_t) curr_pc - 1;
69438 	DUK_ASSERT(offset + DUK_BC_JUMP_BIAS >= DUK_BC_ABC_MIN);
69439 	DUK_ASSERT(offset + DUK_BC_JUMP_BIAS <= DUK_BC_ABC_MAX);
69440 	duk__emit_abc(comp_ctx, DUK_OP_JUMP, (duk_regconst_t) (offset + DUK_BC_JUMP_BIAS));
69441 }
69442 
69443 DUK_LOCAL duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx) {
69444 	duk_int_t ret;
69445 
69446 	ret = duk__get_current_pc(comp_ctx);  /* useful for patching jumps later */
69447 	duk__emit_op_only(comp_ctx, DUK_OP_JUMP);
69448 	return ret;
69449 }
69450 
69451 /* Insert an empty jump in the middle of code emitted earlier.  This is
69452  * currently needed for compiling for-in.
69453  */
69454 DUK_LOCAL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc) {
69455 #if defined(DUK_USE_PC2LINE)
69456 	duk_int_t line;
69457 #endif
69458 	duk_compiler_instr *instr;
69459 	duk_size_t offset;
69460 
69461 	DUK_ASSERT(jump_pc >= 0);
69462 	offset = (duk_size_t) jump_pc * sizeof(duk_compiler_instr);
69463 	instr = (duk_compiler_instr *) (void *)
69464 	        DUK_BW_INSERT_ENSURE_AREA(comp_ctx->thr,
69465 	                                  &comp_ctx->curr_func.bw_code,
69466 	                                  offset,
69467 	                                  sizeof(duk_compiler_instr));
69468 
69469 #if defined(DUK_USE_PC2LINE)
69470 	line = comp_ctx->curr_token.start_line;  /* approximation, close enough */
69471 #endif
69472 	instr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, 0);
69473 #if defined(DUK_USE_PC2LINE)
69474 	instr->line = (duk_uint32_t) line;
69475 #endif
69476 
69477 	DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
69478 	if (DUK_UNLIKELY(DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) > DUK_USE_ESBC_MAX_BYTES)) {
69479 		goto fail_bc_limit;
69480 	}
69481 	return;
69482 
69483   fail_bc_limit:
69484 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_BYTECODE_LIMIT);
69485 	DUK_WO_NORETURN(return;);
69486 }
69487 
69488 /* Does not assume that jump_pc contains a DUK_OP_JUMP previously; this is intentional
69489  * to allow e.g. an INVALID opcode be overwritten with a JUMP (label management uses this).
69490  */
69491 DUK_LOCAL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc) {
69492 	duk_compiler_instr *instr;
69493 	duk_int_t offset;
69494 
69495 	/* allow negative PCs, behave as a no-op */
69496 	if (jump_pc < 0) {
69497 		DUK_DDD(DUK_DDDPRINT("duk__patch_jump(): nop call, jump_pc=%ld (<0), target_pc=%ld",
69498 		                     (long) jump_pc, (long) target_pc));
69499 		return;
69500 	}
69501 	DUK_ASSERT(jump_pc >= 0);
69502 
69503 	/* XXX: range assert */
69504 	instr = duk__get_instr_ptr(comp_ctx, jump_pc);
69505 	DUK_ASSERT(instr != NULL);
69506 
69507 	/* XXX: range assert */
69508 	offset = target_pc - jump_pc - 1;
69509 
69510 	instr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, offset + DUK_BC_JUMP_BIAS);
69511 	DUK_DDD(DUK_DDDPRINT("duk__patch_jump(): jump_pc=%ld, target_pc=%ld, offset=%ld",
69512 	                     (long) jump_pc, (long) target_pc, (long) offset));
69513 }
69514 
69515 DUK_LOCAL void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc) {
69516 	duk__patch_jump(comp_ctx, jump_pc, duk__get_current_pc(comp_ctx));
69517 }
69518 
69519 DUK_LOCAL void duk__patch_trycatch(duk_compiler_ctx *comp_ctx, duk_int_t ldconst_pc, duk_int_t trycatch_pc, duk_regconst_t reg_catch, duk_regconst_t const_varname, duk_small_uint_t flags) {
69520 	duk_compiler_instr *instr;
69521 
69522 	DUK_ASSERT(DUK__ISREG(reg_catch));
69523 
69524 	instr = duk__get_instr_ptr(comp_ctx, ldconst_pc);
69525 	DUK_ASSERT(DUK_DEC_OP(instr->ins) == DUK_OP_LDCONST);
69526 	DUK_ASSERT(instr != NULL);
69527 	if (const_varname & DUK__CONST_MARKER) {
69528 		/* Have a catch variable. */
69529 		const_varname = const_varname & (~DUK__CONST_MARKER);
69530 		if (reg_catch > DUK_BC_BC_MAX || const_varname > DUK_BC_BC_MAX) {
69531 			/* Catch attempts to use out-of-range reg/const.  Without this
69532 			 * check Duktape 0.12.0 could generate invalid code which caused
69533 			 * an assert failure on execution.  This error is triggered e.g.
69534 			 * for functions with a lot of constants and a try-catch statement.
69535 			 * Shuffling or opcode semantics change is needed to fix the issue.
69536 			 * See: test-bug-trycatch-many-constants.js.
69537 			 */
69538 			DUK_D(DUK_DPRINT("failed to patch trycatch: flags=%ld, reg_catch=%ld, const_varname=%ld (0x%08lx)",
69539 			                 (long) flags, (long) reg_catch, (long) const_varname, (long) const_varname));
69540 			DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
69541 			DUK_WO_NORETURN(return;);
69542 		}
69543 		instr->ins |= DUK_ENC_OP_A_BC(0, 0, const_varname);
69544 	} else {
69545 		/* No catch variable, e.g. a try-finally; replace LDCONST with
69546 		 * NOP to avoid a bogus LDCONST.
69547 		 */
69548 		instr->ins = DUK_ENC_OP(DUK_OP_NOP);
69549 	}
69550 
69551 	instr = duk__get_instr_ptr(comp_ctx, trycatch_pc);
69552 	DUK_ASSERT(instr != NULL);
69553 	DUK_ASSERT_DISABLE(flags >= DUK_BC_A_MIN);
69554 	DUK_ASSERT(flags <= DUK_BC_A_MAX);
69555 	instr->ins = DUK_ENC_OP_A_BC(DUK_OP_TRYCATCH, flags, reg_catch);
69556 }
69557 
69558 DUK_LOCAL void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst) {
69559 	duk_small_uint_t op;
69560 
69561 	op = DUK__ISREG(regconst) ? DUK_OP_IFFALSE_R : DUK_OP_IFFALSE_C;
69562 	duk__emit_bc(comp_ctx, op, regconst);  /* helper will remove const flag */
69563 }
69564 
69565 DUK_LOCAL void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst) {
69566 	duk_small_uint_t op;
69567 
69568 	op = DUK__ISREG(regconst) ? DUK_OP_IFTRUE_R : DUK_OP_IFTRUE_C;
69569 	duk__emit_bc(comp_ctx, op, regconst);  /* helper will remove const flag */
69570 }
69571 
69572 DUK_LOCAL void duk__emit_invalid(duk_compiler_ctx *comp_ctx) {
69573 	duk__emit_op_only(comp_ctx, DUK_OP_INVALID);
69574 }
69575 
69576 /*
69577  *  Peephole optimizer for finished bytecode.
69578  *
69579  *  Does not remove opcodes; currently only straightens out unconditional
69580  *  jump chains which are generated by several control structures.
69581  */
69582 
69583 DUK_LOCAL void duk__peephole_optimize_bytecode(duk_compiler_ctx *comp_ctx) {
69584 	duk_compiler_instr *bc;
69585 	duk_small_uint_t iter;
69586 	duk_int_t i, n;
69587 	duk_int_t count_opt;
69588 
69589 	bc = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code);
69590 #if defined(DUK_USE_BUFLEN16)
69591 	/* No need to assert, buffer size maximum is 0xffff. */
69592 #else
69593 	DUK_ASSERT((duk_size_t) DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr) <= (duk_size_t) DUK_INT_MAX);  /* bytecode limits */
69594 #endif
69595 	n = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr));
69596 
69597 	for (iter = 0; iter < DUK_COMPILER_PEEPHOLE_MAXITER; iter++) {
69598 		count_opt = 0;
69599 
69600 		for (i = 0; i < n; i++) {
69601 			duk_instr_t ins;
69602 			duk_int_t target_pc1;
69603 			duk_int_t target_pc2;
69604 
69605 			ins = bc[i].ins;
69606 			if (DUK_DEC_OP(ins) != DUK_OP_JUMP) {
69607 				continue;
69608 			}
69609 
69610 			target_pc1 = i + 1 + (duk_int_t) DUK_DEC_ABC(ins) - (duk_int_t) DUK_BC_JUMP_BIAS;
69611 			DUK_DDD(DUK_DDDPRINT("consider jump at pc %ld; target_pc=%ld", (long) i, (long) target_pc1));
69612 			DUK_ASSERT(target_pc1 >= 0);
69613 			DUK_ASSERT(target_pc1 < n);
69614 
69615 			/* Note: if target_pc1 == i, we'll optimize a jump to itself.
69616 			 * This does not need to be checked for explicitly; the case
69617 			 * is rare and max iter breaks us out.
69618 			 */
69619 
69620 			ins = bc[target_pc1].ins;
69621 			if (DUK_DEC_OP(ins) != DUK_OP_JUMP) {
69622 				continue;
69623 			}
69624 
69625 			target_pc2 = target_pc1 + 1 + (duk_int_t) DUK_DEC_ABC(ins) - (duk_int_t) DUK_BC_JUMP_BIAS;
69626 
69627 			DUK_DDD(DUK_DDDPRINT("optimizing jump at pc %ld; old target is %ld -> new target is %ld",
69628 			                     (long) i, (long) target_pc1, (long) target_pc2));
69629 
69630 			bc[i].ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, target_pc2 - (i + 1) + DUK_BC_JUMP_BIAS);
69631 
69632 			count_opt++;
69633 		}
69634 
69635 		DUK_DD(DUK_DDPRINT("optimized %ld jumps on peephole round %ld", (long) count_opt, (long) (iter + 1)));
69636 
69637 		if (count_opt == 0) {
69638 			break;
69639 		}
69640 	}
69641 }
69642 
69643 /*
69644  *  Intermediate value helpers
69645  */
69646 
69647 /* Flags for intermediate value coercions.  A flag for using a forced reg
69648  * is not needed, the forced_reg argument suffices and generates better
69649  * code (it is checked as it is used).
69650  */
69651 /* XXX: DUK__IVAL_FLAG_REQUIRE_SHORT is passed but not currently implemented
69652  * by ispec/ivalue operations.
69653  */
69654 #define DUK__IVAL_FLAG_ALLOW_CONST          (1 << 0)  /* allow a constant to be returned */
69655 #define DUK__IVAL_FLAG_REQUIRE_TEMP         (1 << 1)  /* require a (mutable) temporary as a result (or a const if allowed) */
69656 #define DUK__IVAL_FLAG_REQUIRE_SHORT        (1 << 2)  /* require a short (8-bit) reg/const which fits into bytecode B/C slot */
69657 
69658 /* XXX: some code might benefit from DUK__SETTEMP_IFTEMP(thr,x) */
69659 
69660 #if 0  /* enable manually for dumping */
69661 #define DUK__DUMP_ISPEC(compctx,ispec) do { duk__dump_ispec((compctx), (ispec)); } while (0)
69662 #define DUK__DUMP_IVALUE(compctx,ivalue) do { duk__dump_ivalue((compctx), (ivalue)); } while (0)
69663 
69664 DUK_LOCAL void duk__dump_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *x) {
69665 	DUK_D(DUK_DPRINT("ispec dump: t=%ld regconst=0x%08lx, valstack_idx=%ld, value=%!T",
69666 	                 (long) x->t, (unsigned long) x->regconst, (long) x->valstack_idx,
69667 	                 duk_get_tval(comp_ctx->thr, x->valstack_idx)));
69668 }
69669 DUK_LOCAL void duk__dump_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
69670 	DUK_D(DUK_DPRINT("ivalue dump: t=%ld op=%ld "
69671 	                 "x1={t=%ld regconst=0x%08lx valstack_idx=%ld value=%!T} "
69672 	                 "x2={t=%ld regconst=0x%08lx valstack_idx=%ld value=%!T}",
69673 		         (long) x->t, (long) x->op,
69674 	                 (long) x->x1.t, (unsigned long) x->x1.regconst, (long) x->x1.valstack_idx,
69675 	                 duk_get_tval(comp_ctx->thr, x->x1.valstack_idx),
69676 	                 (long) x->x2.t, (unsigned long) x->x2.regconst, (long) x->x2.valstack_idx,
69677 	                 duk_get_tval(comp_ctx->thr, x->x2.valstack_idx)));
69678 }
69679 #else
69680 #define DUK__DUMP_ISPEC(comp_ctx,x) do {} while (0)
69681 #define DUK__DUMP_IVALUE(comp_ctx,x) do {} while (0)
69682 #endif
69683 
69684 DUK_LOCAL void duk__ivalue_regconst(duk_ivalue *x, duk_regconst_t regconst) {
69685 	x->t = DUK_IVAL_PLAIN;
69686 	x->x1.t = DUK_ISPEC_REGCONST;
69687 	x->x1.regconst = regconst;
69688 }
69689 
69690 DUK_LOCAL void duk__ivalue_plain_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
69691 	x->t = DUK_IVAL_PLAIN;
69692 	x->x1.t = DUK_ISPEC_VALUE;
69693 	duk_replace(comp_ctx->thr, x->x1.valstack_idx);
69694 }
69695 
69696 DUK_LOCAL void duk__ivalue_var_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
69697 	x->t = DUK_IVAL_VAR;
69698 	x->x1.t = DUK_ISPEC_VALUE;
69699 	duk_replace(comp_ctx->thr, x->x1.valstack_idx);
69700 }
69701 
69702 DUK_LOCAL_DECL void duk__ivalue_var_hstring(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_hstring *h) {
69703 	DUK_ASSERT(h != NULL);
69704 	duk_push_hstring(comp_ctx->thr, h);
69705 	duk__ivalue_var_fromstack(comp_ctx, x);
69706 }
69707 
69708 DUK_LOCAL void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst) {
69709 	dst->t = src->t;
69710 	dst->regconst = src->regconst;
69711 	duk_copy(comp_ctx->thr, src->valstack_idx, dst->valstack_idx);
69712 }
69713 
69714 DUK_LOCAL void duk__copy_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *src, duk_ivalue *dst) {
69715 	dst->t = src->t;
69716 	dst->op = src->op;
69717 	dst->x1.t = src->x1.t;
69718 	dst->x1.regconst = src->x1.regconst;
69719 	dst->x2.t = src->x2.t;
69720 	dst->x2.regconst = src->x2.regconst;
69721 	duk_copy(comp_ctx->thr, src->x1.valstack_idx, dst->x1.valstack_idx);
69722 	duk_copy(comp_ctx->thr, src->x2.valstack_idx, dst->x2.valstack_idx);
69723 }
69724 
69725 DUK_LOCAL duk_regconst_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_int_t num) {
69726 	duk_regconst_t res;
69727 
69728 	res = comp_ctx->curr_func.temp_next;
69729 	comp_ctx->curr_func.temp_next += num;
69730 
69731 	if (comp_ctx->curr_func.temp_next > DUK__MAX_TEMPS) {  /* == DUK__MAX_TEMPS is OK */
69732 		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_TEMP_LIMIT);
69733 		DUK_WO_NORETURN(return 0;);
69734 	}
69735 
69736 	/* maintain highest 'used' temporary, needed to figure out nregs of function */
69737 	if (comp_ctx->curr_func.temp_next > comp_ctx->curr_func.temp_max) {
69738 		comp_ctx->curr_func.temp_max = comp_ctx->curr_func.temp_next;
69739 	}
69740 
69741 	return res;
69742 }
69743 
69744 DUK_LOCAL duk_regconst_t duk__alloctemp(duk_compiler_ctx *comp_ctx) {
69745 	return duk__alloctemps(comp_ctx, 1);
69746 }
69747 
69748 DUK_LOCAL void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_regconst_t temp_next) {
69749 	comp_ctx->curr_func.temp_next = temp_next;
69750 	if (temp_next > comp_ctx->curr_func.temp_max) {
69751 		comp_ctx->curr_func.temp_max = temp_next;
69752 	}
69753 }
69754 
69755 /* get const for value at valstack top */
69756 DUK_LOCAL duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx) {
69757 	duk_hthread *thr = comp_ctx->thr;
69758 	duk_compiler_func *f = &comp_ctx->curr_func;
69759 	duk_tval *tv1;
69760 	duk_int_t i, n, n_check;
69761 
69762 	n = (duk_int_t) duk_get_length(thr, f->consts_idx);
69763 
69764 	tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
69765 	DUK_ASSERT(tv1 != NULL);
69766 
69767 #if defined(DUK_USE_FASTINT)
69768 	/* Explicit check for fastint downgrade. */
69769 	DUK_TVAL_CHKFAST_INPLACE_SLOW(tv1);
69770 #endif
69771 
69772 	/* Sanity workaround for handling functions with a large number of
69773 	 * constants at least somewhat reasonably.  Otherwise checking whether
69774 	 * we already have the constant would grow very slow (as it is O(N^2)).
69775 	 */
69776 	n_check = (n > DUK__GETCONST_MAX_CONSTS_CHECK ? DUK__GETCONST_MAX_CONSTS_CHECK : n);
69777 	for (i = 0; i < n_check; i++) {
69778 		duk_tval *tv2 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, f->h_consts, i);
69779 
69780 		/* Strict equality is NOT enough, because we cannot use the same
69781 		 * constant for e.g. +0 and -0.
69782 		 */
69783 		if (duk_js_samevalue(tv1, tv2)) {
69784 			DUK_DDD(DUK_DDDPRINT("reused existing constant for %!T -> const index %ld",
69785 			                     (duk_tval *) tv1, (long) i));
69786 			duk_pop(thr);
69787 			return (duk_regconst_t) i | (duk_regconst_t) DUK__CONST_MARKER;
69788 		}
69789 	}
69790 
69791 	if (n > DUK__MAX_CONSTS) {
69792 		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_CONST_LIMIT);
69793 		DUK_WO_NORETURN(return 0;);
69794 	}
69795 
69796 	DUK_DDD(DUK_DDDPRINT("allocating new constant for %!T -> const index %ld",
69797 	                     (duk_tval *) tv1, (long) n));
69798 	(void) duk_put_prop_index(thr, f->consts_idx, (duk_uarridx_t) n);  /* invalidates tv1, tv2 */
69799 	return (duk_regconst_t) n | (duk_regconst_t) DUK__CONST_MARKER;
69800 }
69801 
69802 DUK_LOCAL duk_bool_t duk__const_needs_refcount(duk_compiler_ctx *comp_ctx, duk_regconst_t rc) {
69803 #if defined(DUK_USE_REFERENCE_COUNTING)
69804 	duk_compiler_func *f = &comp_ctx->curr_func;
69805 	duk_bool_t ret;
69806 
69807 	DUK_ASSERT((rc & DUK__CONST_MARKER) == 0);  /* caller removes const marker */
69808 	(void) duk_get_prop_index(comp_ctx->thr, f->consts_idx, (duk_uarridx_t) rc);
69809 	ret = !duk_is_number(comp_ctx->thr, -1);  /* now only number/string, so conservative check */
69810 	duk_pop(comp_ctx->thr);
69811 	return ret;
69812 #else
69813 	DUK_UNREF(comp_ctx);
69814 	DUK_UNREF(rc);
69815 	DUK_ASSERT((rc & DUK__CONST_MARKER) == 0);  /* caller removes const marker */
69816 	return 0;
69817 #endif
69818 }
69819 
69820 /* Get the value represented by an duk_ispec to a register or constant.
69821  * The caller can control the result by indicating whether or not:
69822  *
69823  *   (1) a constant is allowed (sometimes the caller needs the result to
69824  *       be in a register)
69825  *
69826  *   (2) a temporary register is required (usually when caller requires
69827  *       the register to be safely mutable; normally either a bound
69828  *       register or a temporary register are both OK)
69829  *
69830  *   (3) a forced register target needs to be used
69831  *
69832  * Bytecode may be emitted to generate the necessary value.  The return
69833  * value is either a register or a constant.
69834  */
69835 
69836 DUK_LOCAL
69837 duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
69838                                          duk_ispec *x,
69839                                          duk_regconst_t forced_reg,
69840                                          duk_small_uint_t flags) {
69841 	duk_hthread *thr = comp_ctx->thr;
69842 
69843 	DUK_DDD(DUK_DDDPRINT("duk__ispec_toregconst_raw(): x={%ld:%ld:%!T}, "
69844 	                     "forced_reg=%ld, flags 0x%08lx: allow_const=%ld require_temp=%ld require_short=%ld",
69845 	                     (long) x->t,
69846 	                     (long) x->regconst,
69847 	                     (duk_tval *) duk_get_tval(thr, x->valstack_idx),
69848 	                     (long) forced_reg,
69849 	                     (unsigned long) flags,
69850 	                     (long) ((flags & DUK__IVAL_FLAG_ALLOW_CONST) ? 1 : 0),
69851 	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) ? 1 : 0),
69852 	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_SHORT) ? 1 : 0)));
69853 
69854 	switch (x->t) {
69855 	case DUK_ISPEC_VALUE: {
69856 		duk_tval *tv;
69857 
69858 		tv = DUK_GET_TVAL_POSIDX(thr, x->valstack_idx);
69859 		DUK_ASSERT(tv != NULL);
69860 
69861 		switch (DUK_TVAL_GET_TAG(tv)) {
69862 		case DUK_TAG_UNDEFINED: {
69863 			/* Note: although there is no 'undefined' literal, undefined
69864 			 * values can occur during compilation as a result of e.g.
69865 			 * the 'void' operator.
69866 			 */
69867 			duk_regconst_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
69868 			duk__emit_bc(comp_ctx, DUK_OP_LDUNDEF, dest);
69869 			return dest;
69870 		}
69871 		case DUK_TAG_NULL: {
69872 			duk_regconst_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
69873 			duk__emit_bc(comp_ctx, DUK_OP_LDNULL, dest);
69874 			return dest;
69875 		}
69876 		case DUK_TAG_BOOLEAN: {
69877 			duk_regconst_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
69878 			duk__emit_bc(comp_ctx,
69879 			             (DUK_TVAL_GET_BOOLEAN(tv) ? DUK_OP_LDTRUE : DUK_OP_LDFALSE),
69880 			             dest);
69881 			return dest;
69882 		}
69883 		case DUK_TAG_POINTER: {
69884 			DUK_UNREACHABLE();
69885 			break;
69886 		}
69887 		case DUK_TAG_STRING: {
69888 			duk_hstring *h;
69889 			duk_regconst_t dest;
69890 			duk_regconst_t constidx;
69891 
69892 			h = DUK_TVAL_GET_STRING(tv);
69893 			DUK_UNREF(h);
69894 			DUK_ASSERT(h != NULL);
69895 
69896 #if 0  /* XXX: to be implemented? */
69897 			/* Use special opcodes to load short strings */
69898 			if (DUK_HSTRING_GET_BYTELEN(h) <= 2) {
69899 				/* Encode into a single opcode (18 bits can encode 1-2 bytes + length indicator) */
69900 			} else if (DUK_HSTRING_GET_BYTELEN(h) <= 6) {
69901 				/* Encode into a double constant (53 bits can encode 6*8 = 48 bits + 3-bit length */
69902 			}
69903 #endif
69904 			duk_dup(thr, x->valstack_idx);
69905 			constidx = duk__getconst(comp_ctx);
69906 
69907 			if (flags & DUK__IVAL_FLAG_ALLOW_CONST) {
69908 				return constidx;
69909 			}
69910 
69911 			dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
69912 			duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, constidx);
69913 			return dest;
69914 		}
69915 		case DUK_TAG_OBJECT: {
69916 			DUK_UNREACHABLE();
69917 			break;
69918 		}
69919 		case DUK_TAG_BUFFER: {
69920 			DUK_UNREACHABLE();
69921 			break;
69922 		}
69923 		case DUK_TAG_LIGHTFUNC: {
69924 			DUK_UNREACHABLE();
69925 			break;
69926 		}
69927 #if defined(DUK_USE_FASTINT)
69928 		case DUK_TAG_FASTINT:
69929 #endif
69930 		default: {
69931 			/* number */
69932 			duk_regconst_t dest;
69933 			duk_regconst_t constidx;
69934 			duk_double_t dval;
69935 			duk_int32_t ival;
69936 
69937 			DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
69938 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
69939 			dval = DUK_TVAL_GET_NUMBER(tv);
69940 
69941 			if (!(flags & DUK__IVAL_FLAG_ALLOW_CONST)) {
69942 				/* A number can be loaded either through a constant, using
69943 				 * LDINT, or using LDINT+LDINTX.  LDINT is always a size win,
69944 				 * LDINT+LDINTX is not if the constant is used multiple times.
69945 				 * Currently always prefer LDINT+LDINTX over a double constant.
69946 				 */
69947 
69948 				if (duk_is_whole_get_int32_nonegzero(dval, &ival)) {
69949 					dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
69950 					duk__emit_load_int32(comp_ctx, dest, ival);
69951 					return dest;
69952 				}
69953 			}
69954 
69955 			duk_dup(thr, x->valstack_idx);
69956 			constidx = duk__getconst(comp_ctx);
69957 
69958 			if (flags & DUK__IVAL_FLAG_ALLOW_CONST) {
69959 				return constidx;
69960 			} else {
69961 				dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
69962 				duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, constidx);
69963 				return dest;
69964 			}
69965 		}
69966 		}  /* end switch */
69967 		goto fail_internal;  /* never here */
69968 	}
69969 	case DUK_ISPEC_REGCONST: {
69970 		if (forced_reg >= 0) {
69971 			if (DUK__ISCONST(x->regconst)) {
69972 				duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, forced_reg, x->regconst);
69973 			} else if (x->regconst != forced_reg) {
69974 				duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, forced_reg, x->regconst);
69975 			} else {
69976 				; /* already in correct reg */
69977 			}
69978 			return forced_reg;
69979 		}
69980 
69981 		DUK_ASSERT(forced_reg < 0);
69982 		if (DUK__ISCONST(x->regconst)) {
69983 			if (!(flags & DUK__IVAL_FLAG_ALLOW_CONST)) {
69984 				duk_regconst_t dest = DUK__ALLOCTEMP(comp_ctx);
69985 				duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, x->regconst);
69986 				return dest;
69987 			}
69988 			return x->regconst;
69989 		}
69990 
69991 		DUK_ASSERT(forced_reg < 0 && !DUK__ISCONST(x->regconst));
69992 		if ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) && !DUK__ISREG_TEMP(comp_ctx, x->regconst)) {
69993 			duk_regconst_t dest = DUK__ALLOCTEMP(comp_ctx);
69994 			duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, dest, x->regconst);
69995 			return dest;
69996 		}
69997 		return x->regconst;
69998 	}
69999 	default: {
70000 		break;  /* never here */
70001 	}
70002 	}
70003 
70004  fail_internal:
70005 	DUK_ERROR_INTERNAL(thr);
70006 	DUK_WO_NORETURN(return 0;);
70007 }
70008 
70009 DUK_LOCAL void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_regconst_t forced_reg) {
70010 	DUK_ASSERT(forced_reg >= 0);
70011 	(void) duk__ispec_toregconst_raw(comp_ctx, x, forced_reg, 0 /*flags*/);
70012 }
70013 
70014 /* Coerce an duk_ivalue to a 'plain' value by generating the necessary
70015  * arithmetic operations, property access, or variable access bytecode.
70016  * The duk_ivalue argument ('x') is converted into a plain value as a
70017  * side effect.
70018  */
70019 DUK_LOCAL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_regconst_t forced_reg) {
70020 	duk_hthread *thr = comp_ctx->thr;
70021 
70022 	DUK_DDD(DUK_DDDPRINT("duk__ivalue_toplain_raw(): x={t=%ld,op=%ld,x1={%ld:%ld:%!T},x2={%ld:%ld:%!T}}, "
70023 	                     "forced_reg=%ld",
70024 	                     (long) x->t, (long) x->op,
70025 	                     (long) x->x1.t, (long) x->x1.regconst,
70026 	                     (duk_tval *) duk_get_tval(thr, x->x1.valstack_idx),
70027 	                     (long) x->x2.t, (long) x->x2.regconst,
70028 	                     (duk_tval *) duk_get_tval(thr, x->x2.valstack_idx),
70029 	                     (long) forced_reg));
70030 
70031 	switch (x->t) {
70032 	case DUK_IVAL_PLAIN: {
70033 		return;
70034 	}
70035 	/* XXX: support unary arithmetic ivalues (useful?) */
70036 	case DUK_IVAL_ARITH: {
70037 		duk_regconst_t arg1;
70038 		duk_regconst_t arg2;
70039 		duk_regconst_t dest;
70040 		duk_tval *tv1;
70041 		duk_tval *tv2;
70042 
70043 		DUK_DDD(DUK_DDDPRINT("arith to plain conversion"));
70044 
70045 		/* inline arithmetic check for constant values */
70046 		/* XXX: use the exactly same arithmetic function here as in executor */
70047 		if (x->x1.t == DUK_ISPEC_VALUE && x->x2.t == DUK_ISPEC_VALUE && x->t == DUK_IVAL_ARITH) {
70048 			tv1 = DUK_GET_TVAL_POSIDX(thr, x->x1.valstack_idx);
70049 			tv2 = DUK_GET_TVAL_POSIDX(thr, x->x2.valstack_idx);
70050 			DUK_ASSERT(tv1 != NULL);
70051 			DUK_ASSERT(tv2 != NULL);
70052 
70053 			DUK_DDD(DUK_DDDPRINT("arith: tv1=%!T, tv2=%!T",
70054 			                     (duk_tval *) tv1,
70055 			                     (duk_tval *) tv2));
70056 
70057 			if (DUK_TVAL_IS_NUMBER(tv1) && DUK_TVAL_IS_NUMBER(tv2)) {
70058 				duk_double_t d1 = DUK_TVAL_GET_NUMBER(tv1);
70059 				duk_double_t d2 = DUK_TVAL_GET_NUMBER(tv2);
70060 				duk_double_t d3;
70061 				duk_bool_t accept_fold = 1;
70062 
70063 				DUK_DDD(DUK_DDDPRINT("arith inline check: d1=%lf, d2=%lf, op=%ld",
70064 				                     (double) d1, (double) d2, (long) x->op));
70065 				switch (x->op) {
70066 				case DUK_OP_ADD: {
70067 					d3 = d1 + d2;
70068 					break;
70069 				}
70070 				case DUK_OP_SUB: {
70071 					d3 = d1 - d2;
70072 					break;
70073 				}
70074 				case DUK_OP_MUL: {
70075 					d3 = d1 * d2;
70076 					break;
70077 				}
70078 				case DUK_OP_DIV: {
70079 					/* Division-by-zero is undefined
70080 					 * behavior, so rely on a helper.
70081 					 */
70082 					d3 = duk_double_div(d1, d2);
70083 					break;
70084 				}
70085 				case DUK_OP_EXP: {
70086 					d3 = (duk_double_t) duk_js_arith_pow((double) d1, (double) d2);
70087 					break;
70088 				}
70089 				default: {
70090 					d3 = 0.0;  /* Won't be used, but silence MSVC /W4 warning. */
70091 					accept_fold = 0;
70092 					break;
70093 				}
70094 				}
70095 
70096 				if (accept_fold) {
70097 					duk_double_union du;
70098 					du.d = d3;
70099 					DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
70100 					d3 = du.d;
70101 
70102 					x->t = DUK_IVAL_PLAIN;
70103 					DUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);
70104 					DUK_TVAL_SET_NUMBER(tv1, d3);  /* old value is number: no refcount */
70105 					return;
70106 				}
70107 			} else if (x->op == DUK_OP_ADD && DUK_TVAL_IS_STRING(tv1) && DUK_TVAL_IS_STRING(tv2)) {
70108 				/* Inline string concatenation.  No need to check for
70109 				 * symbols, as all inputs are valid ECMAScript strings.
70110 				 */
70111 				duk_dup(thr, x->x1.valstack_idx);
70112 				duk_dup(thr, x->x2.valstack_idx);
70113 				duk_concat(thr, 2);
70114 				duk_replace(thr, x->x1.valstack_idx);
70115 				x->t = DUK_IVAL_PLAIN;
70116 				DUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);
70117 				return;
70118 			}
70119 		}
70120 
70121 		arg1 = duk__ispec_toregconst_raw(comp_ctx, &x->x1, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
70122 		arg2 = duk__ispec_toregconst_raw(comp_ctx, &x->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
70123 
70124 		/* If forced reg, use it as destination.  Otherwise try to
70125 		 * use either coerced ispec if it is a temporary.
70126 		 */
70127 		if (forced_reg >= 0) {
70128 			dest = forced_reg;
70129 		} else if (DUK__ISREG_TEMP(comp_ctx, arg1)) {
70130 			dest = arg1;
70131 		} else if (DUK__ISREG_TEMP(comp_ctx, arg2)) {
70132 			dest = arg2;
70133 		} else {
70134 			dest = DUK__ALLOCTEMP(comp_ctx);
70135 		}
70136 
70137 		DUK_ASSERT(DUK__ISREG(dest));
70138 		duk__emit_a_b_c(comp_ctx, x->op | DUK__EMIT_FLAG_BC_REGCONST, dest, arg1, arg2);
70139 
70140 		duk__ivalue_regconst(x, dest);
70141 		return;
70142 	}
70143 	case DUK_IVAL_PROP: {
70144 		/* XXX: very similar to DUK_IVAL_ARITH - merge? */
70145 		duk_regconst_t arg1;
70146 		duk_regconst_t arg2;
70147 		duk_regconst_t dest;
70148 
70149 		/* Need a short reg/const, does not have to be a mutable temp. */
70150 		arg1 = duk__ispec_toregconst_raw(comp_ctx, &x->x1, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
70151 		arg2 = duk__ispec_toregconst_raw(comp_ctx, &x->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
70152 
70153 		/* Pick a destination register.  If either base value or key
70154 		 * happens to be a temp value, reuse it as the destination.
70155 		 *
70156 		 * XXX: The temp must be a "mutable" one, i.e. such that no
70157 		 * other expression is using it anymore.  Here this should be
70158 		 * the case because the value of a property access expression
70159 		 * is neither the base nor the key, but the lookup result.
70160 		 */
70161 
70162 		if (forced_reg >= 0) {
70163 			dest = forced_reg;
70164 		} else if (DUK__ISREG_TEMP(comp_ctx, arg1)) {
70165 			dest = arg1;
70166 		} else if (DUK__ISREG_TEMP(comp_ctx, arg2)) {
70167 			dest = arg2;
70168 		} else {
70169 			dest = DUK__ALLOCTEMP(comp_ctx);
70170 		}
70171 
70172 		duk__emit_a_b_c(comp_ctx,
70173 		                DUK_OP_GETPROP | DUK__EMIT_FLAG_BC_REGCONST,
70174 		                dest,
70175 		                arg1,
70176 		                arg2);
70177 
70178 		duk__ivalue_regconst(x, dest);
70179 		return;
70180 	}
70181 	case DUK_IVAL_VAR: {
70182 		/* x1 must be a string */
70183 		duk_regconst_t dest;
70184 		duk_regconst_t reg_varbind;
70185 		duk_regconst_t rc_varname;
70186 
70187 		DUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);
70188 
70189 		duk_dup(thr, x->x1.valstack_idx);
70190 		if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
70191 			duk__ivalue_regconst(x, reg_varbind);
70192 		} else {
70193 			dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
70194 			duk__emit_a_bc(comp_ctx, DUK_OP_GETVAR, dest, rc_varname);
70195 			duk__ivalue_regconst(x, dest);
70196 		}
70197 		return;
70198 	}
70199 	case DUK_IVAL_NONE:
70200 	default: {
70201 		DUK_D(DUK_DPRINT("invalid ivalue type: %ld", (long) x->t));
70202 		break;
70203 	}
70204 	}
70205 
70206 	DUK_ERROR_INTERNAL(thr);
70207 	DUK_WO_NORETURN(return;);
70208 }
70209 
70210 /* evaluate to plain value, no forced register (temp/bound reg both ok) */
70211 DUK_LOCAL void duk__ivalue_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
70212 	duk__ivalue_toplain_raw(comp_ctx, x, -1 /*forced_reg*/);
70213 }
70214 
70215 /* evaluate to final form (e.g. coerce GETPROP to code), throw away temp */
70216 DUK_LOCAL void duk__ivalue_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
70217 	duk_regconst_t temp;
70218 
70219 	/* If duk__ivalue_toplain_raw() allocates a temp, forget it and
70220 	 * restore next temp state.
70221 	 */
70222 	temp = DUK__GETTEMP(comp_ctx);
70223 	duk__ivalue_toplain_raw(comp_ctx, x, -1 /*forced_reg*/);
70224 	DUK__SETTEMP(comp_ctx, temp);
70225 }
70226 
70227 /* Coerce an duk_ivalue to a register or constant; result register may
70228  * be a temp or a bound register.
70229  *
70230  * The duk_ivalue argument ('x') is converted into a regconst as a
70231  * side effect.
70232  */
70233 DUK_LOCAL
70234 duk_regconst_t duk__ivalue_toregconst_raw(duk_compiler_ctx *comp_ctx,
70235                                           duk_ivalue *x,
70236                                           duk_regconst_t forced_reg,
70237                                           duk_small_uint_t flags) {
70238 	duk_hthread *thr = comp_ctx->thr;
70239 	duk_regconst_t reg;
70240 	DUK_UNREF(thr);
70241 
70242 	DUK_DDD(DUK_DDDPRINT("duk__ivalue_toregconst_raw(): x={t=%ld,op=%ld,x1={%ld:%ld:%!T},x2={%ld:%ld:%!T}}, "
70243 	                     "forced_reg=%ld, flags 0x%08lx: allow_const=%ld require_temp=%ld require_short=%ld",
70244 	                     (long) x->t, (long) x->op,
70245 	                     (long) x->x1.t, (long) x->x1.regconst,
70246 	                     (duk_tval *) duk_get_tval(thr, x->x1.valstack_idx),
70247 	                     (long) x->x2.t, (long) x->x2.regconst,
70248 	                     (duk_tval *) duk_get_tval(thr, x->x2.valstack_idx),
70249 	                     (long) forced_reg,
70250 	                     (unsigned long) flags,
70251 	                     (long) ((flags & DUK__IVAL_FLAG_ALLOW_CONST) ? 1 : 0),
70252 	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) ? 1 : 0),
70253 	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_SHORT) ? 1 : 0)));
70254 
70255 	/* first coerce to a plain value */
70256 	duk__ivalue_toplain_raw(comp_ctx, x, forced_reg);
70257 	DUK_ASSERT(x->t == DUK_IVAL_PLAIN);
70258 
70259 	/* then to a register */
70260 	reg = duk__ispec_toregconst_raw(comp_ctx, &x->x1, forced_reg, flags);
70261 	duk__ivalue_regconst(x, reg);
70262 
70263 	return reg;
70264 }
70265 
70266 DUK_LOCAL duk_regconst_t duk__ivalue_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
70267 	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, 0 /*flags*/);
70268 }
70269 
70270 #if 0  /* unused */
70271 DUK_LOCAL duk_regconst_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
70272 	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
70273 }
70274 #endif
70275 
70276 DUK_LOCAL void duk__ivalue_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_int_t forced_reg) {
70277 	DUK_ASSERT(forced_reg >= 0);
70278 	(void) duk__ivalue_toregconst_raw(comp_ctx, x, forced_reg, 0 /*flags*/);
70279 }
70280 
70281 DUK_LOCAL duk_regconst_t duk__ivalue_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
70282 	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
70283 }
70284 
70285 DUK_LOCAL duk_regconst_t duk__ivalue_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
70286 	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
70287 }
70288 
70289 /* The issues below can be solved with better flags */
70290 
70291 /* XXX: many operations actually want toforcedtemp() -- brand new temp? */
70292 /* XXX: need a toplain_ignore() which will only coerce a value to a temp
70293  * register if it might have a side effect.  Side-effect free values do not
70294  * need to be coerced.
70295  */
70296 
70297 /*
70298  *  Identifier handling
70299  */
70300 
70301 DUK_LOCAL duk_regconst_t duk__lookup_active_register_binding(duk_compiler_ctx *comp_ctx) {
70302 	duk_hthread *thr = comp_ctx->thr;
70303 	duk_hstring *h_varname;
70304 	duk_regconst_t ret;
70305 
70306 	DUK_DDD(DUK_DDDPRINT("resolving identifier reference to '%!T'",
70307 	                     (duk_tval *) duk_get_tval(thr, -1)));
70308 
70309 	/*
70310 	 *  Special name handling
70311 	 */
70312 
70313 	h_varname = duk_known_hstring(thr, -1);
70314 
70315 	if (h_varname == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)) {
70316 		DUK_DDD(DUK_DDDPRINT("flagging function as accessing 'arguments'"));
70317 		comp_ctx->curr_func.id_access_arguments = 1;
70318 	}
70319 
70320 	/*
70321 	 *  Inside one or more 'with' statements fall back to slow path always.
70322 	 *  (See e.g. test-stmt-with.js.)
70323 	 */
70324 
70325 	if (comp_ctx->curr_func.with_depth > 0) {
70326 		DUK_DDD(DUK_DDDPRINT("identifier lookup inside a 'with' -> fall back to slow path"));
70327 		goto slow_path_own;
70328 	}
70329 
70330 	/*
70331 	 *  Any catch bindings ("catch (e)") also affect identifier binding.
70332 	 *
70333 	 *  Currently, the varmap is modified for the duration of the catch
70334 	 *  clause to ensure any identifier accesses with the catch variable
70335 	 *  name will use slow path.
70336 	 */
70337 
70338 	duk_get_prop(thr, comp_ctx->curr_func.varmap_idx);
70339 	if (duk_is_number(thr, -1)) {
70340 		ret = duk_to_int(thr, -1);
70341 		duk_pop(thr);
70342 	} else {
70343 		duk_pop(thr);
70344 		if (comp_ctx->curr_func.catch_depth > 0 || comp_ctx->curr_func.with_depth > 0) {
70345 			DUK_DDD(DUK_DDDPRINT("slow path access from inside a try-catch or with needs _Varmap"));
70346 			goto slow_path_own;
70347 		} else {
70348 			/* In this case we're doing a variable lookup that doesn't
70349 			 * match our own variables, so _Varmap won't be needed at
70350 			 * run time.
70351 			 */
70352 			DUK_DDD(DUK_DDDPRINT("slow path access outside of try-catch and with, no need for _Varmap"));
70353 			goto slow_path_notown;
70354 		}
70355 	}
70356 
70357 	DUK_DDD(DUK_DDDPRINT("identifier lookup -> reg %ld", (long) ret));
70358 	return ret;
70359 
70360  slow_path_notown:
70361 	DUK_DDD(DUK_DDDPRINT("identifier lookup -> slow path, not own variable"));
70362 
70363 	comp_ctx->curr_func.id_access_slow = 1;
70364 	return (duk_regconst_t) -1;
70365 
70366  slow_path_own:
70367 	DUK_DDD(DUK_DDDPRINT("identifier lookup -> slow path, may be own variable"));
70368 
70369 	comp_ctx->curr_func.id_access_slow = 1;
70370 	comp_ctx->curr_func.id_access_slow_own = 1;
70371 	return (duk_regconst_t) -1;
70372 }
70373 
70374 /* Lookup an identifier name in the current varmap, indicating whether the
70375  * identifier is register-bound and if not, allocating a constant for the
70376  * identifier name.  Returns 1 if register-bound, 0 otherwise.  Caller can
70377  * also check (out_reg_varbind >= 0) to check whether or not identifier is
70378  * register bound.  The caller must NOT use out_rc_varname at all unless
70379  * return code is 0 or out_reg_varbind is < 0; this is becuase out_rc_varname
70380  * is unsigned and doesn't have a "unused" / none value.
70381  */
70382 DUK_LOCAL duk_bool_t duk__lookup_lhs(duk_compiler_ctx *comp_ctx, duk_regconst_t *out_reg_varbind, duk_regconst_t *out_rc_varname) {
70383 	duk_hthread *thr = comp_ctx->thr;
70384 	duk_regconst_t reg_varbind;
70385 	duk_regconst_t rc_varname;
70386 
70387 	/* [ ... varname ] */
70388 
70389 	duk_dup_top(thr);
70390 	reg_varbind = duk__lookup_active_register_binding(comp_ctx);
70391 
70392 	if (reg_varbind >= 0) {
70393 		*out_reg_varbind = reg_varbind;
70394 		*out_rc_varname = 0;  /* duk_regconst_t is unsigned, so use 0 as dummy value (ignored by caller) */
70395 		duk_pop(thr);
70396 		return 1;
70397 	} else {
70398 		rc_varname = duk__getconst(comp_ctx);
70399 		*out_reg_varbind = -1;
70400 		*out_rc_varname = rc_varname;
70401 		return 0;
70402 	}
70403 }
70404 
70405 /*
70406  *  Label handling
70407  *
70408  *  Labels are initially added with flags prohibiting both break and continue.
70409  *  When the statement type is finally uncovered (after potentially multiple
70410  *  labels), all the labels are updated to allow/prohibit break and continue.
70411  */
70412 
70413 DUK_LOCAL void duk__add_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk_int_t pc_label, duk_int_t label_id) {
70414 	duk_hthread *thr = comp_ctx->thr;
70415 	duk_size_t n;
70416 	duk_size_t new_size;
70417 	duk_uint8_t *p;
70418 	duk_labelinfo *li_start, *li;
70419 
70420 	/* Duplicate (shadowing) labels are not allowed, except for the empty
70421 	 * labels (which are used as default labels for switch and iteration
70422 	 * statements).
70423 	 *
70424 	 * We could also allow shadowing of non-empty pending labels without any
70425 	 * other issues than breaking the required label shadowing requirements
70426 	 * of the E5 specification, see Section 12.12.
70427 	 */
70428 
70429 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
70430 	li_start = (duk_labelinfo *) (void *) p;
70431 	li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
70432 	n = (duk_size_t) (li - li_start);
70433 
70434 	while (li > li_start) {
70435 		li--;
70436 
70437 		if (li->h_label == h_label && h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) {
70438 			DUK_ERROR_SYNTAX(thr, DUK_STR_DUPLICATE_LABEL);
70439 			DUK_WO_NORETURN(return;);
70440 		}
70441 	}
70442 
70443 	duk_push_hstring(thr, h_label);
70444 	DUK_ASSERT(n <= DUK_UARRIDX_MAX);  /* label limits */
70445 	(void) duk_put_prop_index(thr, comp_ctx->curr_func.labelnames_idx, (duk_uarridx_t) n);
70446 
70447 	new_size = (n + 1) * sizeof(duk_labelinfo);
70448 	duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, new_size);
70449 	/* XXX: slack handling, slow now */
70450 
70451 	/* relookup after possible realloc */
70452 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
70453 	li_start = (duk_labelinfo *) (void *) p;
70454 	DUK_UNREF(li_start);  /* silence scan-build warning */
70455 	li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
70456 	li--;
70457 
70458 	/* Labels can be used for iteration statements but also for other statements,
70459 	 * in particular a label can be used for a block statement.  All cases of a
70460 	 * named label accept a 'break' so that flag is set here.  Iteration statements
70461 	 * also allow 'continue', so that flag is updated when we figure out the
70462 	 * statement type.
70463 	 */
70464 
70465 	li->flags = DUK_LABEL_FLAG_ALLOW_BREAK;
70466 	li->label_id = label_id;
70467 	li->h_label = h_label;
70468 	li->catch_depth = comp_ctx->curr_func.catch_depth;   /* catch depth from current func */
70469 	li->pc_label = pc_label;
70470 
70471 	DUK_DDD(DUK_DDDPRINT("registered label: flags=0x%08lx, id=%ld, name=%!O, catch_depth=%ld, pc_label=%ld",
70472 	                     (unsigned long) li->flags, (long) li->label_id, (duk_heaphdr *) li->h_label,
70473 	                     (long) li->catch_depth, (long) li->pc_label));
70474 }
70475 
70476 /* Update all labels with matching label_id. */
70477 DUK_LOCAL void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t label_id, duk_small_uint_t flags) {
70478 	duk_uint8_t *p;
70479 	duk_labelinfo *li_start, *li;
70480 
70481 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(comp_ctx->thr->heap, comp_ctx->curr_func.h_labelinfos);
70482 	li_start = (duk_labelinfo *) (void *) p;
70483 	li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
70484 
70485 	/* Match labels starting from latest; once label_id no longer matches, we can
70486 	 * safely exit without checking the rest of the labels (only the topmost labels
70487 	 * are ever updated).
70488 	 */
70489 	while (li > li_start) {
70490 		li--;
70491 
70492 		if (li->label_id != label_id) {
70493 			break;
70494 		}
70495 
70496 		DUK_DDD(DUK_DDDPRINT("updating (overwriting) label flags for li=%p, label_id=%ld, flags=%ld",
70497 		                     (void *) li, (long) label_id, (long) flags));
70498 
70499 		li->flags = flags;
70500 	}
70501 }
70502 
70503 /* Lookup active label information.  Break/continue distinction is necessary to handle switch
70504  * statement related labels correctly: a switch will only catch a 'break', not a 'continue'.
70505  *
70506  * An explicit label cannot appear multiple times in the active set, but empty labels (unlabelled
70507  * iteration and switch statements) can.  A break will match the closest unlabelled or labelled
70508  * statement.  A continue will match the closest unlabelled or labelled iteration statement.  It is
70509  * a syntax error if a continue matches a labelled switch statement; because an explicit label cannot
70510  * be duplicated, the continue cannot match any valid label outside the switch.
70511  *
70512  * A side effect of these rules is that a LABEL statement related to a switch should never actually
70513  * catch a continue abrupt completion at run-time.  Hence an INVALID opcode can be placed in the
70514  * continue slot of the switch's LABEL statement.
70515  */
70516 
70517 /* XXX: awkward, especially the bunch of separate output values -> output struct? */
70518 DUK_LOCAL void duk__lookup_active_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk_bool_t is_break, duk_int_t *out_label_id, duk_int_t *out_label_catch_depth, duk_int_t *out_label_pc, duk_bool_t *out_is_closest) {
70519 	duk_hthread *thr = comp_ctx->thr;
70520 	duk_uint8_t *p;
70521 	duk_labelinfo *li_start, *li_end, *li;
70522 	duk_bool_t match = 0;
70523 
70524 	DUK_DDD(DUK_DDDPRINT("looking up active label: label='%!O', is_break=%ld",
70525 	                     (duk_heaphdr *) h_label, (long) is_break));
70526 
70527 	DUK_UNREF(thr);
70528 
70529 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
70530 	li_start = (duk_labelinfo *) (void *) p;
70531 	li_end = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
70532 	li = li_end;
70533 
70534 	/* Match labels starting from latest label because there can be duplicate empty
70535 	 * labels in the label set.
70536 	 */
70537 	while (li > li_start) {
70538 		li--;
70539 
70540 		if (li->h_label != h_label) {
70541 			DUK_DDD(DUK_DDDPRINT("labelinfo[%ld] ->'%!O' != %!O",
70542 			                     (long) (li - li_start),
70543 			                     (duk_heaphdr *) li->h_label,
70544 			                     (duk_heaphdr *) h_label));
70545 			continue;
70546 		}
70547 
70548 		DUK_DDD(DUK_DDDPRINT("labelinfo[%ld] -> '%!O' label name matches (still need to check type)",
70549 		                     (long) (li - li_start), (duk_heaphdr *) h_label));
70550 
70551 		/* currently all labels accept a break, so no explicit check for it now */
70552 		DUK_ASSERT(li->flags & DUK_LABEL_FLAG_ALLOW_BREAK);
70553 
70554 		if (is_break) {
70555 			/* break matches always */
70556 			match = 1;
70557 			break;
70558 		} else if (li->flags & DUK_LABEL_FLAG_ALLOW_CONTINUE) {
70559 			/* iteration statements allow continue */
70560 			match = 1;
70561 			break;
70562 		} else {
70563 			/* continue matched this label -- we can only continue if this is the empty
70564 			 * label, for which duplication is allowed, and thus there is hope of
70565 			 * finding a match deeper in the label stack.
70566 			 */
70567 			if (h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) {
70568 				DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LABEL);
70569 				DUK_WO_NORETURN(return;);
70570 			} else {
70571 				DUK_DDD(DUK_DDDPRINT("continue matched an empty label which does not "
70572 				                     "allow a continue -> continue lookup deeper in label stack"));
70573 			}
70574 		}
70575 	}
70576 	/* XXX: match flag is awkward, rework */
70577 	if (!match) {
70578 		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LABEL);
70579 		DUK_WO_NORETURN(return;);
70580 	}
70581 
70582 	DUK_DDD(DUK_DDDPRINT("label match: %!O -> label_id %ld, catch_depth=%ld, pc_label=%ld",
70583 	                     (duk_heaphdr *) h_label, (long) li->label_id,
70584 	                     (long) li->catch_depth, (long) li->pc_label));
70585 
70586 	*out_label_id = li->label_id;
70587 	*out_label_catch_depth = li->catch_depth;
70588 	*out_label_pc = li->pc_label;
70589 	*out_is_closest = (li == li_end - 1);
70590 }
70591 
70592 DUK_LOCAL void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_size_t len) {
70593 	duk_hthread *thr = comp_ctx->thr;
70594 
70595 	duk_set_length(thr, comp_ctx->curr_func.labelnames_idx, len);
70596 	duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, sizeof(duk_labelinfo) * len);
70597 }
70598 
70599 /*
70600  *  Expression parsing: duk__expr_nud(), duk__expr_led(), duk__expr_lbp(), and helpers.
70601  *
70602  *  - duk__expr_nud(): ("null denotation"): process prev_token as a "start" of an expression (e.g. literal)
70603  *  - duk__expr_led(): ("left denotation"): process prev_token in the "middle" of an expression (e.g. operator)
70604  *  - duk__expr_lbp(): ("left-binding power"): return left-binding power of curr_token
70605  */
70606 
70607 /* object literal key tracking flags */
70608 #define DUK__OBJ_LIT_KEY_PLAIN  (1 << 0)  /* key encountered as a plain property */
70609 #define DUK__OBJ_LIT_KEY_GET    (1 << 1)  /* key encountered as a getter */
70610 #define DUK__OBJ_LIT_KEY_SET    (1 << 2)  /* key encountered as a setter */
70611 
70612 DUK_LOCAL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
70613 	duk_hthread *thr = comp_ctx->thr;
70614 	duk_regconst_t reg_obj;                 /* result reg */
70615 	duk_regconst_t reg_temp;                /* temp reg */
70616 	duk_regconst_t temp_start;              /* temp reg value for start of loop */
70617 	duk_small_uint_t max_init_values;  /* max # of values initialized in one MPUTARR set */
70618 	duk_small_uint_t num_values;       /* number of values in current MPUTARR set */
70619 	duk_uarridx_t curr_idx;            /* current (next) array index */
70620 	duk_uarridx_t start_idx;           /* start array index of current MPUTARR set */
70621 	duk_uarridx_t init_idx;            /* last array index explicitly initialized, +1 */
70622 	duk_bool_t require_comma;          /* next loop requires a comma */
70623 #if !defined(DUK_USE_PREFER_SIZE)
70624 	duk_int_t pc_newarr;
70625 	duk_compiler_instr *instr;
70626 #endif
70627 
70628 	/* DUK_TOK_LBRACKET already eaten, current token is right after that */
70629 	DUK_ASSERT(comp_ctx->prev_token.t == DUK_TOK_LBRACKET);
70630 
70631 	max_init_values = DUK__MAX_ARRAY_INIT_VALUES;  /* XXX: depend on available temps? */
70632 
70633 	reg_obj = DUK__ALLOCTEMP(comp_ctx);
70634 #if !defined(DUK_USE_PREFER_SIZE)
70635 	pc_newarr = duk__get_current_pc(comp_ctx);
70636 #endif
70637 	duk__emit_bc(comp_ctx, DUK_OP_NEWARR, reg_obj);  /* XXX: patch initial size hint afterwards? */
70638 	temp_start = DUK__GETTEMP(comp_ctx);
70639 
70640 	/*
70641 	 *  Emit initializers in sets of maximum max_init_values.
70642 	 *  Corner cases such as single value initializers do not have
70643 	 *  special handling now.
70644 	 *
70645 	 *  Elided elements must not be emitted as 'undefined' values,
70646 	 *  because such values would be enumerable (which is incorrect).
70647 	 *  Also note that trailing elisions must be reflected in the
70648 	 *  length of the final array but cause no elements to be actually
70649 	 *  inserted.
70650 	 */
70651 
70652 	curr_idx = 0;
70653 	init_idx = 0;         /* tracks maximum initialized index + 1 */
70654 	start_idx = 0;
70655 	require_comma = 0;
70656 
70657 	for (;;) {
70658 		num_values = 0;
70659 		DUK__SETTEMP(comp_ctx, temp_start);
70660 
70661 		if (comp_ctx->curr_token.t == DUK_TOK_RBRACKET) {
70662 			break;
70663 		}
70664 
70665 		for (;;) {
70666 			if (comp_ctx->curr_token.t == DUK_TOK_RBRACKET) {
70667 				/* the outer loop will recheck and exit */
70668 				break;
70669 			}
70670 
70671 			/* comma check */
70672 			if (require_comma) {
70673 				if (comp_ctx->curr_token.t == DUK_TOK_COMMA) {
70674 					/* comma after a value, expected */
70675 					duk__advance(comp_ctx);
70676 					require_comma = 0;
70677 					continue;
70678 				} else {
70679 					goto syntax_error;
70680 				}
70681 			} else {
70682 				if (comp_ctx->curr_token.t == DUK_TOK_COMMA) {
70683 					/* elision - flush */
70684 					curr_idx++;
70685 					duk__advance(comp_ctx);
70686 					/* if num_values > 0, MPUTARR emitted by outer loop after break */
70687 					break;
70688 				}
70689 			}
70690 			/* else an array initializer element */
70691 
70692 			/* initial index */
70693 			if (num_values == 0) {
70694 				start_idx = curr_idx;
70695 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
70696 				duk__emit_load_int32(comp_ctx, reg_temp, (duk_int32_t) start_idx);
70697 			}
70698 
70699 			reg_temp = DUK__ALLOCTEMP(comp_ctx);   /* alloc temp just in case, to update max temp */
70700 			DUK__SETTEMP(comp_ctx, reg_temp);
70701 			duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);
70702 			DUK__SETTEMP(comp_ctx, reg_temp + 1);
70703 
70704 			num_values++;
70705 			curr_idx++;
70706 			require_comma = 1;
70707 
70708 			if (num_values >= max_init_values) {
70709 				/* MPUTARR emitted by outer loop */
70710 				break;
70711 			}
70712 		}
70713 
70714 		if (num_values > 0) {
70715 			/* - A is a source register (it's not a write target, but used
70716 			 *   to identify the target object) but can be shuffled.
70717 			 * - B cannot be shuffled normally because it identifies a range
70718 			 *   of registers, the emitter has special handling for this
70719 			 *   (the "no shuffle" flag must not be set).
70720 			 * - C is a non-register number and cannot be shuffled, but
70721 			 *   never needs to be.
70722 			 */
70723 			duk__emit_a_b_c(comp_ctx,
70724 			                DUK_OP_MPUTARR |
70725 			                    DUK__EMIT_FLAG_NO_SHUFFLE_C |
70726 			                    DUK__EMIT_FLAG_A_IS_SOURCE,
70727 			                reg_obj,
70728 			                temp_start,
70729 			                (duk_regconst_t) (num_values + 1));
70730 			init_idx = start_idx + num_values;
70731 
70732 			/* num_values and temp_start reset at top of outer loop */
70733 		}
70734 	}
70735 
70736 	/* Update initil size for NEWARR, doesn't need to be exact and is
70737 	 * capped at A field limit.
70738 	 */
70739 #if !defined(DUK_USE_PREFER_SIZE)
70740 	instr = duk__get_instr_ptr(comp_ctx, pc_newarr);
70741 	instr->ins |= DUK_ENC_OP_A(0, curr_idx > DUK_BC_A_MAX ? DUK_BC_A_MAX : curr_idx);
70742 #endif
70743 
70744 	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RBRACKET);
70745 	duk__advance(comp_ctx);
70746 
70747 	DUK_DDD(DUK_DDDPRINT("array literal done, curridx=%ld, initidx=%ld",
70748 	                     (long) curr_idx, (long) init_idx));
70749 
70750 	/* trailing elisions? */
70751 	if (curr_idx > init_idx) {
70752 		/* yes, must set array length explicitly */
70753 		DUK_DDD(DUK_DDDPRINT("array literal has trailing elisions which affect its length"));
70754 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
70755 		duk__emit_load_int32(comp_ctx, reg_temp, (duk_int_t) curr_idx);
70756 		duk__emit_a_bc(comp_ctx,
70757 		               DUK_OP_SETALEN | DUK__EMIT_FLAG_A_IS_SOURCE,
70758 		               reg_obj,
70759 		               reg_temp);
70760 	}
70761 
70762 	DUK__SETTEMP(comp_ctx, temp_start);
70763 
70764 	duk__ivalue_regconst(res, reg_obj);
70765 	return;
70766 
70767  syntax_error:
70768 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_ARRAY_LITERAL);
70769 	DUK_WO_NORETURN(return;);
70770 }
70771 
70772 typedef struct {
70773 	duk_regconst_t reg_obj;
70774 	duk_regconst_t temp_start;
70775 	duk_small_uint_t num_pairs;
70776 	duk_small_uint_t num_total_pairs;
70777 } duk__objlit_state;
70778 
70779 DUK_LOCAL void duk__objlit_flush_keys(duk_compiler_ctx *comp_ctx, duk__objlit_state *st) {
70780 	if (st->num_pairs > 0) {
70781 		/* - A is a source register (it's not a write target, but used
70782 		 *   to identify the target object) but can be shuffled.
70783 		 * - B cannot be shuffled normally because it identifies a range
70784 		 *   of registers, the emitter has special handling for this
70785 		 *   (the "no shuffle" flag must not be set).
70786 		 * - C is a non-register number and cannot be shuffled, but
70787 		 *   never needs to be.
70788 		 */
70789 		DUK_ASSERT(st->num_pairs > 0);
70790 		duk__emit_a_b_c(comp_ctx,
70791 		                DUK_OP_MPUTOBJ |
70792 		                    DUK__EMIT_FLAG_NO_SHUFFLE_C |
70793 		                    DUK__EMIT_FLAG_A_IS_SOURCE,
70794 		                st->reg_obj,
70795 		                st->temp_start,
70796 		                (duk_regconst_t) (st->num_pairs * 2));
70797 		st->num_total_pairs += st->num_pairs;
70798 		st->num_pairs = 0;
70799 	}
70800 	DUK__SETTEMP(comp_ctx, st->temp_start);
70801 }
70802 
70803 DUK_LOCAL duk_bool_t duk__objlit_load_key(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_token *tok, duk_regconst_t reg_temp) {
70804 	if (tok->t_nores == DUK_TOK_IDENTIFIER || tok->t_nores == DUK_TOK_STRING) {
70805 		/* same handling for identifiers and strings */
70806 		DUK_ASSERT(tok->str1 != NULL);
70807 		duk_push_hstring(comp_ctx->thr, tok->str1);
70808 	} else if (tok->t == DUK_TOK_NUMBER) {
70809 		/* numbers can be loaded as numbers and coerced on the fly */
70810 		duk_push_number(comp_ctx->thr, tok->num);
70811 	} else {
70812 		return 1;  /* error */
70813 	}
70814 
70815 	duk__ivalue_plain_fromstack(comp_ctx, res);
70816 	DUK__SETTEMP(comp_ctx, reg_temp + 1);
70817 	duk__ivalue_toforcedreg(comp_ctx, res, reg_temp);
70818 	DUK__SETTEMP(comp_ctx, reg_temp + 1);
70819 	return 0;
70820 }
70821 
70822 DUK_LOCAL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
70823 	duk_hthread *thr = comp_ctx->thr;
70824 	duk__objlit_state st;
70825 	duk_regconst_t reg_temp;          /* temp reg */
70826 	duk_small_uint_t max_init_pairs;  /* max # of key-value pairs initialized in one MPUTOBJ set */
70827 	duk_bool_t first;                 /* first value: comma must not precede the value */
70828 	duk_bool_t is_set, is_get;        /* temps */
70829 #if !defined(DUK_USE_PREFER_SIZE)
70830 	duk_int_t pc_newobj;
70831 	duk_compiler_instr *instr;
70832 #endif
70833 
70834 	DUK_ASSERT(comp_ctx->prev_token.t == DUK_TOK_LCURLY);
70835 
70836 	max_init_pairs = DUK__MAX_OBJECT_INIT_PAIRS;  /* XXX: depend on available temps? */
70837 
70838 	st.reg_obj = DUK__ALLOCTEMP(comp_ctx);    /* target object */
70839 	st.temp_start = DUK__GETTEMP(comp_ctx);   /* start of MPUTOBJ argument list */
70840 	st.num_pairs = 0;                         /* number of key/value pairs emitted for current MPUTOBJ set */
70841 	st.num_total_pairs = 0;                   /* number of key/value pairs emitted overall */
70842 
70843 #if !defined(DUK_USE_PREFER_SIZE)
70844 	pc_newobj = duk__get_current_pc(comp_ctx);
70845 #endif
70846 	duk__emit_bc(comp_ctx, DUK_OP_NEWOBJ, st.reg_obj);
70847 
70848 	/*
70849 	 *  Emit initializers in sets of maximum max_init_pairs keys.
70850 	 *  Setter/getter is handled separately and terminates the
70851 	 *  current set of initializer values.  Corner cases such as
70852 	 *  single value initializers do not have special handling now.
70853 	 */
70854 
70855 	first = 1;
70856 	for (;;) {
70857 		/*
70858 		 *  ES5 and ES2015+ provide a lot of different PropertyDefinition
70859 		 *  formats, see http://www.ecma-international.org/ecma-262/6.0/#sec-object-initializer.
70860 		 *
70861 		 *  PropertyName can be IdentifierName (includes reserved words), a string
70862 		 *  literal, or a number literal.  Note that IdentifierName allows 'get' and
70863 		 *  'set' too, so we need to look ahead to the next token to distinguish:
70864 		 *
70865 		 *     { get : 1 }
70866 		 *
70867 		 *  and
70868 		 *
70869 		 *     { get foo() { return 1 } }
70870 		 *     { get get() { return 1 } }    // 'get' as getter propertyname
70871 		 *
70872 		 *  Finally, a trailing comma is allowed.
70873 		 *
70874 		 *  Key name is coerced to string at compile time (and ends up as a
70875 		 *  a string constant) even for numeric keys (e.g. "{1:'foo'}").
70876 		 *  These could be emitted using e.g. LDINT, but that seems hardly
70877 		 *  worth the effort and would increase code size.
70878 		 */
70879 
70880 		DUK_DDD(DUK_DDDPRINT("object literal loop, curr_token->t = %ld",
70881 		                     (long) comp_ctx->curr_token.t));
70882 
70883 		if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
70884 			break;
70885 		}
70886 
70887 		if (first) {
70888 			first = 0;
70889 		} else {
70890 			if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
70891 				goto syntax_error;
70892 			}
70893 			duk__advance(comp_ctx);
70894 			if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
70895 				/* trailing comma followed by rcurly */
70896 				break;
70897 			}
70898 		}
70899 
70900 		/* Advance to get one step of lookup. */
70901 		duk__advance(comp_ctx);
70902 
70903 		/* Flush current MPUTOBJ if enough many pairs gathered. */
70904 		if (st.num_pairs >= max_init_pairs) {
70905 			duk__objlit_flush_keys(comp_ctx, &st);
70906 			DUK_ASSERT(st.num_pairs == 0);
70907 		}
70908 
70909 		/* Reset temp register state and reserve reg_temp and
70910 		 * reg_temp + 1 for handling the current property.
70911 		 */
70912 		DUK__SETTEMP(comp_ctx, st.temp_start + 2 * (duk_regconst_t) st.num_pairs);
70913 		reg_temp = DUK__ALLOCTEMPS(comp_ctx, 2);
70914 
70915 		/* NOTE: "get" and "set" are not officially ReservedWords and the lexer
70916 		 * currently treats them always like ordinary identifiers (DUK_TOK_GET
70917 		 * and DUK_TOK_SET are unused).  They need to be detected based on the
70918 		 * identifier string content.
70919 		 */
70920 
70921 		is_get = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
70922 		          comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_GET(thr));
70923 		is_set = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
70924 		          comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_SET(thr));
70925 		if ((is_get || is_set) && comp_ctx->curr_token.t != DUK_TOK_COLON) {
70926 			/* getter/setter */
70927 			duk_int_t fnum;
70928 
70929 			duk__objlit_flush_keys(comp_ctx, &st);
70930 			DUK_ASSERT(DUK__GETTEMP(comp_ctx) == st.temp_start);  /* 2 regs are guaranteed to be allocated w.r.t. temp_max */
70931 			reg_temp = DUK__ALLOCTEMPS(comp_ctx, 2);
70932 
70933 			if (duk__objlit_load_key(comp_ctx, res, &comp_ctx->curr_token, reg_temp) != 0) {
70934 				goto syntax_error;
70935 			}
70936 
70937 			/* curr_token = get/set name */
70938 			fnum = duk__parse_func_like_fnum(comp_ctx, DUK__FUNC_FLAG_GETSET);
70939 
70940 			duk__emit_a_bc(comp_ctx,
70941 			               DUK_OP_CLOSURE,
70942 			               st.temp_start + 1,
70943 			               (duk_regconst_t) fnum);
70944 
70945 			/* Slot C is used in a non-standard fashion (range of regs),
70946 			 * emitter code has special handling for it (must not set the
70947 			 * "no shuffle" flag).
70948 			 */
70949 			duk__emit_a_bc(comp_ctx,
70950 			              (is_get ? DUK_OP_INITGET : DUK_OP_INITSET) | DUK__EMIT_FLAG_A_IS_SOURCE,
70951 			              st.reg_obj,
70952 			              st.temp_start);   /* temp_start+0 = key, temp_start+1 = closure */
70953 
70954 			DUK_ASSERT(st.num_pairs == 0);  /* temp state is reset on next loop */
70955 #if defined(DUK_USE_ES6)
70956 		} else if (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
70957 		           (comp_ctx->curr_token.t == DUK_TOK_COMMA || comp_ctx->curr_token.t == DUK_TOK_RCURLY)) {
70958 			duk_bool_t load_rc;
70959 
70960 			load_rc = duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp);
70961 			DUK_UNREF(load_rc);
70962 			DUK_ASSERT(load_rc == 0);  /* always succeeds because token is identifier */
70963 
70964 			duk__ivalue_var_hstring(comp_ctx, res, comp_ctx->prev_token.str1);
70965 			DUK_ASSERT(DUK__GETTEMP(comp_ctx) == reg_temp + 1);
70966 			duk__ivalue_toforcedreg(comp_ctx, res, reg_temp + 1);
70967 
70968 			st.num_pairs++;
70969 		} else if ((comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER ||
70970 		            comp_ctx->prev_token.t == DUK_TOK_STRING ||
70971 		            comp_ctx->prev_token.t == DUK_TOK_NUMBER) &&
70972 		           comp_ctx->curr_token.t == DUK_TOK_LPAREN) {
70973 			duk_int_t fnum;
70974 
70975 			/* Parsing-wise there's a small hickup here: the token parsing
70976 			 * state is one step too advanced for the function parse helper
70977 			 * compared to other cases.  The current solution is an extra
70978 			 * flag to indicate whether function parsing should use the
70979 			 * current or the previous token to starting parsing from.
70980 			 */
70981 
70982 			if (duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp) != 0) {
70983 				goto syntax_error;
70984 			}
70985 
70986 			fnum = duk__parse_func_like_fnum(comp_ctx, DUK__FUNC_FLAG_USE_PREVTOKEN | DUK__FUNC_FLAG_METDEF);
70987 
70988 			duk__emit_a_bc(comp_ctx,
70989 			               DUK_OP_CLOSURE,
70990 			               reg_temp + 1,
70991 			               (duk_regconst_t) fnum);
70992 
70993 			st.num_pairs++;
70994 #endif  /* DUK_USE_ES6 */
70995 		} else {
70996 #if defined(DUK_USE_ES6)
70997 			if (comp_ctx->prev_token.t == DUK_TOK_LBRACKET) {
70998 				/* ES2015 computed property name.  Executor ToPropertyKey()
70999 				 * coerces the key at runtime.
71000 				 */
71001 				DUK__SETTEMP(comp_ctx, reg_temp);
71002 				duk__expr_toforcedreg(comp_ctx, res, DUK__BP_FOR_EXPR, reg_temp);
71003 				duk__advance_expect(comp_ctx, DUK_TOK_RBRACKET);
71004 
71005 				/* XXX: If next token is '(' we're dealing with
71006 				 * the method shorthand with a computed name,
71007 				 * e.g. { [Symbol.for('foo')](a,b) {} }.  This
71008 				 * form is not yet supported and causes a
71009 				 * SyntaxError on the DUK_TOK_COLON check below.
71010 				 */
71011 			}
71012 			else
71013 #endif  /* DUK_USE_ES6 */
71014 			{
71015 				if (duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp) != 0) {
71016 					goto syntax_error;
71017 				}
71018 			}
71019 
71020 			duk__advance_expect(comp_ctx, DUK_TOK_COLON);
71021 
71022 			DUK__SETTEMP(comp_ctx, reg_temp + 1);
71023 			duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp + 1 /*forced_reg*/);
71024 
71025 			st.num_pairs++;
71026 		}
71027 	}  /* property loop */
71028 
71029 	/* Flush remaining properties. */
71030 	duk__objlit_flush_keys(comp_ctx, &st);
71031 	DUK_ASSERT(st.num_pairs == 0);
71032 	DUK_ASSERT(DUK__GETTEMP(comp_ctx) == st.temp_start);
71033 
71034 	/* Update initial size for NEWOBJ.  The init size doesn't need to be
71035 	 * exact as the purpose is just to avoid object resizes in common
71036 	 * cases.  The size is capped to field A limit, and will be too high
71037 	 * if the object literal contains duplicate keys (this is harmless but
71038 	 * increases memory traffic if the object is compacted later on).
71039 	 */
71040 #if !defined(DUK_USE_PREFER_SIZE)
71041 	instr = duk__get_instr_ptr(comp_ctx, pc_newobj);
71042 	instr->ins |= DUK_ENC_OP_A(0, st.num_total_pairs > DUK_BC_A_MAX ? DUK_BC_A_MAX : st.num_total_pairs);
71043 #endif
71044 
71045 	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);
71046 	duk__advance(comp_ctx);  /* No RegExp after object literal. */
71047 
71048 	duk__ivalue_regconst(res, st.reg_obj);
71049 	return;
71050 
71051  syntax_error:
71052 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_OBJECT_LITERAL);
71053 	DUK_WO_NORETURN(return;);
71054 }
71055 
71056 /* Parse argument list.  Arguments are written to temps starting from
71057  * "next temp".  Returns number of arguments parsed.  Expects left paren
71058  * to be already eaten, and eats the right paren before returning.
71059  */
71060 DUK_LOCAL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
71061 	duk_int_t nargs = 0;
71062 	duk_regconst_t reg_temp;
71063 
71064 	/* Note: expect that caller has already eaten the left paren */
71065 
71066 	DUK_DDD(DUK_DDDPRINT("start parsing arguments, prev_token.t=%ld, curr_token.t=%ld",
71067 	                     (long) comp_ctx->prev_token.t, (long) comp_ctx->curr_token.t));
71068 
71069 	for (;;) {
71070 		if (comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
71071 			break;
71072 		}
71073 		if (nargs > 0) {
71074 			duk__advance_expect(comp_ctx, DUK_TOK_COMMA);
71075 		}
71076 
71077 		/* We want the argument expression value to go to "next temp"
71078 		 * without additional moves.  That should almost always be the
71079 		 * case, but we double check after expression parsing.
71080 		 *
71081 		 * This is not the cleanest possible approach.
71082 		 */
71083 
71084 		reg_temp = DUK__ALLOCTEMP(comp_ctx);  /* bump up "allocated" reg count, just in case */
71085 		DUK__SETTEMP(comp_ctx, reg_temp);
71086 
71087 		/* binding power must be high enough to NOT allow comma expressions directly */
71088 		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp);  /* always allow 'in', coerce to 'tr' just in case */
71089 
71090 		DUK__SETTEMP(comp_ctx, reg_temp + 1);
71091 		nargs++;
71092 
71093 		DUK_DDD(DUK_DDDPRINT("argument #%ld written into reg %ld", (long) nargs, (long) reg_temp));
71094 	}
71095 
71096 	/* eat the right paren */
71097 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* RegExp mode does not matter. */
71098 
71099 	DUK_DDD(DUK_DDDPRINT("end parsing arguments"));
71100 
71101 	return nargs;
71102 }
71103 
71104 DUK_LOCAL duk_bool_t duk__expr_is_empty(duk_compiler_ctx *comp_ctx) {
71105 	/* empty expressions can be detected conveniently with nud/led counts */
71106 	return (comp_ctx->curr_func.nud_count == 0) &&
71107 	       (comp_ctx->curr_func.led_count == 0);
71108 }
71109 
71110 DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
71111 	duk_hthread *thr = comp_ctx->thr;
71112 	duk_token *tk;
71113 	duk_regconst_t temp_at_entry;
71114 	duk_small_uint_t tok;
71115 	duk_uint32_t args;  /* temp variable to pass constants and flags to shared code */
71116 
71117 	/*
71118 	 *  ctx->prev_token     token to process with duk__expr_nud()
71119 	 *  ctx->curr_token     updated by caller
71120 	 *
71121 	 *  Note: the token in the switch below has already been eaten.
71122 	 */
71123 
71124 	temp_at_entry = DUK__GETTEMP(comp_ctx);
71125 
71126 	comp_ctx->curr_func.nud_count++;
71127 
71128 	tk = &comp_ctx->prev_token;
71129 	tok = tk->t;
71130 	res->t = DUK_IVAL_NONE;
71131 
71132 	DUK_DDD(DUK_DDDPRINT("duk__expr_nud(), prev_token.t=%ld, allow_in=%ld, paren_level=%ld",
71133 	                     (long) tk->t, (long) comp_ctx->curr_func.allow_in, (long) comp_ctx->curr_func.paren_level));
71134 
71135 	switch (tok) {
71136 
71137 	/* PRIMARY EXPRESSIONS */
71138 
71139 	case DUK_TOK_THIS: {
71140 		duk_regconst_t reg_temp;
71141 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
71142 		duk__emit_bc(comp_ctx,
71143 		             DUK_OP_LDTHIS,
71144 		             reg_temp);
71145 		duk__ivalue_regconst(res, reg_temp);
71146 		return;
71147 	}
71148 	case DUK_TOK_IDENTIFIER: {
71149 		duk__ivalue_var_hstring(comp_ctx, res, tk->str1);
71150 		return;
71151 	}
71152 	case DUK_TOK_NULL: {
71153 		duk_push_null(thr);
71154 		goto plain_value;
71155 	}
71156 	case DUK_TOK_TRUE: {
71157 		duk_push_true(thr);
71158 		goto plain_value;
71159 	}
71160 	case DUK_TOK_FALSE: {
71161 		duk_push_false(thr);
71162 		goto plain_value;
71163 	}
71164 	case DUK_TOK_NUMBER: {
71165 		duk_push_number(thr, tk->num);
71166 		goto plain_value;
71167 	}
71168 	case DUK_TOK_STRING: {
71169 		DUK_ASSERT(tk->str1 != NULL);
71170 		duk_push_hstring(thr, tk->str1);
71171 		goto plain_value;
71172 	}
71173 	case DUK_TOK_REGEXP: {
71174 #if defined(DUK_USE_REGEXP_SUPPORT)
71175 		duk_regconst_t reg_temp;
71176 		duk_regconst_t rc_re_bytecode;  /* const */
71177 		duk_regconst_t rc_re_source;    /* const */
71178 
71179 		DUK_ASSERT(tk->str1 != NULL);
71180 		DUK_ASSERT(tk->str2 != NULL);
71181 
71182 		DUK_DDD(DUK_DDDPRINT("emitting regexp op, str1=%!O, str2=%!O",
71183 		                     (duk_heaphdr *) tk->str1,
71184 		                     (duk_heaphdr *) tk->str2));
71185 
71186 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
71187 		duk_push_hstring(thr, tk->str1);
71188 		duk_push_hstring(thr, tk->str2);
71189 
71190 		/* [ ... pattern flags ] */
71191 
71192 		duk_regexp_compile(thr);
71193 
71194 		/* [ ... escaped_source bytecode ] */
71195 
71196 		rc_re_bytecode = duk__getconst(comp_ctx);
71197 		rc_re_source = duk__getconst(comp_ctx);
71198 
71199 		duk__emit_a_b_c(comp_ctx,
71200 		                DUK_OP_REGEXP | DUK__EMIT_FLAG_BC_REGCONST,
71201 		                reg_temp /*a*/,
71202 		                rc_re_bytecode /*b*/,
71203 		                rc_re_source /*c*/);
71204 
71205 		duk__ivalue_regconst(res, reg_temp);
71206 		return;
71207 #else  /* DUK_USE_REGEXP_SUPPORT */
71208 		goto syntax_error;
71209 #endif  /* DUK_USE_REGEXP_SUPPORT */
71210 	}
71211 	case DUK_TOK_LBRACKET: {
71212 		DUK_DDD(DUK_DDDPRINT("parsing array literal"));
71213 		duk__nud_array_literal(comp_ctx, res);
71214 		return;
71215 	}
71216 	case DUK_TOK_LCURLY: {
71217 		DUK_DDD(DUK_DDDPRINT("parsing object literal"));
71218 		duk__nud_object_literal(comp_ctx, res);
71219 		return;
71220 	}
71221 	case DUK_TOK_LPAREN: {
71222 		duk_bool_t prev_allow_in;
71223 
71224 		comp_ctx->curr_func.paren_level++;
71225 		prev_allow_in = comp_ctx->curr_func.allow_in;
71226 		comp_ctx->curr_func.allow_in = 1; /* reset 'allow_in' for parenthesized expression */
71227 
71228 		duk__expr(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);  /* Expression, terminates at a ')' */
71229 
71230 		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* No RegExp after parenthesized expression. */
71231 		comp_ctx->curr_func.allow_in = prev_allow_in;
71232 		comp_ctx->curr_func.paren_level--;
71233 		return;
71234 	}
71235 
71236 	/* MEMBER/NEW/CALL EXPRESSIONS */
71237 
71238 	case DUK_TOK_NEW: {
71239 		/*
71240 		 *  Parsing an expression starting with 'new' is tricky because
71241 		 *  there are multiple possible productions deriving from
71242 		 *  LeftHandSideExpression which begin with 'new'.
71243 		 *
71244 		 *  We currently resort to one-token lookahead to distinguish the
71245 		 *  cases.  Hopefully this is correct.  The binding power must be
71246 		 *  such that parsing ends at an LPAREN (CallExpression) but not at
71247 		 *  a PERIOD or LBRACKET (MemberExpression).
71248 		 *
71249 		 *  See doc/compiler.rst for discussion on the parsing approach,
71250 		 *  and testcases/test-dev-new.js for a bunch of documented tests.
71251 		 */
71252 
71253 		duk_regconst_t reg_target;
71254 		duk_int_t nargs;
71255 
71256 		DUK_DDD(DUK_DDDPRINT("begin parsing new expression"));
71257 
71258 		reg_target = DUK__ALLOCTEMPS(comp_ctx, 2);
71259 
71260 #if defined(DUK_USE_ES6)
71261 		if (comp_ctx->curr_token.t == DUK_TOK_PERIOD) {
71262 			/* new.target */
71263 			DUK_DDD(DUK_DDDPRINT("new.target"));
71264 			duk__advance(comp_ctx);
71265 			if (comp_ctx->curr_token.t_nores != DUK_TOK_IDENTIFIER ||
71266 			    !duk_hstring_equals_ascii_cstring(comp_ctx->curr_token.str1, "target")) {
71267 				goto syntax_error_newtarget;
71268 			}
71269 			if (comp_ctx->curr_func.is_global) {
71270 				goto syntax_error_newtarget;
71271 			}
71272 			duk__advance(comp_ctx);
71273 			duk__emit_bc(comp_ctx,
71274 			             DUK_OP_NEWTARGET,
71275 			             reg_target);
71276 			duk__ivalue_regconst(res, reg_target);
71277 			return;
71278 		}
71279 #endif  /* DUK_USE_ES6 */
71280 
71281 		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_CALL /*rbp_flags*/, reg_target /*forced_reg*/);
71282 		duk__emit_bc(comp_ctx, DUK_OP_NEWOBJ, reg_target + 1);  /* default instance */
71283 		DUK__SETTEMP(comp_ctx, reg_target + 2);
71284 
71285 		/* XXX: 'new obj.noSuch()' doesn't use GETPROPC now which
71286 		 * makes the error message worse than for obj.noSuch().
71287 		 */
71288 
71289 		if (comp_ctx->curr_token.t == DUK_TOK_LPAREN) {
71290 			/* 'new' MemberExpression Arguments */
71291 			DUK_DDD(DUK_DDDPRINT("new expression has argument list"));
71292 			duk__advance(comp_ctx);
71293 			nargs = duk__parse_arguments(comp_ctx, res);  /* parse args starting from "next temp", reg_target + 1 */
71294 			/* right paren eaten */
71295 		} else {
71296 			/* 'new' MemberExpression */
71297 			DUK_DDD(DUK_DDDPRINT("new expression has no argument list"));
71298 			nargs = 0;
71299 		}
71300 
71301 		duk__emit_a_bc(comp_ctx,
71302 		              DUK_OP_CALL0 | DUK_BC_CALL_FLAG_CONSTRUCT,
71303 		              nargs /*num_args*/,
71304 		              reg_target /*target*/);
71305 
71306 		DUK_DDD(DUK_DDDPRINT("end parsing new expression"));
71307 
71308 		duk__ivalue_regconst(res, reg_target);
71309 		return;
71310 	}
71311 
71312 	/* FUNCTION EXPRESSIONS */
71313 
71314 	case DUK_TOK_FUNCTION: {
71315 		/* Function expression.  Note that any statement beginning with 'function'
71316 		 * is handled by the statement parser as a function declaration, or a
71317 		 * non-standard function expression/statement (or a SyntaxError).  We only
71318 		 * handle actual function expressions (occurring inside an expression) here.
71319 		 *
71320 		 * O(depth^2) parse count for inner functions is handled by recording a
71321 		 * lexer offset on the first compilation pass, so that the function can
71322 		 * be efficiently skipped on the second pass.  This is encapsulated into
71323 		 * duk__parse_func_like_fnum().
71324 		 */
71325 
71326 		duk_regconst_t reg_temp;
71327 		duk_int_t fnum;
71328 
71329 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
71330 
71331 		/* curr_token follows 'function' */
71332 		fnum = duk__parse_func_like_fnum(comp_ctx, 0 /*flags*/);
71333 		DUK_DDD(DUK_DDDPRINT("parsed inner function -> fnum %ld", (long) fnum));
71334 
71335 		duk__emit_a_bc(comp_ctx,
71336 		               DUK_OP_CLOSURE,
71337 		               reg_temp /*a*/,
71338 		               (duk_regconst_t) fnum /*bc*/);
71339 
71340 		duk__ivalue_regconst(res, reg_temp);
71341 		return;
71342 	}
71343 
71344 	/* UNARY EXPRESSIONS */
71345 
71346 	case DUK_TOK_DELETE: {
71347 		/* Delete semantics are a bit tricky.  The description in E5 specification
71348 		 * is kind of confusing, because it distinguishes between resolvability of
71349 		 * a reference (which is only known at runtime) seemingly at compile time
71350 		 * (= SyntaxError throwing).
71351 		 */
71352 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
71353 		if (res->t == DUK_IVAL_VAR) {
71354 			/* not allowed in strict mode, regardless of whether resolves;
71355 			 * in non-strict mode DELVAR handles both non-resolving and
71356 			 * resolving cases (the specification description is a bit confusing).
71357 			 */
71358 
71359 			duk_regconst_t reg_temp;
71360 			duk_regconst_t reg_varbind;
71361 			duk_regconst_t rc_varname;
71362 
71363 			if (comp_ctx->curr_func.is_strict) {
71364 				DUK_ERROR_SYNTAX(thr, DUK_STR_CANNOT_DELETE_IDENTIFIER);
71365 				DUK_WO_NORETURN(return;);
71366 			}
71367 
71368 			DUK__SETTEMP(comp_ctx, temp_at_entry);
71369 			reg_temp = DUK__ALLOCTEMP(comp_ctx);
71370 
71371 			duk_dup(thr, res->x1.valstack_idx);
71372 			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
71373 				/* register bound variables are non-configurable -> always false */
71374 				duk__emit_bc(comp_ctx,
71375 				             DUK_OP_LDFALSE,
71376 				             reg_temp);
71377 			} else {
71378 				duk_dup(thr, res->x1.valstack_idx);
71379 				rc_varname = duk__getconst(comp_ctx);
71380 				duk__emit_a_bc(comp_ctx,
71381 				               DUK_OP_DELVAR,
71382 				               reg_temp,
71383 				               rc_varname);
71384 			}
71385 			duk__ivalue_regconst(res, reg_temp);
71386 		} else if (res->t == DUK_IVAL_PROP) {
71387 			duk_regconst_t reg_temp;
71388 			duk_regconst_t reg_obj;
71389 			duk_regconst_t rc_key;
71390 
71391 			DUK__SETTEMP(comp_ctx, temp_at_entry);
71392 			reg_temp = DUK__ALLOCTEMP(comp_ctx);
71393 			reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
71394 			rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
71395 			duk__emit_a_b_c(comp_ctx,
71396 			                DUK_OP_DELPROP | DUK__EMIT_FLAG_BC_REGCONST,
71397 			                reg_temp,
71398 			                reg_obj,
71399 			                rc_key);
71400 
71401 			duk__ivalue_regconst(res, reg_temp);
71402 		} else {
71403 			/* non-Reference deletion is always 'true', even in strict mode */
71404 			duk_push_true(thr);
71405 			goto plain_value;
71406 		}
71407 		return;
71408 	}
71409 	case DUK_TOK_VOID: {
71410 		duk__expr_toplain_ignore(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
71411 		duk_push_undefined(thr);
71412 		goto plain_value;
71413 	}
71414 	case DUK_TOK_TYPEOF: {
71415 		/* 'typeof' must handle unresolvable references without throwing
71416 		 * a ReferenceError (E5 Section 11.4.3).  Register mapped values
71417 		 * will never be unresolvable so special handling is only required
71418 		 * when an identifier is a "slow path" one.
71419 		 */
71420 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
71421 
71422 		if (res->t == DUK_IVAL_VAR) {
71423 			duk_regconst_t reg_varbind;
71424 			duk_regconst_t rc_varname;
71425 			duk_regconst_t reg_temp;
71426 
71427 			duk_dup(thr, res->x1.valstack_idx);
71428 			if (!duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
71429 				DUK_DDD(DUK_DDDPRINT("typeof for an identifier name which could not be resolved "
71430 				                     "at compile time, need to use special run-time handling"));
71431 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
71432 				duk__emit_a_bc(comp_ctx,
71433 				               DUK_OP_TYPEOFID,
71434 				               reg_temp,
71435 				               rc_varname);
71436 				duk__ivalue_regconst(res, reg_temp);
71437 				return;
71438 			}
71439 		}
71440 
71441 		args = DUK_OP_TYPEOF;
71442 		goto unary;
71443 	}
71444 	case DUK_TOK_INCREMENT: {
71445 		args = (DUK_OP_PREINCP << 8) + DUK_OP_PREINCR;
71446 		goto preincdec;
71447 	}
71448 	case DUK_TOK_DECREMENT: {
71449 		args = (DUK_OP_PREDECP << 8) + DUK_OP_PREDECR;
71450 		goto preincdec;
71451 	}
71452 	case DUK_TOK_ADD: {
71453 		/* unary plus */
71454 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
71455 		if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE &&
71456 		    duk_is_number(thr, res->x1.valstack_idx)) {
71457 			/* unary plus of a number is identity */
71458 			return;
71459 		}
71460 		args = DUK_OP_UNP;
71461 		goto unary;
71462 	}
71463 	case DUK_TOK_SUB: {
71464 		/* unary minus */
71465 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
71466 		if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE &&
71467 		    duk_is_number(thr, res->x1.valstack_idx)) {
71468 			/* this optimization is important to handle negative literals
71469 			 * (which are not directly provided by the lexical grammar)
71470 			 */
71471 			duk_tval *tv_num;
71472 			duk_double_union du;
71473 
71474 			tv_num = DUK_GET_TVAL_POSIDX(thr, res->x1.valstack_idx);
71475 			DUK_ASSERT(tv_num != NULL);
71476 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_num));
71477 			du.d = DUK_TVAL_GET_NUMBER(tv_num);
71478 			du.d = -du.d;
71479 			DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
71480 			DUK_TVAL_SET_NUMBER(tv_num, du.d);
71481 			return;
71482 		}
71483 		args = DUK_OP_UNM;
71484 		goto unary;
71485 	}
71486 	case DUK_TOK_BNOT: {
71487 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
71488 		args = DUK_OP_BNOT;
71489 		goto unary;
71490 	}
71491 	case DUK_TOK_LNOT: {
71492 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
71493 		if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE) {
71494 			/* Very minimal inlining to handle common idioms '!0' and '!1',
71495 			 * and also boolean arguments like '!false' and '!true'.
71496 			 */
71497 			duk_tval *tv_val;
71498 
71499 			tv_val = DUK_GET_TVAL_POSIDX(thr, res->x1.valstack_idx);
71500 			DUK_ASSERT(tv_val != NULL);
71501 			if (DUK_TVAL_IS_NUMBER(tv_val)) {
71502 				duk_double_t d;
71503 				d = DUK_TVAL_GET_NUMBER(tv_val);
71504 				if (duk_double_equals(d, 0.0)) {
71505 					/* Matches both +0 and -0 on purpose. */
71506 					DUK_DDD(DUK_DDDPRINT("inlined lnot: !0 -> true"));
71507 					DUK_TVAL_SET_BOOLEAN_TRUE(tv_val);
71508 					return;
71509 				} else if (duk_double_equals(d, 1.0)) {
71510 					DUK_DDD(DUK_DDDPRINT("inlined lnot: !1 -> false"));
71511 					DUK_TVAL_SET_BOOLEAN_FALSE(tv_val);
71512 					return;
71513 				}
71514 			} else if (DUK_TVAL_IS_BOOLEAN(tv_val)) {
71515 				duk_small_uint_t v;
71516 				v = DUK_TVAL_GET_BOOLEAN(tv_val);
71517 				DUK_DDD(DUK_DDDPRINT("inlined lnot boolean: %ld", (long) v));
71518 				DUK_ASSERT(v == 0 || v == 1);
71519 				DUK_TVAL_SET_BOOLEAN(tv_val, v ^ 0x01);
71520 				return;
71521 			}
71522 		}
71523 		args = DUK_OP_LNOT;
71524 		goto unary;
71525 	}
71526 
71527 	}  /* end switch */
71528 
71529 	DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);
71530 	DUK_WO_NORETURN(return;);
71531 
71532  unary:
71533 	{
71534 		/* Unary opcodes use just the 'BC' register source because it
71535 		 * matches current shuffle limits, and maps cleanly to 16 high
71536 		 * bits of the opcode.
71537 		 */
71538 
71539 		duk_regconst_t reg_src, reg_res;
71540 
71541 		reg_src = duk__ivalue_toregconst_raw(comp_ctx, res, -1 /*forced_reg*/, 0 /*flags*/);
71542 		if (DUK__ISREG_TEMP(comp_ctx, reg_src)) {
71543 			reg_res = reg_src;
71544 		} else {
71545 			reg_res = DUK__ALLOCTEMP(comp_ctx);
71546 		}
71547 		duk__emit_a_bc(comp_ctx,
71548 		             args,
71549 		             reg_res,
71550 		             reg_src);
71551 		duk__ivalue_regconst(res, reg_res);
71552 		return;
71553 	}
71554 
71555  preincdec:
71556 	{
71557 		/* preincrement and predecrement */
71558 		duk_regconst_t reg_res;
71559 		duk_small_uint_t args_op1 = args & 0xff;  /* DUK_OP_PREINCR/DUK_OP_PREDECR */
71560 		duk_small_uint_t args_op2 = args >> 8;    /* DUK_OP_PREINCP_RR/DUK_OP_PREDECP_RR */
71561 
71562 		/* Specific assumptions for opcode numbering. */
71563 		DUK_ASSERT(DUK_OP_PREINCR + 4 == DUK_OP_PREINCV);
71564 		DUK_ASSERT(DUK_OP_PREDECR + 4 == DUK_OP_PREDECV);
71565 
71566 		reg_res = DUK__ALLOCTEMP(comp_ctx);
71567 
71568 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
71569 		if (res->t == DUK_IVAL_VAR) {
71570 			duk_hstring *h_varname;
71571 			duk_regconst_t reg_varbind;
71572 			duk_regconst_t rc_varname;
71573 
71574 			h_varname = duk_known_hstring(thr, res->x1.valstack_idx);
71575 
71576 			if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
71577 				goto syntax_error;
71578 			}
71579 
71580 			duk_dup(thr, res->x1.valstack_idx);
71581 			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
71582 				duk__emit_a_bc(comp_ctx,
71583 				               args_op1,  /* e.g. DUK_OP_PREINCR */
71584 				               reg_res,
71585 				               reg_varbind);
71586 			} else {
71587 				duk__emit_a_bc(comp_ctx,
71588 				                args_op1 + 4,  /* e.g. DUK_OP_PREINCV */
71589 				                reg_res,
71590 				                rc_varname);
71591 			}
71592 
71593 			DUK_DDD(DUK_DDDPRINT("preincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
71594 			                     (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
71595 		} else if (res->t == DUK_IVAL_PROP) {
71596 			duk_regconst_t reg_obj;  /* allocate to reg only (not const) */
71597 			duk_regconst_t rc_key;
71598 			reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
71599 			rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
71600 			duk__emit_a_b_c(comp_ctx,
71601 			                args_op2 | DUK__EMIT_FLAG_BC_REGCONST,  /* e.g. DUK_OP_PREINCP */
71602 			                reg_res,
71603 			                reg_obj,
71604 			                rc_key);
71605 		} else {
71606 			/* Technically return value is not needed because INVLHS will
71607 			 * unconditially throw a ReferenceError.  Coercion is necessary
71608 			 * for proper semantics (consider ToNumber() called for an object).
71609 			 * Use DUK_OP_UNP with a dummy register to get ToNumber().
71610 			 */
71611 
71612 			duk__ivalue_toforcedreg(comp_ctx, res, reg_res);
71613 			duk__emit_bc(comp_ctx,
71614 			             DUK_OP_UNP,
71615 			             reg_res);  /* for side effects, result ignored */
71616 			duk__emit_op_only(comp_ctx,
71617 			                  DUK_OP_INVLHS);
71618 		}
71619 		DUK__SETTEMP(comp_ctx, reg_res + 1);
71620 		duk__ivalue_regconst(res, reg_res);
71621 		return;
71622 	}
71623 
71624  plain_value:
71625 	{
71626 		/* Stack top contains plain value */
71627 		duk__ivalue_plain_fromstack(comp_ctx, res);
71628 		return;
71629 	}
71630 
71631 #if defined(DUK_USE_ES6)
71632  syntax_error_newtarget:
71633 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_NEWTARGET);
71634 	DUK_WO_NORETURN(return;);
71635 #endif
71636 
71637  syntax_error:
71638 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_EXPRESSION);
71639 	DUK_WO_NORETURN(return;);
71640 }
71641 
71642 /* XXX: add flag to indicate whether caller cares about return value; this
71643  * affects e.g. handling of assignment expressions.  This change needs API
71644  * changes elsewhere too.
71645  */
71646 DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ivalue *res) {
71647 	duk_hthread *thr = comp_ctx->thr;
71648 	duk_token *tk;
71649 	duk_small_uint_t tok;
71650 	duk_uint32_t args;  /* temp variable to pass constants and flags to shared code */
71651 
71652 	/*
71653 	 *  ctx->prev_token     token to process with duk__expr_led()
71654 	 *  ctx->curr_token     updated by caller
71655 	 */
71656 
71657 	comp_ctx->curr_func.led_count++;
71658 
71659 	/* The token in the switch has already been eaten here */
71660 	tk = &comp_ctx->prev_token;
71661 	tok = tk->t;
71662 
71663 	DUK_DDD(DUK_DDDPRINT("duk__expr_led(), prev_token.t=%ld, allow_in=%ld, paren_level=%ld",
71664 	                     (long) tk->t, (long) comp_ctx->curr_func.allow_in, (long) comp_ctx->curr_func.paren_level));
71665 
71666 	/* XXX: default priority for infix operators is duk__expr_lbp(tok) -> get it here? */
71667 
71668 	switch (tok) {
71669 
71670 	/* PRIMARY EXPRESSIONS */
71671 
71672 	case DUK_TOK_PERIOD: {
71673 		/* Property access expressions are critical for correct LHS ordering,
71674 		 * see comments in duk__expr()!
71675 		 *
71676 		 * A conservative approach would be to use duk__ivalue_totempconst()
71677 		 * for 'left'.  However, allowing a reg-bound variable seems safe here
71678 		 * and is nice because "foo.bar" is a common expression.  If the ivalue
71679 		 * is used in an expression a GETPROP will occur before any changes to
71680 		 * the base value can occur.  If the ivalue is used as an assignment
71681 		 * LHS, the assignment code will ensure the base value is safe from
71682 		 * RHS mutation.
71683 		 */
71684 
71685 		/* XXX: This now coerces an identifier into a GETVAR to a temp, which
71686 		 * causes an extra LDREG in call setup.  It's sufficient to coerce to a
71687 		 * unary ivalue?
71688 		 */
71689 		duk__ivalue_toplain(comp_ctx, left);
71690 
71691 		/* NB: must accept reserved words as property name */
71692 		if (comp_ctx->curr_token.t_nores != DUK_TOK_IDENTIFIER) {
71693 			DUK_ERROR_SYNTAX(thr, DUK_STR_EXPECTED_IDENTIFIER);
71694 			DUK_WO_NORETURN(return;);
71695 		}
71696 
71697 		res->t = DUK_IVAL_PROP;
71698 		duk__copy_ispec(comp_ctx, &left->x1, &res->x1);  /* left.x1 -> res.x1 */
71699 		DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
71700 		duk_push_hstring(thr, comp_ctx->curr_token.str1);
71701 		duk_replace(thr, res->x2.valstack_idx);
71702 		res->x2.t = DUK_ISPEC_VALUE;
71703 
71704 		/* special RegExp literal handling after IdentifierName */
71705 		comp_ctx->curr_func.reject_regexp_in_adv = 1;
71706 
71707 		duk__advance(comp_ctx);
71708 		return;
71709 	}
71710 	case DUK_TOK_LBRACKET: {
71711 		/* Property access expressions are critical for correct LHS ordering,
71712 		 * see comments in duk__expr()!
71713 		 */
71714 
71715 		/* XXX: optimize temp reg use */
71716 		/* XXX: similar coercion issue as in DUK_TOK_PERIOD */
71717 		/* XXX: coerce to regs? it might be better for enumeration use, where the
71718 		 * same PROP ivalue is used multiple times.  Or perhaps coerce PROP further
71719 		 * there?
71720 		 */
71721 		/* XXX: for simple cases like x['y'] an unnecessary LDREG is
71722 		 * emitted for the base value; could avoid it if we knew that
71723 		 * the key expression is safe (e.g. just a single literal).
71724 		 */
71725 
71726 		/* The 'left' value must not be a register bound variable
71727 		 * because it may be mutated during the rest of the expression
71728 		 * and E5.1 Section 11.2.1 specifies the order of evaluation
71729 		 * so that the base value is evaluated first.
71730 		 * See: test-bug-nested-prop-mutate.js.
71731 		 */
71732 		duk__ivalue_totempconst(comp_ctx, left);
71733 		duk__expr_toplain(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);  /* Expression, ']' terminates */
71734 		duk__advance_expect(comp_ctx, DUK_TOK_RBRACKET);
71735 
71736 		res->t = DUK_IVAL_PROP;
71737 		duk__copy_ispec(comp_ctx, &res->x1, &res->x2);   /* res.x1 -> res.x2 */
71738 		duk__copy_ispec(comp_ctx, &left->x1, &res->x1);  /* left.x1 -> res.x1 */
71739 		return;
71740 	}
71741 	case DUK_TOK_LPAREN: {
71742 		/* function call */
71743 		duk_regconst_t reg_cs = DUK__ALLOCTEMPS(comp_ctx, 2);
71744 		duk_int_t nargs;
71745 		duk_small_uint_t call_op = DUK_OP_CALL0;
71746 
71747 		/* XXX: attempt to get the call result to "next temp" whenever
71748 		 * possible to avoid unnecessary register shuffles.
71749 		 */
71750 
71751 		/*
71752 		 *  Setup call: target and 'this' binding.  Three cases:
71753 		 *
71754 		 *    1. Identifier base (e.g. "foo()")
71755 		 *    2. Property base (e.g. "foo.bar()")
71756 		 *    3. Register base (e.g. "foo()()"; i.e. when a return value is a function)
71757 		 */
71758 
71759 		if (left->t == DUK_IVAL_VAR) {
71760 			duk_hstring *h_varname;
71761 			duk_regconst_t reg_varbind;
71762 			duk_regconst_t rc_varname;
71763 
71764 			DUK_DDD(DUK_DDDPRINT("function call with identifier base"));
71765 
71766 			h_varname = duk_known_hstring(thr, left->x1.valstack_idx);
71767 			if (h_varname == DUK_HTHREAD_STRING_EVAL(thr)) {
71768 				/* Potential direct eval call detected, flag the CALL
71769 				 * so that a run-time "direct eval" check is made and
71770 				 * special behavior may be triggered.  Note that this
71771 				 * does not prevent 'eval' from being register bound.
71772 				 */
71773 				DUK_DDD(DUK_DDDPRINT("function call with identifier 'eval' "
71774 				                     "-> using EVALCALL, marking function "
71775 				                     "as may_direct_eval"));
71776 				call_op |= DUK_BC_CALL_FLAG_CALLED_AS_EVAL;
71777 				comp_ctx->curr_func.may_direct_eval = 1;
71778 			}
71779 
71780 			duk_dup(thr, left->x1.valstack_idx);
71781 			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
71782 				duk__emit_a_bc(comp_ctx,
71783 				              DUK_OP_CSREG | DUK__EMIT_FLAG_A_IS_SOURCE,
71784 				              reg_varbind,
71785 				              reg_cs + 0);
71786 			} else {
71787 				/* XXX: expand target register or constant field to
71788 				 * reduce shuffling.
71789 				 */
71790 				DUK_ASSERT(DUK__ISCONST(rc_varname));
71791 				duk__emit_a_b(comp_ctx,
71792 				              DUK_OP_CSVAR | DUK__EMIT_FLAG_BC_REGCONST,
71793 				              reg_cs + 0,
71794 				              rc_varname);
71795 			}
71796 		} else if (left->t == DUK_IVAL_PROP) {
71797 			/* Call through a property lookup, E5 Section 11.2.3, step 6.a.i,
71798 			 * E5 Section 10.4.3.  There used to be a separate CSPROP opcode
71799 			 * but a typical call setup took 3 opcodes (e.g. LDREG, LDCONST,
71800 			 * CSPROP) and the same can be achieved with ordinary loads.
71801 			 */
71802 #if defined(DUK_USE_VERBOSE_ERRORS)
71803 			duk_regconst_t reg_key;
71804 #endif
71805 
71806 			DUK_DDD(DUK_DDDPRINT("function call with property base"));
71807 
71808 			/* XXX: For Math.sin() this generates: LDCONST + LDREG +
71809 			 * GETPROPC + call.  The LDREG is unnecessary because LDCONST
71810 			 * could be loaded directly into reg_cs + 1.  This doesn't
71811 			 * happen now because a variable cannot be in left->x1 of a
71812 			 * DUK_IVAL_PROP.  We could notice that left->x1 is a temp
71813 			 * and reuse, but it would still be in the wrong position
71814 			 * (reg_cs + 0 rather than reg_cs + 1).
71815 			 */
71816 			duk__ispec_toforcedreg(comp_ctx, &left->x1, reg_cs + 1);  /* base */
71817 #if defined(DUK_USE_VERBOSE_ERRORS)
71818 			reg_key = duk__ispec_toregconst_raw(comp_ctx, &left->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
71819 			duk__emit_a_b_c(comp_ctx,
71820 			                DUK_OP_GETPROPC | DUK__EMIT_FLAG_BC_REGCONST,
71821 			                reg_cs + 0,
71822 			                reg_cs + 1,
71823 			                reg_key);
71824 #else
71825 			duk__ivalue_toforcedreg(comp_ctx, left, reg_cs + 0);  /* base[key] */
71826 #endif
71827 		} else {
71828 			DUK_DDD(DUK_DDDPRINT("function call with register base"));
71829 
71830 			duk__ivalue_toforcedreg(comp_ctx, left, reg_cs + 0);
71831 #if 0
71832 			duk__emit_a_bc(comp_ctx,
71833 			               DUK_OP_CSREG | DUK__EMIT_FLAG_A_IS_SOURCE,
71834 			               reg_cs + 0,
71835 			               reg_cs + 0);  /* in-place setup */
71836 #endif
71837 			/* Because of in-place setup, REGCS is equivalent to
71838 			 * just this LDUNDEF.
71839 			 */
71840 			duk__emit_bc(comp_ctx, DUK_OP_LDUNDEF, reg_cs + 1);
71841 		}
71842 
71843 		DUK__SETTEMP(comp_ctx, reg_cs + 2);
71844 		nargs = duk__parse_arguments(comp_ctx, res);  /* parse args starting from "next temp" */
71845 
71846 		/* Tailcalls are handled by back-patching the already emitted opcode
71847 		 * later in return statement parser.
71848 		 */
71849 
71850 		duk__emit_a_bc(comp_ctx,
71851 		               call_op,
71852 		               (duk_regconst_t) nargs /*numargs*/,
71853 		               reg_cs /*basereg*/);
71854 		DUK__SETTEMP(comp_ctx, reg_cs + 1);    /* result in csreg */
71855 
71856 		duk__ivalue_regconst(res, reg_cs);
71857 		return;
71858 	}
71859 
71860 	/* POSTFIX EXPRESSION */
71861 
71862 	case DUK_TOK_INCREMENT: {
71863 		args = (DUK_OP_POSTINCP_RR << 16) + (DUK_OP_POSTINCR << 8) + 0;
71864 		goto postincdec;
71865 	}
71866 	case DUK_TOK_DECREMENT: {
71867 		args = (DUK_OP_POSTDECP_RR << 16) + (DUK_OP_POSTDECR << 8) + 0;
71868 		goto postincdec;
71869 	}
71870 
71871 	/* EXPONENTIATION EXPRESSION */
71872 
71873 #if defined(DUK_USE_ES7_EXP_OPERATOR)
71874 	case DUK_TOK_EXP: {
71875 		args = (DUK_OP_EXP << 8) + DUK__BP_EXPONENTIATION - 1;  /* UnaryExpression */
71876 		goto binary;
71877 	}
71878 #endif
71879 
71880 	/* MULTIPLICATIVE EXPRESSION */
71881 
71882 	case DUK_TOK_MUL: {
71883 		args = (DUK_OP_MUL << 8) + DUK__BP_MULTIPLICATIVE;  /* ExponentiationExpression */
71884 		goto binary;
71885 	}
71886 	case DUK_TOK_DIV: {
71887 		args = (DUK_OP_DIV << 8) + DUK__BP_MULTIPLICATIVE;  /* ExponentiationExpression */
71888 		goto binary;
71889 	}
71890 	case DUK_TOK_MOD: {
71891 		args = (DUK_OP_MOD << 8) + DUK__BP_MULTIPLICATIVE;  /* ExponentiationExpression */
71892 		goto binary;
71893 	}
71894 
71895 	/* ADDITIVE EXPRESSION */
71896 
71897 	case DUK_TOK_ADD: {
71898 		args = (DUK_OP_ADD << 8) + DUK__BP_ADDITIVE;  /* MultiplicativeExpression */
71899 		goto binary;
71900 	}
71901 	case DUK_TOK_SUB: {
71902 		args = (DUK_OP_SUB << 8) + DUK__BP_ADDITIVE;  /* MultiplicativeExpression */
71903 		goto binary;
71904 	}
71905 
71906 	/* SHIFT EXPRESSION */
71907 
71908 	case DUK_TOK_ALSHIFT: {
71909 		/* << */
71910 		args = (DUK_OP_BASL << 8) + DUK__BP_SHIFT;
71911 		goto binary;
71912 	}
71913 	case DUK_TOK_ARSHIFT: {
71914 		/* >> */
71915 		args = (DUK_OP_BASR << 8) + DUK__BP_SHIFT;
71916 		goto binary;
71917 	}
71918 	case DUK_TOK_RSHIFT: {
71919 		/* >>> */
71920 		args = (DUK_OP_BLSR << 8) + DUK__BP_SHIFT;
71921 		goto binary;
71922 	}
71923 
71924 	/* RELATIONAL EXPRESSION */
71925 
71926 	case DUK_TOK_LT: {
71927 		/* < */
71928 		args = (DUK_OP_LT << 8) + DUK__BP_RELATIONAL;
71929 		goto binary;
71930 	}
71931 	case DUK_TOK_GT: {
71932 		args = (DUK_OP_GT << 8) + DUK__BP_RELATIONAL;
71933 		goto binary;
71934 	}
71935 	case DUK_TOK_LE: {
71936 		args = (DUK_OP_LE << 8) + DUK__BP_RELATIONAL;
71937 		goto binary;
71938 	}
71939 	case DUK_TOK_GE: {
71940 		args = (DUK_OP_GE << 8) + DUK__BP_RELATIONAL;
71941 		goto binary;
71942 	}
71943 	case DUK_TOK_INSTANCEOF: {
71944 		args = (DUK_OP_INSTOF << 8) + DUK__BP_RELATIONAL;
71945 		goto binary;
71946 	}
71947 	case DUK_TOK_IN: {
71948 		args = (DUK_OP_IN << 8) + DUK__BP_RELATIONAL;
71949 		goto binary;
71950 	}
71951 
71952 	/* EQUALITY EXPRESSION */
71953 
71954 	case DUK_TOK_EQ: {
71955 		args = (DUK_OP_EQ << 8) + DUK__BP_EQUALITY;
71956 		goto binary;
71957 	}
71958 	case DUK_TOK_NEQ: {
71959 		args = (DUK_OP_NEQ << 8) + DUK__BP_EQUALITY;
71960 		goto binary;
71961 	}
71962 	case DUK_TOK_SEQ: {
71963 		args = (DUK_OP_SEQ << 8) + DUK__BP_EQUALITY;
71964 		goto binary;
71965 	}
71966 	case DUK_TOK_SNEQ: {
71967 		args = (DUK_OP_SNEQ << 8) + DUK__BP_EQUALITY;
71968 		goto binary;
71969 	}
71970 
71971 	/* BITWISE EXPRESSIONS */
71972 
71973 	case DUK_TOK_BAND: {
71974 		args = (DUK_OP_BAND << 8) + DUK__BP_BAND;
71975 		goto binary;
71976 	}
71977 	case DUK_TOK_BXOR: {
71978 		args = (DUK_OP_BXOR << 8) + DUK__BP_BXOR;
71979 		goto binary;
71980 	}
71981 	case DUK_TOK_BOR: {
71982 		args = (DUK_OP_BOR << 8) + DUK__BP_BOR;
71983 		goto binary;
71984 	}
71985 
71986 	/* LOGICAL EXPRESSIONS */
71987 
71988 	case DUK_TOK_LAND: {
71989 		/* syntactically left-associative but parsed as right-associative */
71990 		args = (1 << 8) + DUK__BP_LAND - 1;
71991 		goto binary_logical;
71992 	}
71993 	case DUK_TOK_LOR: {
71994 		/* syntactically left-associative but parsed as right-associative */
71995 		args = (0 << 8) + DUK__BP_LOR - 1;
71996 		goto binary_logical;
71997 	}
71998 
71999 	/* CONDITIONAL EXPRESSION */
72000 
72001 	case DUK_TOK_QUESTION: {
72002 		/* XXX: common reg allocation need is to reuse a sub-expression's temp reg,
72003 		 * but only if it really is a temp.  Nothing fancy here now.
72004 		 */
72005 		duk_regconst_t reg_temp;
72006 		duk_int_t pc_jump1;
72007 		duk_int_t pc_jump2;
72008 
72009 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
72010 		duk__ivalue_toforcedreg(comp_ctx, left, reg_temp);
72011 		duk__emit_if_true_skip(comp_ctx, reg_temp);
72012 		pc_jump1 = duk__emit_jump_empty(comp_ctx);  /* jump to false */
72013 		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);  /* AssignmentExpression */
72014 		duk__advance_expect(comp_ctx, DUK_TOK_COLON);
72015 		pc_jump2 = duk__emit_jump_empty(comp_ctx);  /* jump to end */
72016 		duk__patch_jump_here(comp_ctx, pc_jump1);
72017 		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);  /* AssignmentExpression */
72018 		duk__patch_jump_here(comp_ctx, pc_jump2);
72019 
72020 		DUK__SETTEMP(comp_ctx, reg_temp + 1);
72021 		duk__ivalue_regconst(res, reg_temp);
72022 		return;
72023 	}
72024 
72025 	/* ASSIGNMENT EXPRESSION */
72026 
72027 	case DUK_TOK_EQUALSIGN: {
72028 		/*
72029 		 *  Assignments are right associative, allows e.g.
72030 		 *    a = 5;
72031 		 *    a += b = 9;   // same as a += (b = 9)
72032 		 *  -> expression value 14, a = 14, b = 9
72033 		 *
72034 		 *  Right associativiness is reflected in the BP for recursion,
72035 		 *  "-1" ensures assignment operations are allowed.
72036 		 *
72037 		 *  XXX: just use DUK__BP_COMMA (i.e. no need for 2-step bp levels)?
72038 		 */
72039 		args = (DUK_OP_NONE << 8) + DUK__BP_ASSIGNMENT - 1;   /* DUK_OP_NONE marks a 'plain' assignment */
72040 		goto assign;
72041 	}
72042 	case DUK_TOK_ADD_EQ: {
72043 		/* right associative */
72044 		args = (DUK_OP_ADD << 8) + DUK__BP_ASSIGNMENT - 1;
72045 		goto assign;
72046 	}
72047 	case DUK_TOK_SUB_EQ: {
72048 		/* right associative */
72049 		args = (DUK_OP_SUB << 8) + DUK__BP_ASSIGNMENT - 1;
72050 		goto assign;
72051 	}
72052 	case DUK_TOK_MUL_EQ: {
72053 		/* right associative */
72054 		args = (DUK_OP_MUL << 8) + DUK__BP_ASSIGNMENT - 1;
72055 		goto assign;
72056 	}
72057 	case DUK_TOK_DIV_EQ: {
72058 		/* right associative */
72059 		args = (DUK_OP_DIV << 8) + DUK__BP_ASSIGNMENT - 1;
72060 		goto assign;
72061 	}
72062 	case DUK_TOK_MOD_EQ: {
72063 		/* right associative */
72064 		args = (DUK_OP_MOD << 8) + DUK__BP_ASSIGNMENT - 1;
72065 		goto assign;
72066 	}
72067 #if defined(DUK_USE_ES7_EXP_OPERATOR)
72068 	case DUK_TOK_EXP_EQ: {
72069 		/* right associative */
72070 		args = (DUK_OP_EXP << 8) + DUK__BP_ASSIGNMENT - 1;
72071 		goto assign;
72072 	}
72073 #endif
72074 	case DUK_TOK_ALSHIFT_EQ: {
72075 		/* right associative */
72076 		args = (DUK_OP_BASL << 8) + DUK__BP_ASSIGNMENT - 1;
72077 		goto assign;
72078 	}
72079 	case DUK_TOK_ARSHIFT_EQ: {
72080 		/* right associative */
72081 		args = (DUK_OP_BASR << 8) + DUK__BP_ASSIGNMENT - 1;
72082 		goto assign;
72083 	}
72084 	case DUK_TOK_RSHIFT_EQ: {
72085 		/* right associative */
72086 		args = (DUK_OP_BLSR << 8) + DUK__BP_ASSIGNMENT - 1;
72087 		goto assign;
72088 	}
72089 	case DUK_TOK_BAND_EQ: {
72090 		/* right associative */
72091 		args = (DUK_OP_BAND << 8) + DUK__BP_ASSIGNMENT - 1;
72092 		goto assign;
72093 	}
72094 	case DUK_TOK_BOR_EQ: {
72095 		/* right associative */
72096 		args = (DUK_OP_BOR << 8) + DUK__BP_ASSIGNMENT - 1;
72097 		goto assign;
72098 	}
72099 	case DUK_TOK_BXOR_EQ: {
72100 		/* right associative */
72101 		args = (DUK_OP_BXOR << 8) + DUK__BP_ASSIGNMENT - 1;
72102 		goto assign;
72103 	}
72104 
72105 	/* COMMA */
72106 
72107 	case DUK_TOK_COMMA: {
72108 		/* right associative */
72109 
72110 		duk__ivalue_toplain_ignore(comp_ctx, left);  /* need side effects, not value */
72111 		duk__expr_toplain(comp_ctx, res, DUK__BP_COMMA - 1 /*rbp_flags*/);
72112 
72113 		/* return 'res' (of right part) as our result */
72114 		return;
72115 	}
72116 
72117 	default: {
72118 		break;
72119 	}
72120 	}
72121 
72122 	DUK_D(DUK_DPRINT("parse error: unexpected token: %ld", (long) tok));
72123 	DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);
72124 	DUK_WO_NORETURN(return;);
72125 
72126 #if 0
72127 	/* XXX: shared handling for 'duk__expr_lhs'? */
72128 	if (comp_ctx->curr_func.paren_level == 0 && XXX) {
72129 		comp_ctx->curr_func.duk__expr_lhs = 0;
72130 	}
72131 #endif
72132 
72133  binary:
72134 	/*
72135 	 *  Shared handling of binary operations
72136 	 *
72137 	 *  args = (opcode << 8) + rbp
72138 	 */
72139 	{
72140 		duk__ivalue_toplain(comp_ctx, left);
72141 		duk__expr_toplain(comp_ctx, res, args & 0xff /*rbp_flags*/);
72142 
72143 		/* combine left->x1 and res->x1 (right->x1, really) -> (left->x1 OP res->x1) */
72144 		DUK_ASSERT(left->t == DUK_IVAL_PLAIN);
72145 		DUK_ASSERT(res->t == DUK_IVAL_PLAIN);
72146 
72147 		res->t = DUK_IVAL_ARITH;
72148 		res->op = (args >> 8) & 0xff;
72149 
72150 		res->x2.t = res->x1.t;
72151 		res->x2.regconst = res->x1.regconst;
72152 		duk_copy(thr, res->x1.valstack_idx, res->x2.valstack_idx);
72153 
72154 		res->x1.t = left->x1.t;
72155 		res->x1.regconst = left->x1.regconst;
72156 		duk_copy(thr, left->x1.valstack_idx, res->x1.valstack_idx);
72157 
72158 		DUK_DDD(DUK_DDDPRINT("binary op, res: t=%ld, x1.t=%ld, x1.regconst=0x%08lx, x2.t=%ld, x2.regconst=0x%08lx",
72159 		                     (long) res->t, (long) res->x1.t, (unsigned long) res->x1.regconst, (long) res->x2.t, (unsigned long) res->x2.regconst));
72160 		return;
72161 	}
72162 
72163  binary_logical:
72164 	/*
72165 	 *  Shared handling for logical AND and logical OR.
72166 	 *
72167 	 *  args = (truthval << 8) + rbp
72168 	 *
72169 	 *  Truthval determines when to skip right-hand-side.
72170 	 *  For logical AND truthval=1, for logical OR truthval=0.
72171 	 *
72172 	 *  See doc/compiler.rst for discussion on compiling logical
72173 	 *  AND and OR expressions.  The approach here is very simplistic,
72174 	 *  generating extra jumps and multiple evaluations of truth values,
72175 	 *  but generates code on-the-fly with only local back-patching.
72176 	 *
72177 	 *  Both logical AND and OR are syntactically left-associated.
72178 	 *  However, logical ANDs are compiled as right associative
72179 	 *  expressions, i.e. "A && B && C" as "A && (B && C)", to allow
72180 	 *  skip jumps to skip over the entire tail.  Similarly for logical OR.
72181 	 */
72182 
72183 	{
72184 		duk_regconst_t reg_temp;
72185 		duk_int_t pc_jump;
72186 		duk_small_uint_t args_truthval = args >> 8;
72187 		duk_small_uint_t args_rbp = args & 0xff;
72188 
72189 		/* XXX: unoptimal use of temps, resetting */
72190 
72191 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
72192 
72193 		duk__ivalue_toforcedreg(comp_ctx, left, reg_temp);
72194 		DUK_ASSERT(DUK__ISREG(reg_temp));
72195 		duk__emit_bc(comp_ctx,
72196 		            (args_truthval ? DUK_OP_IFTRUE_R : DUK_OP_IFFALSE_R),
72197 		            reg_temp);  /* skip jump conditionally */
72198 		pc_jump = duk__emit_jump_empty(comp_ctx);
72199 		duk__expr_toforcedreg(comp_ctx, res, args_rbp /*rbp_flags*/, reg_temp /*forced_reg*/);
72200 		duk__patch_jump_here(comp_ctx, pc_jump);
72201 
72202 		duk__ivalue_regconst(res, reg_temp);
72203 		return;
72204 	}
72205 
72206  assign:
72207 	/*
72208 	 *  Shared assignment expression handling
72209 	 *
72210 	 *  args = (opcode << 8) + rbp
72211 	 *
72212 	 *  If 'opcode' is DUK_OP_NONE, plain assignment without arithmetic.
72213 	 *  Syntactically valid left-hand-side forms which are not accepted as
72214 	 *  left-hand-side values (e.g. as in "f() = 1") must NOT cause a
72215 	 *  SyntaxError, but rather a run-time ReferenceError.
72216 	 *
72217 	 *  When evaluating X <op>= Y, the LHS (X) is conceptually evaluated
72218 	 *  to a temporary first.  The RHS is then evaluated.  Finally, the
72219 	 *  <op> is applied to the initial value of RHS (not the value after
72220 	 *  RHS evaluation), and written to X.  Doing so concretely generates
72221 	 *  inefficient code so we'd like to avoid the temporary when possible.
72222 	 *  See: https://github.com/svaarala/duktape/pull/992.
72223 	 *
72224 	 *  The expression value (final LHS value, written to RHS) is
72225 	 *  conceptually copied into a fresh temporary so that it won't
72226 	 *  change even if the LHS/RHS values change in outer expressions.
72227 	 *  For example, it'd be generally incorrect for the expression value
72228 	 *  to be the RHS register binding, unless there's a guarantee that it
72229 	 *  won't change during further expression evaluation.  Using the
72230 	 *  temporary concretely produces inefficient bytecode, so we try to
72231 	 *  avoid the extra temporary for some known-to-be-safe cases.
72232 	 *  Currently the only safe case we detect is a "top level assignment",
72233 	 *  for example "x = y + z;", where the assignment expression value is
72234 	 *  ignored.
72235 	 *  See: test-dev-assign-expr.js and test-bug-assign-mutate-gh381.js.
72236 	 */
72237 
72238 	{
72239 		duk_small_uint_t args_op = args >> 8;
72240 		duk_small_uint_t args_rbp = args & 0xff;
72241 		duk_bool_t toplevel_assign;
72242 
72243 		/* XXX: here we need to know if 'left' is left-hand-side compatible.
72244 		 * That information is no longer available from current expr parsing
72245 		 * state; it would need to be carried into the 'left' ivalue or by
72246 		 * some other means.
72247 		 */
72248 
72249 		/* A top-level assignment is e.g. "x = y;".  For these it's safe
72250 		 * to use the RHS as-is as the expression value, even if the RHS
72251 		 * is a reg-bound identifier.  The RHS ('res') is right associative
72252 		 * so it has consumed all other assignment level operations; the
72253 		 * only relevant lower binding power construct is comma operator
72254 		 * which will ignore the expression value provided here.  Usually
72255 		 * the top level assignment expression value is ignored, but it
72256 		 * is relevant for e.g. eval code.
72257 		 */
72258 		toplevel_assign = (comp_ctx->curr_func.nud_count == 1 && /* one token before */
72259 		                   comp_ctx->curr_func.led_count == 1);  /* one operator (= assign) */
72260 		DUK_DDD(DUK_DDDPRINT("assignment: nud_count=%ld, led_count=%ld, toplevel_assign=%ld",
72261 		                     (long) comp_ctx->curr_func.nud_count,
72262 		                     (long) comp_ctx->curr_func.led_count,
72263 		                     (long) toplevel_assign));
72264 
72265 		if (left->t == DUK_IVAL_VAR) {
72266 			duk_hstring *h_varname;
72267 			duk_regconst_t reg_varbind;
72268 			duk_regconst_t rc_varname;
72269 
72270 			DUK_ASSERT(left->x1.t == DUK_ISPEC_VALUE);  /* LHS is already side effect free */
72271 
72272 			h_varname = duk_known_hstring(thr, left->x1.valstack_idx);
72273 			if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
72274 				/* E5 Section 11.13.1 (and others for other assignments), step 4. */
72275 				goto syntax_error_lvalue;
72276 			}
72277 			duk_dup(thr, left->x1.valstack_idx);
72278 			(void) duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname);
72279 
72280 			if (args_op == DUK_OP_NONE) {
72281 				duk__expr(comp_ctx, res, args_rbp /*rbp_flags*/);
72282 				if (toplevel_assign) {
72283 					/* Any 'res' will do. */
72284 					DUK_DDD(DUK_DDDPRINT("plain assignment, toplevel assign, use as is"));
72285 				} else {
72286 					/* 'res' must be a plain ivalue, and not register-bound variable. */
72287 					DUK_DDD(DUK_DDDPRINT("plain assignment, not toplevel assign, ensure not a reg-bound identifier"));
72288 					if (res->t != DUK_IVAL_PLAIN || (res->x1.t == DUK_ISPEC_REGCONST &&
72289 					                                 DUK__ISREG_NOTTEMP(comp_ctx, res->x1.regconst))) {
72290 						duk__ivalue_totempconst(comp_ctx, res);
72291 					}
72292 				}
72293 			} else {
72294 				/* For X <op>= Y we need to evaluate the pre-op
72295 				 * value of X before evaluating the RHS: the RHS
72296 				 * can change X, but when we do <op> we must use
72297 				 * the pre-op value.
72298 				 */
72299 				duk_regconst_t reg_temp;
72300 
72301 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
72302 
72303 				if (reg_varbind >= 0) {
72304 					duk_regconst_t reg_res;
72305 					duk_regconst_t reg_src;
72306 					duk_int_t pc_temp_load;
72307 					duk_int_t pc_before_rhs;
72308 					duk_int_t pc_after_rhs;
72309 
72310 					if (toplevel_assign) {
72311 						/* 'reg_varbind' is the operation result and can also
72312 						 * become the expression value for top level assignments
72313 						 * such as: "var x; x += y;".
72314 						 */
72315 						DUK_DD(DUK_DDPRINT("<op>= expression is top level, write directly to reg_varbind"));
72316 						reg_res = reg_varbind;
72317 					} else {
72318 						/* Not safe to use 'reg_varbind' as assignment expression
72319 						 * value, so go through a temp.
72320 						 */
72321 						DUK_DD(DUK_DDPRINT("<op>= expression is not top level, write to reg_temp"));
72322 						reg_res = reg_temp;  /* reg_res should be smallest possible */
72323 						reg_temp = DUK__ALLOCTEMP(comp_ctx);
72324 					}
72325 
72326 					/* Try to optimize X <op>= Y for reg-bound
72327 					 * variables.  Detect side-effect free RHS
72328 					 * narrowly by seeing whether it emits code.
72329 					 * If not, rewind the code emitter and overwrite
72330 					 * the unnecessary temp reg load.
72331 					 */
72332 
72333 					pc_temp_load = duk__get_current_pc(comp_ctx);
72334 					duk__emit_a_bc(comp_ctx,
72335 					               DUK_OP_LDREG,
72336 					               reg_temp,
72337 					               reg_varbind);
72338 
72339 					pc_before_rhs = duk__get_current_pc(comp_ctx);
72340 					duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
72341 					DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
72342 					pc_after_rhs = duk__get_current_pc(comp_ctx);
72343 
72344 					DUK_DD(DUK_DDPRINT("pc_temp_load=%ld, pc_before_rhs=%ld, pc_after_rhs=%ld",
72345 					                   (long) pc_temp_load, (long) pc_before_rhs,
72346 					                   (long) pc_after_rhs));
72347 
72348 					if (pc_after_rhs == pc_before_rhs) {
72349 						/* Note: if the reg_temp load generated shuffling
72350 						 * instructions, we may need to rewind more than
72351 						 * one instruction, so use explicit PC computation.
72352 						 */
72353 						DUK_DD(DUK_DDPRINT("rhs is side effect free, rewind and avoid unnecessary temp for reg-based <op>="));
72354 						DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, (pc_temp_load - pc_before_rhs) * (duk_int_t) sizeof(duk_compiler_instr));
72355 						reg_src = reg_varbind;
72356 					} else {
72357 						DUK_DD(DUK_DDPRINT("rhs evaluation emitted code, not sure if rhs is side effect free; use temp reg for LHS"));
72358 						reg_src = reg_temp;
72359 					}
72360 
72361 					duk__emit_a_b_c(comp_ctx,
72362 					                args_op | DUK__EMIT_FLAG_BC_REGCONST,
72363 					                reg_res,
72364 					                reg_src,
72365 					                res->x1.regconst);
72366 
72367 					res->x1.regconst = reg_res;
72368 
72369 					/* Ensure compact use of temps. */
72370 					if (DUK__ISREG_TEMP(comp_ctx, reg_res)) {
72371 						DUK__SETTEMP(comp_ctx, reg_res + 1);
72372 					}
72373 				} else {
72374 					/* When LHS is not register bound, always go through a
72375 					 * temporary.  No optimization for top level assignment.
72376 					 */
72377 
72378 					duk__emit_a_bc(comp_ctx,
72379 					               DUK_OP_GETVAR,
72380 					               reg_temp,
72381 					               rc_varname);
72382 
72383 					duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
72384 					DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
72385 
72386 					duk__emit_a_b_c(comp_ctx,
72387 					                args_op | DUK__EMIT_FLAG_BC_REGCONST,
72388 					                reg_temp,
72389 					                reg_temp,
72390 					                res->x1.regconst);
72391 					res->x1.regconst = reg_temp;
72392 				}
72393 
72394 				DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
72395 			}
72396 
72397 			/* At this point 'res' holds the potential expression value.
72398 			 * It can be basically any ivalue here, including a reg-bound
72399 			 * identifier (if code above deems it safe) or a unary/binary
72400 			 * operation.  Operations must be resolved to a side effect free
72401 			 * plain value, and the side effects must happen exactly once.
72402 			 */
72403 
72404 			if (reg_varbind >= 0) {
72405 				if (res->t != DUK_IVAL_PLAIN) {
72406 					/* Resolve 'res' directly into the LHS binding, and use
72407 					 * that as the expression value if safe.  If not safe,
72408 					 * resolve to a temp/const and copy to LHS.
72409 					 */
72410 					if (toplevel_assign) {
72411 						duk__ivalue_toforcedreg(comp_ctx, res, (duk_int_t) reg_varbind);
72412 					} else {
72413 						duk__ivalue_totempconst(comp_ctx, res);
72414 						duk__copy_ivalue(comp_ctx, res, left);  /* use 'left' as a temp */
72415 						duk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);
72416 					}
72417 				} else {
72418 					/* Use 'res' as the expression value (it's side effect
72419 					 * free and may be a plain value, a register, or a
72420 					 * constant) and write it to the LHS binding too.
72421 					 */
72422 					duk__copy_ivalue(comp_ctx, res, left);  /* use 'left' as a temp */
72423 					duk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);
72424 				}
72425 			} else {
72426 				/* Only a reg fits into 'A' so coerce 'res' into a register
72427 				 * for PUTVAR.
72428 				 *
72429 				 * XXX: here the current A/B/C split is suboptimal: we could
72430 				 * just use 9 bits for reg_res (and support constants) and 17
72431 				 * instead of 18 bits for the varname const index.
72432 				 */
72433 
72434 				duk__ivalue_toreg(comp_ctx, res);
72435 				duk__emit_a_bc(comp_ctx,
72436 				               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
72437 				               res->x1.regconst,
72438 				               rc_varname);
72439 			}
72440 
72441 			/* 'res' contains expression value */
72442 		} else if (left->t == DUK_IVAL_PROP) {
72443 			/* E5 Section 11.13.1 (and others) step 4 never matches for prop writes -> no check */
72444 			duk_regconst_t reg_obj;
72445 			duk_regconst_t rc_key;
72446 			duk_regconst_t rc_res;
72447 			duk_regconst_t reg_temp;
72448 
72449 			/* Property access expressions ('a[b]') are critical to correct
72450 			 * LHS evaluation ordering, see test-dev-assign-eval-order*.js.
72451 			 * We must make sure that the LHS target slot (base object and
72452 			 * key) don't change during RHS evaluation.  The only concrete
72453 			 * problem is a register reference to a variable-bound register
72454 			 * (i.e., non-temp).  Require temp regs for both key and base.
72455 			 *
72456 			 * Don't allow a constant for the object (even for a number
72457 			 * etc), as it goes into the 'A' field of the opcode.
72458 			 */
72459 
72460 			reg_obj = duk__ispec_toregconst_raw(comp_ctx,
72461 			                                    &left->x1,
72462 			                                    -1 /*forced_reg*/,
72463 			                                    DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
72464 
72465 			rc_key = duk__ispec_toregconst_raw(comp_ctx,
72466 			                                   &left->x2,
72467 			                                   -1 /*forced_reg*/,
72468 			                                   DUK__IVAL_FLAG_REQUIRE_TEMP | DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
72469 
72470 			/* Evaluate RHS only when LHS is safe. */
72471 
72472 			if (args_op == DUK_OP_NONE) {
72473 				duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
72474 				DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
72475 				rc_res = res->x1.regconst;
72476 			} else {
72477 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
72478 				duk__emit_a_b_c(comp_ctx,
72479 				                DUK_OP_GETPROP | DUK__EMIT_FLAG_BC_REGCONST,
72480 				                reg_temp,
72481 				                reg_obj,
72482 				                rc_key);
72483 
72484 				duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
72485 				DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
72486 
72487 				duk__emit_a_b_c(comp_ctx,
72488 				                args_op | DUK__EMIT_FLAG_BC_REGCONST,
72489 				                reg_temp,
72490 				                reg_temp,
72491 				                res->x1.regconst);
72492 				rc_res = reg_temp;
72493 			}
72494 
72495 			duk__emit_a_b_c(comp_ctx,
72496 			                DUK_OP_PUTPROP | DUK__EMIT_FLAG_A_IS_SOURCE | DUK__EMIT_FLAG_BC_REGCONST,
72497 			                reg_obj,
72498 			                rc_key,
72499 			                rc_res);
72500 
72501 			duk__ivalue_regconst(res, rc_res);
72502 		} else {
72503 			/* No support for lvalues returned from new or function call expressions.
72504 			 * However, these must NOT cause compile-time SyntaxErrors, but run-time
72505 			 * ReferenceErrors.  Both left and right sides of the assignment must be
72506 			 * evaluated before throwing a ReferenceError.  For instance:
72507 			 *
72508 			 *     f() = g();
72509 			 *
72510 			 * must result in f() being evaluated, then g() being evaluated, and
72511 			 * finally, a ReferenceError being thrown.  See E5 Section 11.13.1.
72512 			 */
72513 
72514 			duk_regconst_t rc_res;
72515 
72516 			/* First evaluate LHS fully to ensure all side effects are out. */
72517 			duk__ivalue_toplain_ignore(comp_ctx, left);
72518 
72519 			/* Then evaluate RHS fully (its value becomes the expression value too).
72520 			 * Technically we'd need the side effect safety check here too, but because
72521 			 * we always throw using INVLHS the result doesn't matter.
72522 			 */
72523 			rc_res = duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
72524 
72525 			duk__emit_op_only(comp_ctx, DUK_OP_INVLHS);
72526 
72527 			duk__ivalue_regconst(res, rc_res);
72528 		}
72529 
72530 		return;
72531 	}
72532 
72533  postincdec:
72534 	{
72535 		/*
72536 		 *  Post-increment/decrement will return the original value as its
72537 		 *  result value.  However, even that value will be coerced using
72538 		 *  ToNumber() which is quite awkward.  Specific bytecode opcodes
72539 		 *  are used to handle these semantics.
72540 		 *
72541 		 *  Note that post increment/decrement has a "no LineTerminator here"
72542 		 *  restriction.  This is handled by duk__expr_lbp(), which forcibly terminates
72543 		 *  the previous expression if a LineTerminator occurs before '++'/'--'.
72544 		 */
72545 
72546 		duk_regconst_t reg_res;
72547 		duk_small_uint_t args_op1 = (args >> 8) & 0xff;  /* DUK_OP_POSTINCR/DUK_OP_POSTDECR */
72548 		duk_small_uint_t args_op2 = args >> 16;          /* DUK_OP_POSTINCP_RR/DUK_OP_POSTDECP_RR */
72549 
72550 		/* Specific assumptions for opcode numbering. */
72551 		DUK_ASSERT(DUK_OP_POSTINCR + 4 == DUK_OP_POSTINCV);
72552 		DUK_ASSERT(DUK_OP_POSTDECR + 4 == DUK_OP_POSTDECV);
72553 
72554 		reg_res = DUK__ALLOCTEMP(comp_ctx);
72555 
72556 		if (left->t == DUK_IVAL_VAR) {
72557 			duk_hstring *h_varname;
72558 			duk_regconst_t reg_varbind;
72559 			duk_regconst_t rc_varname;
72560 
72561 			h_varname = duk_known_hstring(thr, left->x1.valstack_idx);
72562 
72563 			if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
72564 				goto syntax_error;
72565 			}
72566 
72567 			duk_dup(thr, left->x1.valstack_idx);
72568 			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
72569 				duk__emit_a_bc(comp_ctx,
72570 				               args_op1,  /* e.g. DUK_OP_POSTINCR */
72571 				               reg_res,
72572 				               reg_varbind);
72573 			} else {
72574 				duk__emit_a_bc(comp_ctx,
72575 				               args_op1 + 4,  /* e.g. DUK_OP_POSTINCV */
72576 				               reg_res,
72577 				               rc_varname);
72578 			}
72579 
72580 			DUK_DDD(DUK_DDDPRINT("postincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
72581 			                     (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
72582 		} else if (left->t == DUK_IVAL_PROP) {
72583 			duk_regconst_t reg_obj;  /* allocate to reg only (not const) */
72584 			duk_regconst_t rc_key;
72585 
72586 			reg_obj = duk__ispec_toregconst_raw(comp_ctx, &left->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
72587 			rc_key = duk__ispec_toregconst_raw(comp_ctx, &left->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
72588 			duk__emit_a_b_c(comp_ctx,
72589 			                args_op2 | DUK__EMIT_FLAG_BC_REGCONST,  /* e.g. DUK_OP_POSTINCP */
72590 			                reg_res,
72591 			                reg_obj,
72592 			                rc_key);
72593 		} else {
72594 			/* Technically return value is not needed because INVLHS will
72595 			 * unconditially throw a ReferenceError.  Coercion is necessary
72596 			 * for proper semantics (consider ToNumber() called for an object).
72597 			 * Use DUK_OP_UNP with a dummy register to get ToNumber().
72598 			 */
72599 			duk__ivalue_toforcedreg(comp_ctx, left, reg_res);
72600 			duk__emit_bc(comp_ctx,
72601 			             DUK_OP_UNP,
72602 			             reg_res);  /* for side effects, result ignored */
72603 			duk__emit_op_only(comp_ctx,
72604 			                  DUK_OP_INVLHS);
72605 		}
72606 
72607 		DUK__SETTEMP(comp_ctx, reg_res + 1);
72608 		duk__ivalue_regconst(res, reg_res);
72609 		return;
72610 	}
72611 
72612  syntax_error:
72613 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_EXPRESSION);
72614 	DUK_WO_NORETURN(return;);
72615 
72616  syntax_error_lvalue:
72617 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LVALUE);
72618 	DUK_WO_NORETURN(return;);
72619 }
72620 
72621 DUK_LOCAL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx) {
72622 	duk_small_uint_t tok = comp_ctx->curr_token.t;
72623 
72624 	DUK_ASSERT_DISABLE(tok >= DUK_TOK_MINVAL);  /* unsigned */
72625 	DUK_ASSERT(tok <= DUK_TOK_MAXVAL);
72626 	DUK_ASSERT(sizeof(duk__token_lbp) == DUK_TOK_MAXVAL + 1);
72627 
72628 	/* XXX: integrate support for this into led() instead?
72629 	 * Similar issue as post-increment/post-decrement.
72630 	 */
72631 
72632 	/* prevent duk__expr_led() by using a binding power less than anything valid */
72633 	if (tok == DUK_TOK_IN && !comp_ctx->curr_func.allow_in) {
72634 		return 0;
72635 	}
72636 
72637 	if ((tok == DUK_TOK_DECREMENT || tok == DUK_TOK_INCREMENT) &&
72638 	    (comp_ctx->curr_token.lineterm)) {
72639 		/* '++' or '--' in a post-increment/decrement position,
72640 		 * and a LineTerminator occurs between the operator and
72641 		 * the preceding expression.  Force the previous expr
72642 		 * to terminate, in effect treating e.g. "a,b\n++" as
72643 		 * "a,b;++" (= SyntaxError).
72644 		 */
72645 		return 0;
72646 	}
72647 
72648 	return DUK__TOKEN_LBP_GET_BP(duk__token_lbp[tok]);  /* format is bit packed */
72649 }
72650 
72651 /*
72652  *  Expression parsing.
72653  *
72654  *  Upon entry to 'expr' and its variants, 'curr_tok' is assumed to be the
72655  *  first token of the expression.  Upon exit, 'curr_tok' will be the first
72656  *  token not part of the expression (e.g. semicolon terminating an expression
72657  *  statement).
72658  */
72659 
72660 #define DUK__EXPR_RBP_MASK           0xff
72661 #define DUK__EXPR_FLAG_REJECT_IN     (1 << 8)   /* reject 'in' token (used for for-in) */
72662 #define DUK__EXPR_FLAG_ALLOW_EMPTY   (1 << 9)   /* allow empty expression */
72663 #define DUK__EXPR_FLAG_REQUIRE_INIT  (1 << 10)  /* require initializer for var/const */
72664 
72665 /* main expression parser function */
72666 DUK_LOCAL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
72667 	duk_hthread *thr = comp_ctx->thr;
72668 	duk_ivalue tmp_alloc;   /* 'res' is used for "left", and 'tmp' for "right" */
72669 	duk_ivalue *tmp = &tmp_alloc;
72670 	duk_small_uint_t rbp;
72671 
72672 	DUK__RECURSION_INCREASE(comp_ctx, thr);
72673 
72674 	duk_require_stack(thr, DUK__PARSE_EXPR_SLOTS);
72675 
72676 	/* filter out flags from exprtop rbp_flags here to save space */
72677 	rbp = rbp_flags & DUK__EXPR_RBP_MASK;
72678 
72679 	DUK_DDD(DUK_DDDPRINT("duk__expr(), rbp_flags=%ld, rbp=%ld, allow_in=%ld, paren_level=%ld",
72680 	                     (long) rbp_flags, (long) rbp, (long) comp_ctx->curr_func.allow_in,
72681 	                     (long) comp_ctx->curr_func.paren_level));
72682 
72683 	duk_memzero(&tmp_alloc, sizeof(tmp_alloc));
72684 	tmp->x1.valstack_idx = duk_get_top(thr);
72685 	tmp->x2.valstack_idx = tmp->x1.valstack_idx + 1;
72686 	duk_push_undefined(thr);
72687 	duk_push_undefined(thr);
72688 
72689 	/* XXX: where to release temp regs in intermediate expressions?
72690 	 * e.g. 1+2+3 -> don't inflate temp register count when parsing this.
72691 	 * that particular expression temp regs can be forced here.
72692 	 */
72693 
72694 	/* XXX: increase ctx->expr_tokens here for every consumed token
72695 	 * (this would be a nice statistic)?
72696 	 */
72697 
72698 	if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON || comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
72699 		/* XXX: possibly incorrect handling of empty expression */
72700 		DUK_DDD(DUK_DDDPRINT("empty expression"));
72701 		if (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY)) {
72702 			DUK_ERROR_SYNTAX(thr, DUK_STR_EMPTY_EXPR_NOT_ALLOWED);
72703 			DUK_WO_NORETURN(return;);
72704 		}
72705 		duk_push_undefined(thr);
72706 		duk__ivalue_plain_fromstack(comp_ctx, res);
72707 		goto cleanup;
72708 	}
72709 
72710 	duk__advance(comp_ctx);
72711 	duk__expr_nud(comp_ctx, res);  /* reuse 'res' as 'left' */
72712 	while (rbp < duk__expr_lbp(comp_ctx)) {
72713 		duk__advance(comp_ctx);
72714 		duk__expr_led(comp_ctx, res, tmp);
72715 		duk__copy_ivalue(comp_ctx, tmp, res);  /* tmp -> res */
72716 	}
72717 
72718  cleanup:
72719 	/* final result is already in 'res' */
72720 
72721 	duk_pop_2(thr);
72722 
72723 	DUK__RECURSION_DECREASE(comp_ctx, thr);
72724 }
72725 
72726 DUK_LOCAL void duk__exprtop(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
72727 	duk_hthread *thr = comp_ctx->thr;
72728 
72729 	/* Note: these variables must reside in 'curr_func' instead of the global
72730 	 * context: when parsing function expressions, expression parsing is nested.
72731 	 */
72732 	comp_ctx->curr_func.nud_count = 0;
72733 	comp_ctx->curr_func.led_count = 0;
72734 	comp_ctx->curr_func.paren_level = 0;
72735 	comp_ctx->curr_func.expr_lhs = 1;
72736 	comp_ctx->curr_func.allow_in = (rbp_flags & DUK__EXPR_FLAG_REJECT_IN ? 0 : 1);
72737 
72738 	duk__expr(comp_ctx, res, rbp_flags);
72739 
72740 	if (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY) && duk__expr_is_empty(comp_ctx)) {
72741 		DUK_ERROR_SYNTAX(thr, DUK_STR_EMPTY_EXPR_NOT_ALLOWED);
72742 		DUK_WO_NORETURN(return;);
72743 	}
72744 }
72745 
72746 /* A bunch of helpers (for size optimization) that combine duk__expr()/duk__exprtop()
72747  * and result conversions.
72748  *
72749  * Each helper needs at least 2-3 calls to make it worth while to wrap.
72750  */
72751 
72752 #if 0  /* unused */
72753 DUK_LOCAL duk_regconst_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
72754 	duk__expr(comp_ctx, res, rbp_flags);
72755 	return duk__ivalue_toreg(comp_ctx, res);
72756 }
72757 #endif
72758 
72759 #if 0  /* unused */
72760 DUK_LOCAL duk_regconst_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
72761 	duk__expr(comp_ctx, res, rbp_flags);
72762 	return duk__ivalue_totemp(comp_ctx, res);
72763 }
72764 #endif
72765 
72766 DUK_LOCAL void duk__expr_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_regconst_t forced_reg) {
72767 	DUK_ASSERT(forced_reg >= 0);
72768 	duk__expr(comp_ctx, res, rbp_flags);
72769 	duk__ivalue_toforcedreg(comp_ctx, res, forced_reg);
72770 }
72771 
72772 DUK_LOCAL duk_regconst_t duk__expr_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
72773 	duk__expr(comp_ctx, res, rbp_flags);
72774 	return duk__ivalue_toregconst(comp_ctx, res);
72775 }
72776 
72777 #if 0  /* unused */
72778 DUK_LOCAL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
72779 	duk__expr(comp_ctx, res, rbp_flags);
72780 	return duk__ivalue_totempconst(comp_ctx, res);
72781 }
72782 #endif
72783 
72784 DUK_LOCAL void duk__expr_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
72785 	duk__expr(comp_ctx, res, rbp_flags);
72786 	duk__ivalue_toplain(comp_ctx, res);
72787 }
72788 
72789 DUK_LOCAL void duk__expr_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
72790 	duk__expr(comp_ctx, res, rbp_flags);
72791 	duk__ivalue_toplain_ignore(comp_ctx, res);
72792 }
72793 
72794 DUK_LOCAL duk_regconst_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
72795 	duk__exprtop(comp_ctx, res, rbp_flags);
72796 	return duk__ivalue_toreg(comp_ctx, res);
72797 }
72798 
72799 #if 0  /* unused */
72800 DUK_LOCAL duk_regconst_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
72801 	duk__exprtop(comp_ctx, res, rbp_flags);
72802 	return duk__ivalue_totemp(comp_ctx, res);
72803 }
72804 #endif
72805 
72806 DUK_LOCAL void duk__exprtop_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_regconst_t forced_reg) {
72807 	DUK_ASSERT(forced_reg >= 0);
72808 	duk__exprtop(comp_ctx, res, rbp_flags);
72809 	duk__ivalue_toforcedreg(comp_ctx, res, forced_reg);
72810 }
72811 
72812 DUK_LOCAL duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
72813 	duk__exprtop(comp_ctx, res, rbp_flags);
72814 	return duk__ivalue_toregconst(comp_ctx, res);
72815 }
72816 
72817 #if 0  /* unused */
72818 DUK_LOCAL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, int rbp_flags) {
72819 	duk__exprtop(comp_ctx, res, rbp_flags);
72820 	duk__ivalue_toplain_ignore(comp_ctx, res);
72821 }
72822 #endif
72823 
72824 /*
72825  *  Parse an individual source element (top level statement) or a statement.
72826  *
72827  *  Handles labeled statements automatically (peeling away labels before
72828  *  parsing an expression that follows the label(s)).
72829  *
72830  *  Upon entry, 'curr_tok' contains the first token of the statement (parsed
72831  *  in "allow regexp literal" mode).  Upon exit, 'curr_tok' contains the first
72832  *  token following the statement (if the statement has a terminator, this is
72833  *  the token after the terminator).
72834  */
72835 
72836 #define DUK__HAS_VAL                  (1 << 0)  /* stmt has non-empty value */
72837 #define DUK__HAS_TERM                 (1 << 1)  /* stmt has explicit/implicit semicolon terminator */
72838 #define DUK__ALLOW_AUTO_SEMI_ALWAYS   (1 << 2)  /* allow automatic semicolon even without lineterm (compatibility) */
72839 #define DUK__STILL_PROLOGUE           (1 << 3)  /* statement does not terminate directive prologue */
72840 #define DUK__IS_TERMINAL              (1 << 4)  /* statement is guaranteed to be terminal (control doesn't flow to next statement) */
72841 
72842 /* Parse a single variable declaration (e.g. "i" or "i=10").  A leading 'var'
72843  * has already been eaten.  These is no return value in 'res', it is used only
72844  * as a temporary.
72845  *
72846  * When called from 'for-in' statement parser, the initializer expression must
72847  * not allow the 'in' token.  The caller supply additional expression parsing
72848  * flags (like DUK__EXPR_FLAG_REJECT_IN) in 'expr_flags'.
72849  *
72850  * Finally, out_rc_varname and out_reg_varbind are updated to reflect where
72851  * the identifier is bound:
72852  *
72853  *    If register bound:      out_reg_varbind >= 0, out_rc_varname == 0 (ignore)
72854  *    If not register bound:  out_reg_varbind < 0, out_rc_varname >= 0
72855  *
72856  * These allow the caller to use the variable for further assignment, e.g.
72857  * as is done in 'for-in' parsing.
72858  */
72859 
72860 DUK_LOCAL void duk__parse_var_decl(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags, duk_regconst_t *out_reg_varbind, duk_regconst_t *out_rc_varname) {
72861 	duk_hthread *thr = comp_ctx->thr;
72862 	duk_hstring *h_varname;
72863 	duk_regconst_t reg_varbind;
72864 	duk_regconst_t rc_varname;
72865 
72866 	/* assume 'var' has been eaten */
72867 
72868 	/* Note: Identifier rejects reserved words */
72869 	if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
72870 		goto syntax_error;
72871 	}
72872 	h_varname = comp_ctx->curr_token.str1;
72873 
72874 	DUK_ASSERT(h_varname != NULL);
72875 
72876 	/* strict mode restrictions (E5 Section 12.2.1) */
72877 	if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
72878 		goto syntax_error;
72879 	}
72880 
72881 	/* register declarations in first pass */
72882 	if (comp_ctx->curr_func.in_scanning) {
72883 		duk_uarridx_t n;
72884 		DUK_DDD(DUK_DDDPRINT("register variable declaration %!O in pass 1",
72885 		                     (duk_heaphdr *) h_varname));
72886 		n = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.decls_idx);
72887 		duk_push_hstring(thr, h_varname);
72888 		duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n);
72889 		duk_push_int(thr, DUK_DECL_TYPE_VAR + (0 << 8));
72890 		duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n + 1);
72891 	}
72892 
72893 	duk_push_hstring(thr, h_varname);  /* push before advancing to keep reachable */
72894 
72895 	/* register binding lookup is based on varmap (even in first pass) */
72896 	duk_dup_top(thr);
72897 	(void) duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname);
72898 
72899 	duk__advance(comp_ctx);  /* eat identifier */
72900 
72901 	if (comp_ctx->curr_token.t == DUK_TOK_EQUALSIGN) {
72902 		duk__advance(comp_ctx);
72903 
72904 		DUK_DDD(DUK_DDDPRINT("vardecl, assign to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
72905 		                     (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
72906 
72907 		duk__exprtop(comp_ctx, res, DUK__BP_COMMA | expr_flags /*rbp_flags*/);  /* AssignmentExpression */
72908 
72909 		if (reg_varbind >= 0) {
72910 			duk__ivalue_toforcedreg(comp_ctx, res, reg_varbind);
72911 		} else {
72912 			duk_regconst_t reg_val;
72913 			reg_val = duk__ivalue_toreg(comp_ctx, res);
72914 			duk__emit_a_bc(comp_ctx,
72915 			               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
72916 			               reg_val,
72917 			               rc_varname);
72918 		}
72919 	} else {
72920 		if (expr_flags & DUK__EXPR_FLAG_REQUIRE_INIT) {
72921 			/* Used for minimal 'const': initializer required. */
72922 			goto syntax_error;
72923 		}
72924 	}
72925 
72926 	duk_pop(thr);  /* pop varname */
72927 
72928 	*out_rc_varname = rc_varname;
72929 	*out_reg_varbind = reg_varbind;
72930 
72931 	return;
72932 
72933  syntax_error:
72934 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_VAR_DECLARATION);
72935 	DUK_WO_NORETURN(return;);
72936 }
72937 
72938 DUK_LOCAL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags) {
72939 	duk_regconst_t reg_varbind;
72940 	duk_regconst_t rc_varname;
72941 
72942 	duk__advance(comp_ctx);  /* eat 'var' */
72943 
72944 	for (;;) {
72945 		/* rc_varname and reg_varbind are ignored here */
72946 		duk__parse_var_decl(comp_ctx, res, 0 | expr_flags, &reg_varbind, &rc_varname);
72947 
72948 		if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
72949 			break;
72950 		}
72951 		duk__advance(comp_ctx);
72952 	}
72953 }
72954 
72955 DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
72956 	duk_hthread *thr = comp_ctx->thr;
72957 	duk_int_t pc_v34_lhs;         /* start variant 3/4 left-hand-side code (L1 in doc/compiler.rst example) */
72958 	duk_regconst_t temp_reset;    /* knock back "next temp" to this whenever possible */
72959 	duk_regconst_t reg_temps;     /* preallocated temporaries (2) for variants 3 and 4 */
72960 
72961 	DUK_DDD(DUK_DDDPRINT("start parsing a for/for-in statement"));
72962 
72963 	/* Two temporaries are preallocated here for variants 3 and 4 which need
72964 	 * registers which are never clobbered by expressions in the loop
72965 	 * (concretely: for the enumerator object and the next enumerated value).
72966 	 * Variants 1 and 2 "release" these temps.
72967 	 */
72968 
72969 	reg_temps = DUK__ALLOCTEMPS(comp_ctx, 2);
72970 
72971 	temp_reset = DUK__GETTEMP(comp_ctx);
72972 
72973 	/*
72974 	 *  For/for-in main variants are:
72975 	 *
72976 	 *    1. for (ExpressionNoIn_opt; Expression_opt; Expression_opt) Statement
72977 	 *    2. for (var VariableDeclarationNoIn; Expression_opt; Expression_opt) Statement
72978 	 *    3. for (LeftHandSideExpression in Expression) Statement
72979 	 *    4. for (var VariableDeclarationNoIn in Expression) Statement
72980 	 *
72981 	 *  Parsing these without arbitrary lookahead or backtracking is relatively
72982 	 *  tricky but we manage to do so for now.
72983 	 *
72984 	 *  See doc/compiler.rst for a detailed discussion of control flow
72985 	 *  issues, evaluation order issues, etc.
72986 	 */
72987 
72988 	duk__advance(comp_ctx);  /* eat 'for' */
72989 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
72990 
72991 	DUK_DDD(DUK_DDDPRINT("detecting for/for-in loop variant, pc=%ld", (long) duk__get_current_pc(comp_ctx)));
72992 
72993 	/* a label site has been emitted by duk__parse_stmt() automatically
72994 	 * (it will also emit the ENDLABEL).
72995 	 */
72996 
72997 	if (comp_ctx->curr_token.t == DUK_TOK_VAR) {
72998 		/*
72999 		 *  Variant 2 or 4
73000 		 */
73001 
73002 		duk_regconst_t reg_varbind;  /* variable binding register if register-bound (otherwise < 0) */
73003 		duk_regconst_t rc_varname;   /* variable name reg/const, if variable not register-bound */
73004 
73005 		duk__advance(comp_ctx);  /* eat 'var' */
73006 		duk__parse_var_decl(comp_ctx, res, DUK__EXPR_FLAG_REJECT_IN, &reg_varbind, &rc_varname);
73007 		DUK__SETTEMP(comp_ctx, temp_reset);
73008 
73009 		if (comp_ctx->curr_token.t == DUK_TOK_IN) {
73010 			/*
73011 			 *  Variant 4
73012 			 */
73013 
73014 			DUK_DDD(DUK_DDDPRINT("detected for variant 4: for (var VariableDeclarationNoIn in Expression) Statement"));
73015 			pc_v34_lhs = duk__get_current_pc(comp_ctx);  /* jump is inserted here */
73016 			if (reg_varbind >= 0) {
73017 				duk__emit_a_bc(comp_ctx,
73018 				               DUK_OP_LDREG,
73019 				               reg_varbind,
73020 				               reg_temps + 0);
73021 			} else {
73022 				duk__emit_a_bc(comp_ctx,
73023 				               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
73024 				               reg_temps + 0,
73025 				               rc_varname);
73026 			}
73027 			goto parse_3_or_4;
73028 		} else {
73029 			/*
73030 			 *  Variant 2
73031 			 */
73032 
73033 			DUK_DDD(DUK_DDDPRINT("detected for variant 2: for (var VariableDeclarationNoIn; Expression_opt; Expression_opt) Statement"));
73034 			for (;;) {
73035 				/* more initializers */
73036 				if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
73037 					break;
73038 				}
73039 				DUK_DDD(DUK_DDDPRINT("variant 2 has another variable initializer"));
73040 
73041 				duk__advance(comp_ctx);  /* eat comma */
73042 				duk__parse_var_decl(comp_ctx, res, DUK__EXPR_FLAG_REJECT_IN, &reg_varbind, &rc_varname);
73043 			}
73044 			goto parse_1_or_2;
73045 		}
73046 	} else {
73047 		/*
73048 		 *  Variant 1 or 3
73049 		 */
73050 
73051 		pc_v34_lhs = duk__get_current_pc(comp_ctx);  /* jump is inserted here (variant 3) */
73052 
73053 		/* Note that duk__exprtop() here can clobber any reg above current temp_next,
73054 		 * so any loop variables (e.g. enumerator) must be "preallocated".
73055 		 */
73056 
73057 		/* don't coerce yet to a plain value (variant 3 needs special handling) */
73058 		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_REJECT_IN | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/);  /* Expression */
73059 		if (comp_ctx->curr_token.t == DUK_TOK_IN) {
73060 			/*
73061 			 *  Variant 3
73062 			 */
73063 
73064 			/* XXX: need to determine LHS type, and check that it is LHS compatible */
73065 			DUK_DDD(DUK_DDDPRINT("detected for variant 3: for (LeftHandSideExpression in Expression) Statement"));
73066 			if (duk__expr_is_empty(comp_ctx)) {
73067 				goto syntax_error;  /* LeftHandSideExpression does not allow empty expression */
73068 			}
73069 
73070 			if (res->t == DUK_IVAL_VAR) {
73071 				duk_regconst_t reg_varbind;
73072 				duk_regconst_t rc_varname;
73073 
73074 				duk_dup(thr, res->x1.valstack_idx);
73075 				if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
73076 					duk__emit_a_bc(comp_ctx,
73077 					               DUK_OP_LDREG,
73078 					               reg_varbind,
73079 					               reg_temps + 0);
73080 				} else {
73081 					duk__emit_a_bc(comp_ctx,
73082 					               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
73083 					               reg_temps + 0,
73084 					               rc_varname);
73085 				}
73086 			} else if (res->t == DUK_IVAL_PROP) {
73087 				/* Don't allow a constant for the object (even for a number etc), as
73088 				 * it goes into the 'A' field of the opcode.
73089 				 */
73090 				duk_regconst_t reg_obj;
73091 				duk_regconst_t rc_key;
73092 				reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
73093 				rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
73094 				duk__emit_a_b_c(comp_ctx,
73095 				                DUK_OP_PUTPROP | DUK__EMIT_FLAG_A_IS_SOURCE | DUK__EMIT_FLAG_BC_REGCONST,
73096 				                reg_obj,
73097 				                rc_key,
73098 				                reg_temps + 0);
73099 			} else {
73100 				duk__ivalue_toplain_ignore(comp_ctx, res);  /* just in case */
73101 				duk__emit_op_only(comp_ctx,
73102 				                  DUK_OP_INVLHS);
73103 			}
73104 			goto parse_3_or_4;
73105 		} else {
73106 			/*
73107 			 *  Variant 1
73108 			 */
73109 
73110 			DUK_DDD(DUK_DDDPRINT("detected for variant 1: for (ExpressionNoIn_opt; Expression_opt; Expression_opt) Statement"));
73111 			duk__ivalue_toplain_ignore(comp_ctx, res);
73112 			goto parse_1_or_2;
73113 		}
73114 	}
73115 
73116  parse_1_or_2:
73117 	/*
73118 	 *  Parse variant 1 or 2.  The first part expression (which differs
73119 	 *  in the variants) has already been parsed and its code emitted.
73120 	 *
73121 	 *  reg_temps + 0: unused
73122 	 *  reg_temps + 1: unused
73123 	 */
73124 	{
73125 		duk_regconst_t rc_cond;
73126 		duk_int_t pc_l1, pc_l2, pc_l3, pc_l4;
73127 		duk_int_t pc_jumpto_l3, pc_jumpto_l4;
73128 		duk_bool_t expr_c_empty;
73129 
73130 		DUK_DDD(DUK_DDDPRINT("shared code for parsing variants 1 and 2"));
73131 
73132 		/* "release" preallocated temps since we won't need them */
73133 		temp_reset = reg_temps + 0;
73134 		DUK__SETTEMP(comp_ctx, temp_reset);
73135 
73136 		duk__advance_expect(comp_ctx, DUK_TOK_SEMICOLON);
73137 
73138 		pc_l1 = duk__get_current_pc(comp_ctx);
73139 		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/);  /* Expression_opt */
73140 		if (duk__expr_is_empty(comp_ctx)) {
73141 			/* no need to coerce */
73142 			pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx);  /* to body */
73143 			pc_jumpto_l4 = -1;  /* omitted */
73144 		} else {
73145 			rc_cond = duk__ivalue_toregconst(comp_ctx, res);
73146 			duk__emit_if_false_skip(comp_ctx, rc_cond);
73147 			pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx);  /* to body */
73148 			pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx);  /* to exit */
73149 		}
73150 		DUK__SETTEMP(comp_ctx, temp_reset);
73151 
73152 		duk__advance_expect(comp_ctx, DUK_TOK_SEMICOLON);
73153 
73154 		pc_l2 = duk__get_current_pc(comp_ctx);
73155 		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/);  /* Expression_opt */
73156 		if (duk__expr_is_empty(comp_ctx)) {
73157 			/* no need to coerce */
73158 			expr_c_empty = 1;
73159 			/* JUMP L1 omitted */
73160 		} else {
73161 			duk__ivalue_toplain_ignore(comp_ctx, res);
73162 			expr_c_empty = 0;
73163 			duk__emit_jump(comp_ctx, pc_l1);
73164 		}
73165 		DUK__SETTEMP(comp_ctx, temp_reset);
73166 
73167 		comp_ctx->curr_func.allow_regexp_in_adv = 1;
73168 		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */
73169 
73170 		pc_l3 = duk__get_current_pc(comp_ctx);
73171 		duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
73172 		if (expr_c_empty) {
73173 			duk__emit_jump(comp_ctx, pc_l1);
73174 		} else {
73175 			duk__emit_jump(comp_ctx, pc_l2);
73176 		}
73177 		/* temp reset is not necessary after duk__parse_stmt(), which already does it */
73178 
73179 		pc_l4 = duk__get_current_pc(comp_ctx);
73180 
73181 		DUK_DDD(DUK_DDDPRINT("patching jumps: jumpto_l3: %ld->%ld, jumpto_l4: %ld->%ld, "
73182 		                     "break: %ld->%ld, continue: %ld->%ld",
73183 			             (long) pc_jumpto_l3, (long) pc_l3, (long) pc_jumpto_l4, (long) pc_l4,
73184 		                     (long) (pc_label_site + 1), (long) pc_l4, (long) (pc_label_site + 2), (long) pc_l2));
73185 
73186 		duk__patch_jump(comp_ctx, pc_jumpto_l3, pc_l3);
73187 		duk__patch_jump(comp_ctx, pc_jumpto_l4, pc_l4);
73188 		duk__patch_jump(comp_ctx,
73189 		                pc_label_site + 1,
73190 		                pc_l4);                         /* break jump */
73191 		duk__patch_jump(comp_ctx,
73192 		                pc_label_site + 2,
73193 		                expr_c_empty ? pc_l1 : pc_l2);  /* continue jump */
73194 	}
73195 	goto finished;
73196 
73197  parse_3_or_4:
73198 	/*
73199 	 *  Parse variant 3 or 4.
73200 	 *
73201 	 *  For variant 3 (e.g. "for (A in C) D;") the code for A (except the
73202 	 *  final property/variable write) has already been emitted.  The first
73203 	 *  instruction of that code is at pc_v34_lhs; a JUMP needs to be inserted
73204 	 *  there to satisfy control flow needs.
73205 	 *
73206 	 *  For variant 4, if the variable declaration had an initializer
73207 	 *  (e.g. "for (var A = B in C) D;") the code for the assignment
73208 	 *  (B) has already been emitted.
73209 	 *
73210 	 *  Variables set before entering here:
73211 	 *
73212 	 *    pc_v34_lhs:    insert a "JUMP L2" here (see doc/compiler.rst example).
73213 	 *    reg_temps + 0: iteration target value (written to LHS)
73214 	 *    reg_temps + 1: enumerator object
73215 	 */
73216 	{
73217 		duk_int_t pc_l1, pc_l2, pc_l3, pc_l4, pc_l5;
73218 		duk_int_t pc_jumpto_l2, pc_jumpto_l3, pc_jumpto_l4, pc_jumpto_l5;
73219 		duk_regconst_t reg_target;
73220 
73221 		DUK_DDD(DUK_DDDPRINT("shared code for parsing variants 3 and 4, pc_v34_lhs=%ld", (long) pc_v34_lhs));
73222 
73223 		DUK__SETTEMP(comp_ctx, temp_reset);
73224 
73225 		/* First we need to insert a jump in the middle of previously
73226 		 * emitted code to get the control flow right.  No jumps can
73227 		 * cross the position where the jump is inserted.  See doc/compiler.rst
73228 		 * for discussion on the intricacies of control flow and side effects
73229 		 * for variants 3 and 4.
73230 		 */
73231 
73232 		duk__insert_jump_entry(comp_ctx, pc_v34_lhs);
73233 		pc_jumpto_l2 = pc_v34_lhs;  /* inserted jump */
73234 		pc_l1 = pc_v34_lhs + 1;     /* +1, right after inserted jump */
73235 
73236 		/* The code for writing reg_temps + 0 to the left hand side has already
73237 		 * been emitted.
73238 		 */
73239 
73240 		pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx);  /* -> loop body */
73241 
73242 		duk__advance(comp_ctx);  /* eat 'in' */
73243 
73244 		/* Parse enumeration target and initialize enumerator.  For 'null' and 'undefined',
73245 		 * INITENUM will creates a 'null' enumerator which works like an empty enumerator
73246 		 * (E5 Section 12.6.4, step 3).  Note that INITENUM requires the value to be in a
73247 		 * register (constant not allowed).
73248 		 */
73249 
73250 		pc_l2 = duk__get_current_pc(comp_ctx);
73251 		reg_target = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);  /* Expression */
73252 		duk__emit_b_c(comp_ctx,
73253 		              DUK_OP_INITENUM | DUK__EMIT_FLAG_B_IS_TARGET,
73254 		              reg_temps + 1,
73255 		              reg_target);
73256 		pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx);
73257 		DUK__SETTEMP(comp_ctx, temp_reset);
73258 
73259 		comp_ctx->curr_func.allow_regexp_in_adv = 1;
73260 		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */
73261 
73262 		pc_l3 = duk__get_current_pc(comp_ctx);
73263 		duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
73264 		/* temp reset is not necessary after duk__parse_stmt(), which already does it */
73265 
73266 		/* NEXTENUM needs a jump slot right after the main opcode.
73267 		 * We need the code emitter to reserve the slot: if there's
73268 		 * target shuffling, the target shuffle opcodes must happen
73269 		 * after the jump slot (for NEXTENUM the shuffle opcodes are
73270 		 * not needed if the enum is finished).
73271 		 */
73272 		pc_l4 = duk__get_current_pc(comp_ctx);
73273 		duk__emit_b_c(comp_ctx,
73274 		              DUK_OP_NEXTENUM | DUK__EMIT_FLAG_B_IS_TARGET | DUK__EMIT_FLAG_RESERVE_JUMPSLOT,
73275 		              reg_temps + 0,
73276 		              reg_temps + 1);
73277 		pc_jumpto_l5 = comp_ctx->emit_jumpslot_pc;  /* NEXTENUM jump slot: executed when enum finished */
73278 		duk__emit_jump(comp_ctx, pc_l1);  /* jump to next loop, using reg_v34_iter as iterated value */
73279 
73280 		pc_l5 = duk__get_current_pc(comp_ctx);
73281 
73282 		/* XXX: since the enumerator may be a memory expensive object,
73283 		 * perhaps clear it explicitly here?  If so, break jump must
73284 		 * go through this clearing operation.
73285 		 */
73286 
73287 		DUK_DDD(DUK_DDDPRINT("patching jumps: jumpto_l2: %ld->%ld, jumpto_l3: %ld->%ld, "
73288 		                     "jumpto_l4: %ld->%ld, jumpto_l5: %ld->%ld, "
73289 		                     "break: %ld->%ld, continue: %ld->%ld",
73290 			             (long) pc_jumpto_l2, (long) pc_l2, (long) pc_jumpto_l3, (long) pc_l3,
73291 			             (long) pc_jumpto_l4, (long) pc_l4, (long) pc_jumpto_l5, (long) pc_l5,
73292 		                     (long) (pc_label_site + 1), (long) pc_l5, (long) (pc_label_site + 2), (long) pc_l4));
73293 
73294 		duk__patch_jump(comp_ctx, pc_jumpto_l2, pc_l2);
73295 		duk__patch_jump(comp_ctx, pc_jumpto_l3, pc_l3);
73296 		duk__patch_jump(comp_ctx, pc_jumpto_l4, pc_l4);
73297 		duk__patch_jump(comp_ctx, pc_jumpto_l5, pc_l5);
73298 		duk__patch_jump(comp_ctx, pc_label_site + 1, pc_l5);  /* break jump */
73299 		duk__patch_jump(comp_ctx, pc_label_site + 2, pc_l4);  /* continue jump */
73300 	}
73301 	goto finished;
73302 
73303  finished:
73304 	DUK_DDD(DUK_DDDPRINT("end parsing a for/for-in statement"));
73305 	return;
73306 
73307  syntax_error:
73308 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_FOR);
73309 	DUK_WO_NORETURN(return;);
73310 }
73311 
73312 DUK_LOCAL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
73313 	duk_hthread *thr = comp_ctx->thr;
73314 	duk_regconst_t temp_at_loop;
73315 	duk_regconst_t rc_switch;    /* reg/const for switch value */
73316 	duk_regconst_t rc_case;      /* reg/const for case value */
73317 	duk_regconst_t reg_temp;     /* general temp register */
73318 	duk_int_t pc_prevcase = -1;
73319 	duk_int_t pc_prevstmt = -1;
73320 	duk_int_t pc_default = -1;   /* -1 == not set, -2 == pending (next statement list) */
73321 
73322 	/* Note: negative pc values are ignored when patching jumps, so no explicit checks needed */
73323 
73324 	/*
73325 	 *  Switch is pretty complicated because of several conflicting concerns:
73326 	 *
73327 	 *    - Want to generate code without an intermediate representation,
73328 	 *      i.e., in one go
73329 	 *
73330 	 *    - Case selectors are expressions, not values, and may thus e.g. throw
73331 	 *      exceptions (which causes evaluation order concerns)
73332 	 *
73333 	 *    - Evaluation semantics of case selectors and default clause need to be
73334 	 *      carefully implemented to provide correct behavior even with case value
73335 	 *      side effects
73336 	 *
73337 	 *    - Fall through case and default clauses; avoiding dead JUMPs if case
73338 	 *      ends with an unconditional jump (a break or a continue)
73339 	 *
73340 	 *    - The same case value may occur multiple times, but evaluation rules
73341 	 *      only process the first match before switching to a "propagation" mode
73342 	 *      where case values are no longer evaluated
73343 	 *
73344 	 *  See E5 Section 12.11.  Also see doc/compiler.rst for compilation
73345 	 *  discussion.
73346 	 */
73347 
73348 	duk__advance(comp_ctx);
73349 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
73350 	rc_switch = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
73351 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* RegExp mode does not matter. */
73352 	duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
73353 
73354 	DUK_DDD(DUK_DDDPRINT("switch value in register %ld", (long) rc_switch));
73355 
73356 	temp_at_loop = DUK__GETTEMP(comp_ctx);
73357 
73358 	for (;;) {
73359 		duk_int_t num_stmts;
73360 		duk_small_uint_t tok;
73361 
73362 		/* sufficient for keeping temp reg numbers in check */
73363 		DUK__SETTEMP(comp_ctx, temp_at_loop);
73364 
73365 		if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
73366 			break;
73367 		}
73368 
73369 		/*
73370 		 *  Parse a case or default clause.
73371 		 */
73372 
73373 		if (comp_ctx->curr_token.t == DUK_TOK_CASE) {
73374 			/*
73375 			 *  Case clause.
73376 			 *
73377 			 *  Note: cannot use reg_case as a temp register (for SEQ target)
73378 			 *  because it may be a constant.
73379 			 */
73380 
73381 			duk__patch_jump_here(comp_ctx, pc_prevcase);  /* chain jumps for case
73382 			                                               * evaluation and checking
73383 			                                               */
73384 
73385 			duk__advance(comp_ctx);
73386 			rc_case = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
73387 			duk__advance_expect(comp_ctx, DUK_TOK_COLON);
73388 
73389 			reg_temp = DUK__ALLOCTEMP(comp_ctx);
73390 			duk__emit_a_b_c(comp_ctx,
73391 			                DUK_OP_SEQ | DUK__EMIT_FLAG_BC_REGCONST,
73392 			                reg_temp,
73393 			                rc_switch,
73394 			                rc_case);
73395 			duk__emit_if_true_skip(comp_ctx, reg_temp);
73396 
73397 			/* jump to next case clause */
73398 			pc_prevcase = duk__emit_jump_empty(comp_ctx);  /* no match, next case */
73399 
73400 			/* statements go here (if any) on next loop */
73401 		} else if (comp_ctx->curr_token.t == DUK_TOK_DEFAULT) {
73402 			/*
73403 			 *  Default clause.
73404 			 */
73405 
73406 			if (pc_default >= 0) {
73407 				goto syntax_error;
73408 			}
73409 			duk__advance(comp_ctx);
73410 			duk__advance_expect(comp_ctx, DUK_TOK_COLON);
73411 
73412 			/* Fix for https://github.com/svaarala/duktape/issues/155:
73413 			 * If 'default' is first clause (detected by pc_prevcase < 0)
73414 			 * we need to ensure we stay in the matching chain.
73415 			 */
73416 			if (pc_prevcase < 0) {
73417 				DUK_DD(DUK_DDPRINT("default clause is first, emit prevcase jump"));
73418 				pc_prevcase = duk__emit_jump_empty(comp_ctx);
73419 			}
73420 
73421 			/* default clause matches next statement list (if any) */
73422 			pc_default = -2;
73423 		} else {
73424 			/* Code is not accepted before the first case/default clause */
73425 			goto syntax_error;
73426 		}
73427 
73428 		/*
73429 		 *  Parse code after the clause.  Possible terminators are
73430 		 *  'case', 'default', and '}'.
73431 		 *
73432 		 *  Note that there may be no code at all, not even an empty statement,
73433 		 *  between case clauses.  This must be handled just like an empty statement
73434 		 *  (omitting seemingly pointless JUMPs), to avoid situations like
73435 		 *  test-bug-case-fallthrough.js.
73436 		 */
73437 
73438 		num_stmts = 0;
73439 		if (pc_default == -2) {
73440 			pc_default = duk__get_current_pc(comp_ctx);
73441 		}
73442 
73443 		/* Note: this is correct even for default clause statements:
73444 		 * they participate in 'fall-through' behavior even if the
73445 		 * default clause is in the middle.
73446 		 */
73447 		duk__patch_jump_here(comp_ctx, pc_prevstmt);  /* chain jumps for 'fall-through'
73448 		                                               * after a case matches.
73449 		                                               */
73450 
73451 		for (;;) {
73452 			tok = comp_ctx->curr_token.t;
73453 			if (tok == DUK_TOK_CASE || tok == DUK_TOK_DEFAULT ||
73454 			    tok == DUK_TOK_RCURLY) {
73455 				break;
73456 			}
73457 			num_stmts++;
73458 			duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
73459 		}
73460 
73461 		/* fall-through jump to next code of next case (backpatched) */
73462 		pc_prevstmt = duk__emit_jump_empty(comp_ctx);
73463 
73464 		/* XXX: would be nice to omit this jump when the jump is not
73465 		 * reachable, at least in the obvious cases (such as the case
73466 		 * ending with a 'break'.
73467 		 *
73468 		 * Perhaps duk__parse_stmt() could provide some info on whether
73469 		 * the statement is a "dead end"?
73470 		 *
73471 		 * If implemented, just set pc_prevstmt to -1 when not needed.
73472 		 */
73473 	}
73474 
73475 	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);
73476 	comp_ctx->curr_func.allow_regexp_in_adv = 1;
73477 	duk__advance(comp_ctx);  /* Allow RegExp as part of next stmt. */
73478 
73479 	/* default case control flow patchup; note that if pc_prevcase < 0
73480 	 * (i.e. no case clauses), control enters default case automatically.
73481 	 */
73482 	if (pc_default >= 0) {
73483 		/* default case exists: go there if no case matches */
73484 		duk__patch_jump(comp_ctx, pc_prevcase, pc_default);
73485 	} else {
73486 		/* default case does not exist, or no statements present
73487 		 * after default case: finish case evaluation
73488 		 */
73489 		duk__patch_jump_here(comp_ctx, pc_prevcase);
73490 	}
73491 
73492 	/* fall-through control flow patchup; note that pc_prevstmt may be
73493 	 * < 0 (i.e. no case clauses), in which case this is a no-op.
73494 	 */
73495 	duk__patch_jump_here(comp_ctx, pc_prevstmt);
73496 
73497 	/* continue jump not patched, an INVALID opcode remains there */
73498 	duk__patch_jump_here(comp_ctx, pc_label_site + 1);  /* break jump */
73499 
73500 	/* Note: 'fast' breaks will jump to pc_label_site + 1, which will
73501 	 * then jump here.  The double jump will be eliminated by a
73502 	 * peephole pass, resulting in an optimal jump here.  The label
73503 	 * site jumps will remain in bytecode and will waste code size.
73504 	 */
73505 
73506 	return;
73507 
73508  syntax_error:
73509 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_SWITCH);
73510 	DUK_WO_NORETURN(return;);
73511 }
73512 
73513 DUK_LOCAL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
73514 	duk_regconst_t temp_reset;
73515 	duk_regconst_t rc_cond;
73516 	duk_int_t pc_jump_false;
73517 
73518 	DUK_DDD(DUK_DDDPRINT("begin parsing if statement"));
73519 
73520 	temp_reset = DUK__GETTEMP(comp_ctx);
73521 
73522 	duk__advance(comp_ctx);  /* eat 'if' */
73523 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
73524 
73525 	rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
73526 	duk__emit_if_true_skip(comp_ctx, rc_cond);
73527 	pc_jump_false = duk__emit_jump_empty(comp_ctx);  /* jump to end or else part */
73528 	DUK__SETTEMP(comp_ctx, temp_reset);
73529 
73530 	comp_ctx->curr_func.allow_regexp_in_adv = 1;
73531 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */
73532 
73533 	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
73534 
73535 	/* The 'else' ambiguity is resolved by 'else' binding to the innermost
73536 	 * construct, so greedy matching is correct here.
73537 	 */
73538 
73539 	if (comp_ctx->curr_token.t == DUK_TOK_ELSE) {
73540 		duk_int_t pc_jump_end;
73541 
73542 		DUK_DDD(DUK_DDDPRINT("if has else part"));
73543 
73544 		duk__advance(comp_ctx);
73545 
73546 		pc_jump_end = duk__emit_jump_empty(comp_ctx);  /* jump from true part to end */
73547 		duk__patch_jump_here(comp_ctx, pc_jump_false);
73548 
73549 		duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
73550 
73551 		duk__patch_jump_here(comp_ctx, pc_jump_end);
73552 	} else {
73553 		DUK_DDD(DUK_DDDPRINT("if does not have else part"));
73554 
73555 		duk__patch_jump_here(comp_ctx, pc_jump_false);
73556 	}
73557 
73558 	DUK_DDD(DUK_DDDPRINT("end parsing if statement"));
73559 }
73560 
73561 DUK_LOCAL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
73562 	duk_regconst_t rc_cond;
73563 	duk_int_t pc_start;
73564 
73565 	DUK_DDD(DUK_DDDPRINT("begin parsing do statement"));
73566 
73567 	duk__advance(comp_ctx);  /* Eat 'do'; allow RegExp as part of next stmt. */
73568 
73569 	pc_start = duk__get_current_pc(comp_ctx);
73570 	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
73571 	duk__patch_jump_here(comp_ctx, pc_label_site + 2);  /* continue jump */
73572 
73573 	duk__advance_expect(comp_ctx, DUK_TOK_WHILE);
73574 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
73575 
73576 	rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
73577 	duk__emit_if_false_skip(comp_ctx, rc_cond);
73578 	duk__emit_jump(comp_ctx, pc_start);
73579 	/* no need to reset temps, as we're finished emitting code */
73580 
73581 	comp_ctx->curr_func.allow_regexp_in_adv = 1;  /* Allow RegExp as part of next stmt. */
73582 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
73583 
73584 	duk__patch_jump_here(comp_ctx, pc_label_site + 1);  /* break jump */
73585 
73586 	DUK_DDD(DUK_DDDPRINT("end parsing do statement"));
73587 }
73588 
73589 DUK_LOCAL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
73590 	duk_regconst_t temp_reset;
73591 	duk_regconst_t rc_cond;
73592 	duk_int_t pc_start;
73593 	duk_int_t pc_jump_false;
73594 
73595 	DUK_DDD(DUK_DDDPRINT("begin parsing while statement"));
73596 
73597 	temp_reset = DUK__GETTEMP(comp_ctx);
73598 
73599 	duk__advance(comp_ctx);  /* eat 'while' */
73600 
73601 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
73602 
73603 	pc_start = duk__get_current_pc(comp_ctx);
73604 	duk__patch_jump_here(comp_ctx, pc_label_site + 2);  /* continue jump */
73605 
73606 	rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
73607 	duk__emit_if_true_skip(comp_ctx, rc_cond);
73608 	pc_jump_false = duk__emit_jump_empty(comp_ctx);
73609 	DUK__SETTEMP(comp_ctx, temp_reset);
73610 
73611 	comp_ctx->curr_func.allow_regexp_in_adv = 1;
73612 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */
73613 
73614 	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
73615 	duk__emit_jump(comp_ctx, pc_start);
73616 
73617 	duk__patch_jump_here(comp_ctx, pc_jump_false);
73618 	duk__patch_jump_here(comp_ctx, pc_label_site + 1);  /* break jump */
73619 
73620 	DUK_DDD(DUK_DDDPRINT("end parsing while statement"));
73621 }
73622 
73623 DUK_LOCAL void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
73624 	duk_hthread *thr = comp_ctx->thr;
73625 	duk_bool_t is_break = (comp_ctx->curr_token.t == DUK_TOK_BREAK);
73626 	duk_int_t label_id;
73627 	duk_int_t label_catch_depth;
73628 	duk_int_t label_pc;  /* points to LABEL; pc+1 = jump site for break; pc+2 = jump site for continue */
73629 	duk_bool_t label_is_closest;
73630 
73631 	DUK_UNREF(res);
73632 
73633 	duk__advance(comp_ctx);  /* eat 'break' or 'continue' */
73634 
73635 	if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON ||  /* explicit semi follows */
73636 	    comp_ctx->curr_token.lineterm ||                /* automatic semi will be inserted */
73637 	    comp_ctx->curr_token.allow_auto_semi) {         /* automatic semi will be inserted */
73638 		/* break/continue without label */
73639 
73640 		duk__lookup_active_label(comp_ctx, DUK_HTHREAD_STRING_EMPTY_STRING(thr), is_break, &label_id, &label_catch_depth, &label_pc, &label_is_closest);
73641 	} else if (comp_ctx->curr_token.t == DUK_TOK_IDENTIFIER) {
73642 		/* break/continue with label (label cannot be a reserved word, production is 'Identifier' */
73643 		DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
73644 		duk__lookup_active_label(comp_ctx, comp_ctx->curr_token.str1, is_break, &label_id, &label_catch_depth, &label_pc, &label_is_closest);
73645 		duk__advance(comp_ctx);
73646 	} else {
73647 		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_BREAK_CONT_LABEL);
73648 		DUK_WO_NORETURN(return;);
73649 	}
73650 
73651 	/* Use a fast break/continue when possible.  A fast break/continue is
73652 	 * just a jump to the LABEL break/continue jump slot, which then jumps
73653 	 * to an appropriate place (for break, going through ENDLABEL correctly).
73654 	 * The peephole optimizer will optimize the jump to a direct one.
73655 	 */
73656 
73657 	if (label_catch_depth == comp_ctx->curr_func.catch_depth &&
73658 	    label_is_closest) {
73659 		DUK_DDD(DUK_DDDPRINT("break/continue: is_break=%ld, label_id=%ld, label_is_closest=%ld, "
73660 		                     "label_catch_depth=%ld, catch_depth=%ld "
73661 		                     "-> use fast variant (direct jump)",
73662 		                     (long) is_break, (long) label_id, (long) label_is_closest,
73663 		                     (long) label_catch_depth, (long) comp_ctx->curr_func.catch_depth));
73664 
73665 		duk__emit_jump(comp_ctx, label_pc + (is_break ? 1 : 2));
73666 	} else {
73667 		DUK_DDD(DUK_DDDPRINT("break/continue: is_break=%ld, label_id=%ld, label_is_closest=%ld, "
73668 		                     "label_catch_depth=%ld, catch_depth=%ld "
73669 		                     "-> use slow variant (longjmp)",
73670 		                     (long) is_break, (long) label_id, (long) label_is_closest,
73671 		                     (long) label_catch_depth, (long) comp_ctx->curr_func.catch_depth));
73672 
73673 		duk__emit_bc(comp_ctx,
73674 		             is_break ? DUK_OP_BREAK : DUK_OP_CONTINUE,
73675 		             (duk_regconst_t) label_id);
73676 	}
73677 }
73678 
73679 DUK_LOCAL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
73680 	duk_hthread *thr = comp_ctx->thr;
73681 	duk_regconst_t rc_val;
73682 
73683 	duk__advance(comp_ctx);  /* eat 'return' */
73684 
73685 	/* A 'return' statement is only allowed inside an actual function body,
73686 	 * not as part of eval or global code.
73687 	 */
73688 	if (!comp_ctx->curr_func.is_function) {
73689 		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_RETURN);
73690 		DUK_WO_NORETURN(return;);
73691 	}
73692 
73693 	if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON ||  /* explicit semi follows */
73694 	    comp_ctx->curr_token.lineterm ||                /* automatic semi will be inserted */
73695 	    comp_ctx->curr_token.allow_auto_semi) {         /* automatic semi will be inserted */
73696 		DUK_DDD(DUK_DDDPRINT("empty return value -> undefined"));
73697 		duk__emit_op_only(comp_ctx, DUK_OP_RETUNDEF);
73698 	} else {
73699 		duk_int_t pc_before_expr;
73700 		duk_int_t pc_after_expr;
73701 
73702 		DUK_DDD(DUK_DDDPRINT("return with a value"));
73703 
73704 		DUK_UNREF(pc_before_expr);
73705 		DUK_UNREF(pc_after_expr);
73706 
73707 		pc_before_expr = duk__get_current_pc(comp_ctx);
73708 		rc_val = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
73709 		pc_after_expr = duk__get_current_pc(comp_ctx);
73710 
73711 		/* Tail call check: if last opcode emitted was CALL, and
73712 		 * the context allows it, add a tailcall flag to the CALL.
73713 		 * This doesn't guarantee that a tail call will be allowed at
73714 		 * runtime, so the RETURN must still be emitted.  (Duktape
73715 		 * 0.10.0 avoided this and simulated a RETURN if a tail call
73716 		 * couldn't be used at runtime; but this didn't work
73717 		 * correctly with a thread yield/resume, see
73718 		 * test-bug-tailcall-thread-yield-resume.js for discussion.)
73719 		 *
73720 		 * In addition to the last opcode being CALL, we also need to
73721 		 * be sure that 'rc_val' is the result register of the CALL.
73722 		 * For instance, for the expression 'return 0, (function ()
73723 		 * { return 1; }), 2' the last opcode emitted is CALL (no
73724 		 * bytecode is emitted for '2') but 'rc_val' indicates
73725 		 * constant '2'.  Similarly if '2' is replaced by a register
73726 		 * bound variable, no opcodes are emitted but tail call would
73727 		 * be incorrect.
73728 		 *
73729 		 * This is tricky and easy to get wrong.  It would be best to
73730 		 * track enough expression metadata to check that 'rc_val' came
73731 		 * from that last CALL instruction.  We don't have that metadata
73732 		 * now, so we check that 'rc_val' is a temporary register result
73733 		 * (not a constant or a register bound variable).  There should
73734 		 * be no way currently for 'rc_val' to be a temporary for an
73735 		 * expression following the CALL instruction without emitting
73736 		 * some opcodes following the CALL.  This proxy check is used
73737 		 * below.
73738 		 *
73739 		 * See: test-bug-comma-expr-gh131.js.
73740 		 *
73741 		 * The non-standard 'caller' property disables tail calls
73742 		 * because they pose some special cases which haven't been
73743 		 * fixed yet.
73744 		 */
73745 
73746 #if defined(DUK_USE_TAILCALL)
73747 		if (comp_ctx->curr_func.catch_depth == 0 &&   /* no catchers */
73748 		    pc_after_expr > pc_before_expr) {         /* at least one opcode emitted */
73749 			duk_compiler_instr *instr;
73750 			duk_instr_t ins;
73751 			duk_small_uint_t op;
73752 
73753 			instr = duk__get_instr_ptr(comp_ctx, pc_after_expr - 1);
73754 			DUK_ASSERT(instr != NULL);
73755 
73756 			ins = instr->ins;
73757 			op = (duk_small_uint_t) DUK_DEC_OP(ins);
73758 			if ((op & ~0x0fU) == DUK_OP_CALL0 &&
73759 			    DUK__ISREG_TEMP(comp_ctx, rc_val) /* see above */) {
73760 				DUK_DDD(DUK_DDDPRINT("return statement detected a tail call opportunity: "
73761 				                     "catch depth is 0, duk__exprtop() emitted >= 1 instructions, "
73762 				                     "and last instruction is a CALL "
73763 				                     "-> change to TAILCALL"));
73764 				ins |= DUK_ENC_OP(DUK_BC_CALL_FLAG_TAILCALL);
73765 				instr->ins = ins;
73766 			}
73767 		}
73768 #endif  /* DUK_USE_TAILCALL */
73769 
73770 		if (DUK__ISREG(rc_val)) {
73771 			duk__emit_bc(comp_ctx, DUK_OP_RETREG, rc_val);
73772 		} else {
73773 			rc_val = DUK__REMOVECONST(rc_val);
73774 			if (duk__const_needs_refcount(comp_ctx, rc_val)) {
73775 				duk__emit_bc(comp_ctx, DUK_OP_RETCONST, rc_val);
73776 			} else {
73777 				duk__emit_bc(comp_ctx, DUK_OP_RETCONSTN, rc_val);
73778 			}
73779 		}
73780 	}
73781 }
73782 
73783 DUK_LOCAL void duk__parse_throw_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
73784 	duk_regconst_t reg_val;
73785 
73786 	duk__advance(comp_ctx);  /* eat 'throw' */
73787 
73788 	/* Unlike break/continue, throw statement does not allow an empty value. */
73789 
73790 	if (comp_ctx->curr_token.lineterm) {
73791 		DUK_ERROR_SYNTAX(comp_ctx->thr, DUK_STR_INVALID_THROW);
73792 		DUK_WO_NORETURN(return;);
73793 	}
73794 
73795 	reg_val = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
73796 	duk__emit_bc(comp_ctx,
73797 	             DUK_OP_THROW,
73798 	             reg_val);
73799 }
73800 
73801 DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
73802 	duk_hthread *thr = comp_ctx->thr;
73803 	duk_regconst_t reg_catch;      /* reg_catch+0 and reg_catch+1 are reserved for TRYCATCH */
73804 	duk_regconst_t rc_varname = 0;
73805 	duk_small_uint_t trycatch_flags = 0;
73806 	duk_int_t pc_ldconst = -1;
73807 	duk_int_t pc_trycatch = -1;
73808 	duk_int_t pc_catch = -1;
73809 	duk_int_t pc_finally = -1;
73810 
73811 	DUK_UNREF(res);
73812 
73813 	/*
73814 	 *  See the following documentation for discussion:
73815 	 *
73816 	 *    doc/execution.rst: control flow details
73817 	 *
73818 	 *  Try, catch, and finally "parts" are Blocks, not Statements, so
73819 	 *  they must always be delimited by curly braces.  This is unlike e.g.
73820 	 *  the if statement, which accepts any Statement.  This eliminates any
73821 	 *  questions of matching parts of nested try statements.  The Block
73822 	 *  parsing is implemented inline here (instead of calling out).
73823 	 *
73824 	 *  Finally part has a 'let scoped' variable, which requires a few kinks
73825 	 *  here.
73826 	 */
73827 
73828 	comp_ctx->curr_func.catch_depth++;
73829 
73830 	duk__advance(comp_ctx);  /* eat 'try' */
73831 
73832 	reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);
73833 
73834 	/* The target for this LDCONST may need output shuffling, but we assume
73835 	 * that 'pc_ldconst' will be the LDCONST that we can patch later.  This
73836 	 * should be the case because there's no input shuffling.  (If there's
73837 	 * no catch clause, this LDCONST will be replaced with a NOP.)
73838 	 */
73839 	pc_ldconst = duk__get_current_pc(comp_ctx);
73840 	duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, reg_catch, 0 /*patched later*/);
73841 
73842 	pc_trycatch = duk__get_current_pc(comp_ctx);
73843 	duk__emit_invalid(comp_ctx);  /* TRYCATCH, cannot emit now (not enough info) */
73844 	duk__emit_invalid(comp_ctx);  /* jump for 'catch' case */
73845 	duk__emit_invalid(comp_ctx);  /* jump for 'finally' case or end (if no finally) */
73846 
73847 	/* try part */
73848 	duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
73849 	duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
73850 	/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
73851 	duk__emit_op_only(comp_ctx, DUK_OP_ENDTRY);
73852 
73853 	if (comp_ctx->curr_token.t == DUK_TOK_CATCH) {
73854 		/*
73855 		 *  The catch variable must be updated to reflect the new allocated
73856 		 *  register for the duration of the catch clause.  We need to store
73857 		 *  and restore the original value for the varmap entry (if any).
73858 		 */
73859 
73860 		/*
73861 		 *  Note: currently register bindings must be fixed for the entire
73862 		 *  function.  So, even though the catch variable is in a register
73863 		 *  we know, we must use an explicit environment record and slow path
73864 		 *  accesses to read/write the catch binding to make closures created
73865 		 *  within the catch clause work correctly.  This restriction should
73866 		 *  be fixable (at least in common cases) later.
73867 		 *
73868 		 *  See: test-bug-catch-binding-2.js.
73869 		 *
73870 		 *  XXX: improve to get fast path access to most catch clauses.
73871 		 */
73872 
73873 		duk_hstring *h_var;
73874 		duk_int_t varmap_value;  /* for storing/restoring the varmap binding for catch variable */
73875 
73876 		DUK_DDD(DUK_DDDPRINT("stack top at start of catch clause: %ld", (long) duk_get_top(thr)));
73877 
73878 		trycatch_flags |= DUK_BC_TRYCATCH_FLAG_HAVE_CATCH;
73879 
73880 		pc_catch = duk__get_current_pc(comp_ctx);
73881 
73882 		duk__advance(comp_ctx);
73883 		duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
73884 
73885 		if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
73886 			/* Identifier, i.e. don't allow reserved words */
73887 			goto syntax_error;
73888 		}
73889 		h_var = comp_ctx->curr_token.str1;
73890 		DUK_ASSERT(h_var != NULL);
73891 
73892 		duk_push_hstring(thr, h_var);  /* keep in on valstack, use borrowed ref below */
73893 
73894 		if (comp_ctx->curr_func.is_strict &&
73895 		    ((h_var == DUK_HTHREAD_STRING_EVAL(thr)) ||
73896 		     (h_var == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)))) {
73897 			DUK_DDD(DUK_DDDPRINT("catch identifier 'eval' or 'arguments' in strict mode -> SyntaxError"));
73898 			goto syntax_error;
73899 		}
73900 
73901 		duk_dup_top(thr);
73902 		rc_varname = duk__getconst(comp_ctx);
73903 		DUK_DDD(DUK_DDDPRINT("catch clause, rc_varname=0x%08lx (%ld)",
73904 		                     (unsigned long) rc_varname, (long) rc_varname));
73905 
73906 		duk__advance(comp_ctx);
73907 		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
73908 
73909 		duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
73910 
73911 		DUK_DDD(DUK_DDDPRINT("varmap before modifying for catch clause: %!iT",
73912 		                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx)));
73913 
73914 		duk_dup_top(thr);
73915 		duk_get_prop(thr, comp_ctx->curr_func.varmap_idx);
73916 		if (duk_is_undefined(thr, -1)) {
73917 			varmap_value = -2;
73918 		} else if (duk_is_null(thr, -1)) {
73919 			varmap_value = -1;
73920 		} else {
73921 			DUK_ASSERT(duk_is_number(thr, -1));
73922 			varmap_value = duk_get_int(thr, -1);
73923 			DUK_ASSERT(varmap_value >= 0);
73924 		}
73925 		duk_pop(thr);
73926 
73927 #if 0
73928 		/* It'd be nice to do something like this - but it doesn't
73929 		 * work for closures created inside the catch clause.
73930 		 */
73931 		duk_dup_top(thr);
73932 		duk_push_int(thr, (duk_int_t) (reg_catch + 0));
73933 		duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);
73934 #endif
73935 		duk_dup_top(thr);
73936 		duk_push_null(thr);
73937 		duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);
73938 
73939 		duk__emit_a_bc(comp_ctx,
73940 		               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
73941 		               reg_catch + 0 /*value*/,
73942 		               rc_varname /*varname*/);
73943 
73944 		DUK_DDD(DUK_DDDPRINT("varmap before parsing catch clause: %!iT",
73945 		                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx)));
73946 
73947 		duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
73948 		/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
73949 
73950 		if (varmap_value == -2) {
73951 			/* not present */
73952 			duk_del_prop(thr, comp_ctx->curr_func.varmap_idx);
73953 		} else {
73954 			if (varmap_value == -1) {
73955 				duk_push_null(thr);
73956 			} else {
73957 				DUK_ASSERT(varmap_value >= 0);
73958 				duk_push_int(thr, varmap_value);
73959 			}
73960 			duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);
73961 		}
73962 		/* varname is popped by above code */
73963 
73964 		DUK_DDD(DUK_DDDPRINT("varmap after restore catch clause: %!iT",
73965 		                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx)));
73966 
73967 		duk__emit_op_only(comp_ctx,
73968 		                  DUK_OP_ENDCATCH);
73969 
73970 		/*
73971 		 *  XXX: for now, indicate that an expensive catch binding
73972 		 *  declarative environment is always needed.  If we don't
73973 		 *  need it, we don't need the const_varname either.
73974 		 */
73975 
73976 		trycatch_flags |= DUK_BC_TRYCATCH_FLAG_CATCH_BINDING;
73977 
73978 		DUK_DDD(DUK_DDDPRINT("stack top at end of catch clause: %ld", (long) duk_get_top(thr)));
73979 	}
73980 
73981 	if (comp_ctx->curr_token.t == DUK_TOK_FINALLY) {
73982 		trycatch_flags |= DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY;
73983 
73984 		pc_finally = duk__get_current_pc(comp_ctx);
73985 
73986 		duk__advance(comp_ctx);
73987 
73988 		duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
73989 		duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
73990 		/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
73991 		duk__emit_abc(comp_ctx,
73992 		              DUK_OP_ENDFIN,
73993 		              reg_catch);  /* rethrow */
73994 	}
73995 
73996 	if (!(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) &&
73997 	    !(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY)) {
73998 		/* must have catch and/or finally */
73999 		goto syntax_error;
74000 	}
74001 
74002 	/* If there's no catch block, rc_varname will be 0 and duk__patch_trycatch()
74003 	 * will replace the LDCONST with a NOP.  For any actual constant (including
74004 	 * constant 0) the DUK__CONST_MARKER flag will be set in rc_varname.
74005 	 */
74006 
74007 	duk__patch_trycatch(comp_ctx,
74008 	                    pc_ldconst,
74009 	                    pc_trycatch,
74010 	                    reg_catch,
74011 	                    rc_varname,
74012 	                    trycatch_flags);
74013 
74014 	if (trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) {
74015 		DUK_ASSERT(pc_catch >= 0);
74016 		duk__patch_jump(comp_ctx, pc_trycatch + 1, pc_catch);
74017 	}
74018 
74019 	if (trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY) {
74020 		DUK_ASSERT(pc_finally >= 0);
74021 		duk__patch_jump(comp_ctx, pc_trycatch + 2, pc_finally);
74022 	} else {
74023 		/* without finally, the second jump slot is used to jump to end of stmt */
74024 		duk__patch_jump_here(comp_ctx, pc_trycatch + 2);
74025 	}
74026 
74027 	comp_ctx->curr_func.catch_depth--;
74028 	return;
74029 
74030  syntax_error:
74031 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_TRY);
74032 	DUK_WO_NORETURN(return;);
74033 }
74034 
74035 DUK_LOCAL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
74036 	duk_int_t pc_trycatch;
74037 	duk_int_t pc_finished;
74038 	duk_regconst_t reg_catch;
74039 	duk_small_uint_t trycatch_flags;
74040 
74041 	if (comp_ctx->curr_func.is_strict) {
74042 		DUK_ERROR_SYNTAX(comp_ctx->thr, DUK_STR_WITH_IN_STRICT_MODE);
74043 		DUK_WO_NORETURN(return;);
74044 	}
74045 
74046 	comp_ctx->curr_func.catch_depth++;
74047 
74048 	duk__advance(comp_ctx);  /* eat 'with' */
74049 
74050 	reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);
74051 
74052 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
74053 	duk__exprtop_toforcedreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/, reg_catch);
74054 	comp_ctx->curr_func.allow_regexp_in_adv = 1;
74055 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */
74056 
74057 	pc_trycatch = duk__get_current_pc(comp_ctx);
74058 	trycatch_flags = DUK_BC_TRYCATCH_FLAG_WITH_BINDING;
74059 	duk__emit_a_bc(comp_ctx,
74060 	                DUK_OP_TRYCATCH | DUK__EMIT_FLAG_NO_SHUFFLE_A,
74061 	                (duk_regconst_t) trycatch_flags /*a*/,
74062 	                reg_catch /*bc*/);
74063 	duk__emit_invalid(comp_ctx);  /* catch jump */
74064 	duk__emit_invalid(comp_ctx);  /* finished jump */
74065 
74066 	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
74067 	duk__emit_op_only(comp_ctx, DUK_OP_ENDTRY);
74068 
74069 	pc_finished = duk__get_current_pc(comp_ctx);
74070 
74071 	duk__patch_jump(comp_ctx, pc_trycatch + 2, pc_finished);
74072 
74073 	comp_ctx->curr_func.catch_depth--;
74074 }
74075 
74076 DUK_LOCAL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id) {
74077 	/* if a site already exists, nop: max one label site per statement */
74078 	if (label_id >= 0) {
74079 		return label_id;
74080 	}
74081 
74082 	label_id = comp_ctx->curr_func.label_next++;
74083 	DUK_DDD(DUK_DDDPRINT("allocated new label id for label site: %ld", (long) label_id));
74084 
74085 	duk__emit_bc(comp_ctx,
74086 	             DUK_OP_LABEL,
74087 	             (duk_regconst_t) label_id);
74088 	duk__emit_invalid(comp_ctx);
74089 	duk__emit_invalid(comp_ctx);
74090 
74091 	return label_id;
74092 }
74093 
74094 /* Parse a single statement.
74095  *
74096  * Creates a label site (with an empty label) automatically for iteration
74097  * statements.  Also "peels off" any label statements for explicit labels.
74098  */
74099 DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem) {
74100 	duk_hthread *thr = comp_ctx->thr;
74101 	duk_bool_t dir_prol_at_entry;    /* directive prologue status at entry */
74102 	duk_regconst_t temp_at_entry;
74103 	duk_size_t labels_len_at_entry;
74104 	duk_int_t pc_at_entry;           /* assumed to also be PC of "LABEL" */
74105 	duk_int_t stmt_id;
74106 	duk_small_uint_t stmt_flags = 0;
74107 	duk_int_t label_id = -1;
74108 	duk_small_uint_t tok;
74109 	duk_bool_t test_func_decl;
74110 
74111 	DUK__RECURSION_INCREASE(comp_ctx, thr);
74112 
74113 	temp_at_entry = DUK__GETTEMP(comp_ctx);
74114 	pc_at_entry = duk__get_current_pc(comp_ctx);
74115 	labels_len_at_entry = duk_get_length(thr, comp_ctx->curr_func.labelnames_idx);
74116 	stmt_id = comp_ctx->curr_func.stmt_next++;
74117 	dir_prol_at_entry = comp_ctx->curr_func.in_directive_prologue;
74118 
74119 	DUK_UNREF(stmt_id);
74120 
74121 	DUK_DDD(DUK_DDDPRINT("parsing a statement, stmt_id=%ld, temp_at_entry=%ld, labels_len_at_entry=%ld, "
74122 	                     "is_strict=%ld, in_directive_prologue=%ld, catch_depth=%ld",
74123 	                     (long) stmt_id, (long) temp_at_entry, (long) labels_len_at_entry,
74124 	                     (long) comp_ctx->curr_func.is_strict, (long) comp_ctx->curr_func.in_directive_prologue,
74125 	                     (long) comp_ctx->curr_func.catch_depth));
74126 
74127 	/* The directive prologue flag is cleared by default so that it is
74128 	 * unset for any recursive statement parsing.  It is only "revived"
74129 	 * if a directive is detected.  (We could also make directives only
74130 	 * allowed if 'allow_source_elem' was true.)
74131 	 */
74132 	comp_ctx->curr_func.in_directive_prologue = 0;
74133 
74134  retry_parse:
74135 
74136 	DUK_DDD(DUK_DDDPRINT("try stmt parse, stmt_id=%ld, label_id=%ld, allow_source_elem=%ld, catch_depth=%ld",
74137 	                     (long) stmt_id, (long) label_id, (long) allow_source_elem,
74138 	                     (long) comp_ctx->curr_func.catch_depth));
74139 
74140 	/*
74141 	 *  Detect iteration statements; if encountered, establish an
74142 	 *  empty label.
74143 	 */
74144 
74145 	tok = comp_ctx->curr_token.t;
74146 	if (tok == DUK_TOK_FOR || tok == DUK_TOK_DO || tok == DUK_TOK_WHILE ||
74147 	    tok == DUK_TOK_SWITCH) {
74148 		DUK_DDD(DUK_DDDPRINT("iteration/switch statement -> add empty label"));
74149 
74150 		label_id = duk__stmt_label_site(comp_ctx, label_id);
74151 		duk__add_label(comp_ctx,
74152 		               DUK_HTHREAD_STRING_EMPTY_STRING(thr),
74153 		               pc_at_entry /*pc_label*/,
74154 		               label_id);
74155 	}
74156 
74157 	/*
74158 	 *  Main switch for statement / source element type.
74159 	 */
74160 
74161 	switch (comp_ctx->curr_token.t) {
74162 	case DUK_TOK_FUNCTION: {
74163 		/*
74164 		 *  Function declaration, function expression, or (non-standard)
74165 		 *  function statement.
74166 		 *
74167 		 *  The E5 specification only allows function declarations at
74168 		 *  the top level (in "source elements").  An ExpressionStatement
74169 		 *  is explicitly not allowed to begin with a "function" keyword
74170 		 *  (E5 Section 12.4).  Hence any non-error semantics for such
74171 		 *  non-top-level statements are non-standard.  Duktape semantics
74172 		 *  for function statements are modelled after V8, see
74173 		 *  test-dev-func-decl-outside-top.js.
74174 		 */
74175 		test_func_decl = allow_source_elem;
74176 #if defined(DUK_USE_NONSTD_FUNC_STMT)
74177 		/* Lenient: allow function declarations outside top level in both
74178 		 * strict and non-strict modes.  However, don't allow labelled
74179 		 * function declarations in strict mode.
74180 		 */
74181 		test_func_decl = test_func_decl ||
74182 		                 !comp_ctx->curr_func.is_strict ||
74183 		                 label_id < 0;
74184 #endif  /* DUK_USE_NONSTD_FUNC_STMT */
74185 		/* Strict: never allow function declarations outside top level. */
74186 		if (test_func_decl) {
74187 			/* FunctionDeclaration: not strictly a statement but handled as such.
74188 			 *
74189 			 * O(depth^2) parse count for inner functions is handled by recording a
74190 			 * lexer offset on the first compilation pass, so that the function can
74191 			 * be efficiently skipped on the second pass.  This is encapsulated into
74192 			 * duk__parse_func_like_fnum().
74193 			 */
74194 
74195 			duk_int_t fnum;
74196 #if defined(DUK_USE_ASSERTIONS)
74197 			duk_idx_t top_before;
74198 #endif
74199 
74200 			DUK_DDD(DUK_DDDPRINT("function declaration statement"));
74201 
74202 #if defined(DUK_USE_ASSERTIONS)
74203 			top_before = duk_get_top(thr);
74204 #endif
74205 
74206 			duk__advance(comp_ctx);  /* eat 'function' */
74207 			fnum = duk__parse_func_like_fnum(comp_ctx, DUK__FUNC_FLAG_DECL | DUK__FUNC_FLAG_PUSHNAME_PASS1);
74208 
74209 			/* The value stack convention here is a bit odd: the function
74210 			 * name is only pushed on pass 1 (in_scanning), and is needed
74211 			 * to process function declarations.
74212 			 */
74213 			if (comp_ctx->curr_func.in_scanning) {
74214 				duk_uarridx_t n;
74215 
74216 #if defined(DUK_USE_ASSERTIONS)
74217 				DUK_ASSERT(duk_get_top(thr) == top_before + 1);
74218 #endif
74219 				DUK_DDD(DUK_DDDPRINT("register function declaration %!T in pass 1, fnum %ld",
74220 				                     duk_get_tval(thr, -1), (long) fnum));
74221 				n = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.decls_idx);
74222 				/* funcname is at index -1 */
74223 				duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n);
74224 				duk_push_int(thr, (duk_int_t) (DUK_DECL_TYPE_FUNC + (fnum << 8)));
74225 				duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n + 1);
74226 			} else {
74227 #if defined(DUK_USE_ASSERTIONS)
74228 				DUK_ASSERT(duk_get_top(thr) == top_before);
74229 #endif
74230 			}
74231 
74232 			/* no statement value (unlike function expression) */
74233 			stmt_flags = 0;
74234 			break;
74235 		} else {
74236 			DUK_ERROR_SYNTAX(thr, DUK_STR_FUNC_STMT_NOT_ALLOWED);
74237 			DUK_WO_NORETURN(return;);
74238 		}
74239 		break;
74240 	}
74241 	case DUK_TOK_LCURLY: {
74242 		DUK_DDD(DUK_DDDPRINT("block statement"));
74243 		duk__advance(comp_ctx);
74244 		duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
74245 		/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
74246 		if (label_id >= 0) {
74247 			duk__patch_jump_here(comp_ctx, pc_at_entry + 1);  /* break jump */
74248 		}
74249 		stmt_flags = 0;
74250 		break;
74251 	}
74252 	case DUK_TOK_CONST: {
74253 		DUK_DDD(DUK_DDDPRINT("constant declaration statement"));
74254 		duk__parse_var_stmt(comp_ctx, res, DUK__EXPR_FLAG_REQUIRE_INIT /*expr_flags*/);
74255 		stmt_flags = DUK__HAS_TERM;
74256 		break;
74257 	}
74258 	case DUK_TOK_VAR: {
74259 		DUK_DDD(DUK_DDDPRINT("variable declaration statement"));
74260 		duk__parse_var_stmt(comp_ctx, res, 0 /*expr_flags*/);
74261 		stmt_flags = DUK__HAS_TERM;
74262 		break;
74263 	}
74264 	case DUK_TOK_SEMICOLON: {
74265 		/* empty statement with an explicit semicolon */
74266 		DUK_DDD(DUK_DDDPRINT("empty statement"));
74267 		stmt_flags = DUK__HAS_TERM;
74268 		break;
74269 	}
74270 	case DUK_TOK_IF: {
74271 		DUK_DDD(DUK_DDDPRINT("if statement"));
74272 		duk__parse_if_stmt(comp_ctx, res);
74273 		if (label_id >= 0) {
74274 			duk__patch_jump_here(comp_ctx, pc_at_entry + 1);  /* break jump */
74275 		}
74276 		stmt_flags = 0;
74277 		break;
74278 	}
74279 	case DUK_TOK_DO: {
74280 		/*
74281 		 *  Do-while statement is mostly trivial, but there is special
74282 		 *  handling for automatic semicolon handling (triggered by the
74283 		 *  DUK__ALLOW_AUTO_SEMI_ALWAYS) flag related to a bug filed at:
74284 		 *
74285 		 *    https://bugs.ecmascript.org/show_bug.cgi?id=8
74286 		 *
74287 		 *  See doc/compiler.rst for details.
74288 		 */
74289 		DUK_DDD(DUK_DDDPRINT("do statement"));
74290 		DUK_ASSERT(label_id >= 0);
74291 		duk__update_label_flags(comp_ctx,
74292 		                        label_id,
74293 		                        DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
74294 		duk__parse_do_stmt(comp_ctx, res, pc_at_entry);
74295 		stmt_flags = DUK__HAS_TERM | DUK__ALLOW_AUTO_SEMI_ALWAYS;  /* DUK__ALLOW_AUTO_SEMI_ALWAYS workaround */
74296 		break;
74297 	}
74298 	case DUK_TOK_WHILE: {
74299 		DUK_DDD(DUK_DDDPRINT("while statement"));
74300 		DUK_ASSERT(label_id >= 0);
74301 		duk__update_label_flags(comp_ctx,
74302 		                        label_id,
74303 		                        DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
74304 		duk__parse_while_stmt(comp_ctx, res, pc_at_entry);
74305 		stmt_flags = 0;
74306 		break;
74307 	}
74308 	case DUK_TOK_FOR: {
74309 		/*
74310 		 *  For/for-in statement is complicated to parse because
74311 		 *  determining the statement type (three-part for vs. a
74312 		 *  for-in) requires potential backtracking.
74313 		 *
74314 		 *  See the helper for the messy stuff.
74315 		 */
74316 		DUK_DDD(DUK_DDDPRINT("for/for-in statement"));
74317 		DUK_ASSERT(label_id >= 0);
74318 		duk__update_label_flags(comp_ctx,
74319 		                        label_id,
74320 		                        DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
74321 		duk__parse_for_stmt(comp_ctx, res, pc_at_entry);
74322 		stmt_flags = 0;
74323 		break;
74324 	}
74325 	case DUK_TOK_CONTINUE:
74326 	case DUK_TOK_BREAK: {
74327 		DUK_DDD(DUK_DDDPRINT("break/continue statement"));
74328 		duk__parse_break_or_continue_stmt(comp_ctx, res);
74329 		stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
74330 		break;
74331 	}
74332 	case DUK_TOK_RETURN: {
74333 		DUK_DDD(DUK_DDDPRINT("return statement"));
74334 		duk__parse_return_stmt(comp_ctx, res);
74335 		stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
74336 		break;
74337 	}
74338 	case DUK_TOK_WITH: {
74339 		DUK_DDD(DUK_DDDPRINT("with statement"));
74340 		comp_ctx->curr_func.with_depth++;
74341 		duk__parse_with_stmt(comp_ctx, res);
74342 		if (label_id >= 0) {
74343 			duk__patch_jump_here(comp_ctx, pc_at_entry + 1);  /* break jump */
74344 		}
74345 		comp_ctx->curr_func.with_depth--;
74346 		stmt_flags = 0;
74347 		break;
74348 	}
74349 	case DUK_TOK_SWITCH: {
74350 		/*
74351 		 *  The switch statement is pretty messy to compile.
74352 		 *  See the helper for details.
74353 		 */
74354 		DUK_DDD(DUK_DDDPRINT("switch statement"));
74355 		DUK_ASSERT(label_id >= 0);
74356 		duk__update_label_flags(comp_ctx,
74357 		                        label_id,
74358 		                        DUK_LABEL_FLAG_ALLOW_BREAK);  /* don't allow continue */
74359 		duk__parse_switch_stmt(comp_ctx, res, pc_at_entry);
74360 		stmt_flags = 0;
74361 		break;
74362 	}
74363 	case DUK_TOK_THROW: {
74364 		DUK_DDD(DUK_DDDPRINT("throw statement"));
74365 		duk__parse_throw_stmt(comp_ctx, res);
74366 		stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
74367 		break;
74368 	}
74369 	case DUK_TOK_TRY: {
74370 		DUK_DDD(DUK_DDDPRINT("try statement"));
74371 		duk__parse_try_stmt(comp_ctx, res);
74372 		stmt_flags = 0;
74373 		break;
74374 	}
74375 	case DUK_TOK_DEBUGGER: {
74376 		duk__advance(comp_ctx);
74377 #if defined(DUK_USE_DEBUGGER_SUPPORT)
74378 		DUK_DDD(DUK_DDDPRINT("debugger statement: debugging enabled, emit debugger opcode"));
74379 		duk__emit_op_only(comp_ctx, DUK_OP_DEBUGGER);
74380 #else
74381 		DUK_DDD(DUK_DDDPRINT("debugger statement: ignored"));
74382 #endif
74383 		stmt_flags = DUK__HAS_TERM;
74384 		break;
74385 	}
74386 	default: {
74387 		/*
74388 		 *  Else, must be one of:
74389 		 *    - ExpressionStatement, possibly a directive (String)
74390 		 *    - LabelledStatement (Identifier followed by ':')
74391 		 *
74392 		 *  Expressions beginning with 'function' keyword are covered by a case
74393 		 *  above (such expressions are not allowed in standard E5 anyway).
74394 		 *  Also expressions starting with '{' are interpreted as block
74395 		 *  statements.  See E5 Section 12.4.
74396 		 *
74397 		 *  Directive detection is tricky; see E5 Section 14.1 on directive
74398 		 *  prologue.  A directive is an expression statement with a single
74399 		 *  string literal and an explicit or automatic semicolon.  Escape
74400 		 *  characters are significant and no parens etc are allowed:
74401 		 *
74402 		 *    'use strict';          // valid 'use strict' directive
74403 		 *    'use\u0020strict';     // valid directive, not a 'use strict' directive
74404 		 *    ('use strict');        // not a valid directive
74405 		 *
74406 		 *  The expression is determined to consist of a single string literal
74407 		 *  based on duk__expr_nud() and duk__expr_led() call counts.  The string literal
74408 		 *  of a 'use strict' directive is determined to lack any escapes based
74409 		 *  num_escapes count from the lexer.  Note that other directives may be
74410 		 *  allowed to contain escapes, so a directive with escapes does not
74411 		 *  terminate a directive prologue.
74412 		 *
74413 		 *  We rely on the fact that the expression parser will not emit any
74414 		 *  code for a single token expression.  However, it will generate an
74415 		 *  intermediate value which we will then successfully ignore.
74416 		 *
74417 		 *  A similar approach is used for labels.
74418 		 */
74419 
74420 		duk_bool_t single_token;
74421 
74422 		DUK_DDD(DUK_DDDPRINT("expression statement"));
74423 		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
74424 
74425 		single_token = (comp_ctx->curr_func.nud_count == 1 &&  /* one token */
74426 		                comp_ctx->curr_func.led_count == 0);   /* no operators */
74427 
74428 		if (single_token &&
74429 		    comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
74430 		    comp_ctx->curr_token.t == DUK_TOK_COLON) {
74431 			/*
74432 			 *  Detected label
74433 			 */
74434 
74435 			duk_hstring *h_lab;
74436 
74437 			/* expected ival */
74438 			DUK_ASSERT(res->t == DUK_IVAL_VAR);
74439 			DUK_ASSERT(res->x1.t == DUK_ISPEC_VALUE);
74440 			DUK_ASSERT(DUK_TVAL_IS_STRING(duk_get_tval(thr, res->x1.valstack_idx)));
74441 			h_lab = comp_ctx->prev_token.str1;
74442 			DUK_ASSERT(h_lab != NULL);
74443 
74444 			DUK_DDD(DUK_DDDPRINT("explicit label site for label '%!O'",
74445 			                     (duk_heaphdr *) h_lab));
74446 
74447 			duk__advance(comp_ctx);  /* eat colon */
74448 
74449 			label_id = duk__stmt_label_site(comp_ctx, label_id);
74450 
74451 			duk__add_label(comp_ctx,
74452 			               h_lab,
74453 			               pc_at_entry /*pc_label*/,
74454 			               label_id);
74455 
74456 			/* a statement following a label cannot be a source element
74457 			 * (a function declaration).
74458 			 */
74459 			allow_source_elem = 0;
74460 
74461 			DUK_DDD(DUK_DDDPRINT("label handled, retry statement parsing"));
74462 			goto retry_parse;
74463 		}
74464 
74465 		stmt_flags = 0;
74466 
74467 		if (dir_prol_at_entry &&                           /* still in prologue */
74468 		    single_token &&                                /* single string token */
74469 		    comp_ctx->prev_token.t == DUK_TOK_STRING) {
74470 			/*
74471 			 *  Detected a directive
74472 			 */
74473 			duk_hstring *h_dir;
74474 
74475 			/* expected ival */
74476 			DUK_ASSERT(res->t == DUK_IVAL_PLAIN);
74477 			DUK_ASSERT(res->x1.t == DUK_ISPEC_VALUE);
74478 			DUK_ASSERT(DUK_TVAL_IS_STRING(duk_get_tval(thr, res->x1.valstack_idx)));
74479 			h_dir = comp_ctx->prev_token.str1;
74480 			DUK_ASSERT(h_dir != NULL);
74481 
74482 			DUK_DDD(DUK_DDDPRINT("potential directive: %!O", h_dir));
74483 
74484 			stmt_flags |= DUK__STILL_PROLOGUE;
74485 
74486 			/* Note: escaped characters differentiate directives */
74487 
74488 			if (comp_ctx->prev_token.num_escapes > 0) {
74489 				DUK_DDD(DUK_DDDPRINT("directive contains escapes: valid directive "
74490 				                     "but we ignore such directives"));
74491 			} else {
74492 				/*
74493 				 * The length comparisons are present to handle
74494 				 * strings like "use strict\u0000foo" as required.
74495 				 */
74496 
74497 				if (DUK_HSTRING_GET_BYTELEN(h_dir) == 10 &&
74498 				    DUK_STRCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use strict") == 0) {
74499 #if defined(DUK_USE_STRICT_DECL)
74500 					DUK_DDD(DUK_DDDPRINT("use strict directive detected: strict flag %ld -> %ld",
74501 					                     (long) comp_ctx->curr_func.is_strict, (long) 1));
74502 					comp_ctx->curr_func.is_strict = 1;
74503 #else
74504 					DUK_DDD(DUK_DDDPRINT("use strict detected but strict declarations disabled, ignoring"));
74505 #endif
74506 				} else if (DUK_HSTRING_GET_BYTELEN(h_dir) == 14 &&
74507 				           DUK_STRCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use duk notail") == 0) {
74508 					DUK_DDD(DUK_DDDPRINT("use duk notail directive detected: notail flag %ld -> %ld",
74509 					                     (long) comp_ctx->curr_func.is_notail, (long) 1));
74510 					comp_ctx->curr_func.is_notail = 1;
74511 				} else {
74512 					DUK_DD(DUK_DDPRINT("unknown directive: '%!O', ignoring but not terminating "
74513 					                   "directive prologue", (duk_hobject *) h_dir));
74514 				}
74515 			}
74516 		} else {
74517 			DUK_DDD(DUK_DDDPRINT("non-directive expression statement or no longer in prologue; "
74518 			                     "prologue terminated if still active"));
74519                 }
74520 
74521 		stmt_flags |= DUK__HAS_VAL | DUK__HAS_TERM;
74522 	}
74523 	}  /* end switch (tok) */
74524 
74525 	/*
74526 	 *  Statement value handling.
74527 	 *
74528 	 *  Global code and eval code has an implicit return value
74529 	 *  which comes from the last statement with a value
74530 	 *  (technically a non-"empty" continuation, which is
74531 	 *  different from an empty statement).
74532 	 *
74533 	 *  Since we don't know whether a later statement will
74534 	 *  override the value of the current statement, we need
74535 	 *  to coerce the statement value to a register allocated
74536 	 *  for implicit return values.  In other cases we need
74537 	 *  to coerce the statement value to a plain value to get
74538 	 *  any side effects out (consider e.g. "foo.bar;").
74539 	 */
74540 
74541 	/* XXX: what about statements which leave a half-cooked value in 'res'
74542 	 * but have no stmt value?  Any such statements?
74543 	 */
74544 
74545 	if (stmt_flags & DUK__HAS_VAL) {
74546 		duk_regconst_t reg_stmt_value = comp_ctx->curr_func.reg_stmt_value;
74547 		if (reg_stmt_value >= 0) {
74548 			duk__ivalue_toforcedreg(comp_ctx, res, reg_stmt_value);
74549 		} else {
74550 			duk__ivalue_toplain_ignore(comp_ctx, res);
74551 		}
74552 	} else {
74553 		;
74554 	}
74555 
74556 	/*
74557 	 *  Statement terminator check, including automatic semicolon
74558 	 *  handling.  After this step, 'curr_tok' should be the first
74559 	 *  token after a possible statement terminator.
74560 	 */
74561 
74562 	if (stmt_flags & DUK__HAS_TERM) {
74563 		if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON) {
74564 			DUK_DDD(DUK_DDDPRINT("explicit semicolon terminates statement"));
74565 			duk__advance(comp_ctx);
74566 		} else {
74567 			if (comp_ctx->curr_token.allow_auto_semi) {
74568 				DUK_DDD(DUK_DDDPRINT("automatic semicolon terminates statement"));
74569 			} else if (stmt_flags & DUK__ALLOW_AUTO_SEMI_ALWAYS) {
74570 				/* XXX: make this lenience dependent on flags or strictness? */
74571 				DUK_DDD(DUK_DDDPRINT("automatic semicolon terminates statement (allowed for compatibility "
74572 				                     "even though no lineterm present before next token)"));
74573 			} else {
74574 				DUK_ERROR_SYNTAX(thr, DUK_STR_UNTERMINATED_STMT);
74575 				DUK_WO_NORETURN(return;);
74576 			}
74577 		}
74578 	} else {
74579 		DUK_DDD(DUK_DDDPRINT("statement has no terminator"));
74580 	}
74581 
74582 	/*
74583 	 *  Directive prologue tracking.
74584 	 */
74585 
74586 	if (stmt_flags & DUK__STILL_PROLOGUE) {
74587 		DUK_DDD(DUK_DDDPRINT("setting in_directive_prologue"));
74588 		comp_ctx->curr_func.in_directive_prologue = 1;
74589 	}
74590 
74591 	/*
74592 	 *  Cleanups (all statement parsing flows through here).
74593 	 *
74594 	 *  Pop label site and reset labels.  Reset 'next temp' to value at
74595 	 *  entry to reuse temps.
74596 	 */
74597 
74598 	if (label_id >= 0) {
74599 		duk__emit_bc(comp_ctx,
74600 		             DUK_OP_ENDLABEL,
74601 		             (duk_regconst_t) label_id);
74602 	}
74603 
74604 	DUK__SETTEMP(comp_ctx, temp_at_entry);
74605 
74606 	duk__reset_labels_to_length(comp_ctx, labels_len_at_entry);
74607 
74608 	/* XXX: return indication of "terminalness" (e.g. a 'throw' is terminal) */
74609 
74610 	DUK__RECURSION_DECREASE(comp_ctx, thr);
74611 }
74612 
74613 /*
74614  *  Parse a statement list.
74615  *
74616  *  Handles automatic semicolon insertion and implicit return value.
74617  *
74618  *  Upon entry, 'curr_tok' should contain the first token of the first
74619  *  statement (parsed in the "allow regexp literal" mode).  Upon exit,
74620  *  'curr_tok' contains the token following the statement list terminator
74621  *  (EOF or closing brace).
74622  */
74623 
74624 DUK_LOCAL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof, duk_bool_t regexp_after) {
74625 	duk_hthread *thr = comp_ctx->thr;
74626 	duk_ivalue res_alloc;
74627 	duk_ivalue *res = &res_alloc;
74628 
74629 	/* Setup state.  Initial ivalue is 'undefined'. */
74630 
74631 	duk_require_stack(thr, DUK__PARSE_STATEMENTS_SLOTS);
74632 
74633 	/* XXX: 'res' setup can be moved to function body level; in fact, two 'res'
74634 	 * intermediate values suffice for parsing of each function.  Nesting is needed
74635 	 * for nested functions (which may occur inside expressions).
74636 	 */
74637 
74638 	duk_memzero(&res_alloc, sizeof(res_alloc));
74639 	res->t = DUK_IVAL_PLAIN;
74640 	res->x1.t = DUK_ISPEC_VALUE;
74641 	res->x1.valstack_idx = duk_get_top(thr);
74642 	res->x2.valstack_idx = res->x1.valstack_idx + 1;
74643 	duk_push_undefined(thr);
74644 	duk_push_undefined(thr);
74645 
74646 	/* Parse statements until a closing token (EOF or '}') is found. */
74647 
74648 	for (;;) {
74649 		/* Check whether statement list ends. */
74650 
74651 		if (expect_eof) {
74652 			if (comp_ctx->curr_token.t == DUK_TOK_EOF) {
74653 				break;
74654 			}
74655 		} else {
74656 			if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
74657 				break;
74658 			}
74659 		}
74660 
74661 		/* Check statement type based on the first token type.
74662 		 *
74663 		 * Note: expression parsing helpers expect 'curr_tok' to
74664 		 * contain the first token of the expression upon entry.
74665 		 */
74666 
74667 		DUK_DDD(DUK_DDDPRINT("TOKEN %ld (non-whitespace, non-comment)", (long) comp_ctx->curr_token.t));
74668 
74669 		duk__parse_stmt(comp_ctx, res, allow_source_elem);
74670 	}
74671 
74672 	/* RegExp is allowed / not allowed depending on context.  For function
74673 	 * declarations RegExp is allowed because it follows a function
74674 	 * declaration statement and may appear as part of the next statement.
74675 	 * For function expressions RegExp is not allowed, and it's possible
74676 	 * to do something like '(function () {} / 123)'.
74677 	 */
74678 	if (regexp_after) {
74679 		comp_ctx->curr_func.allow_regexp_in_adv = 1;
74680 	}
74681 	duk__advance(comp_ctx);
74682 
74683 	/* Tear down state. */
74684 
74685 	duk_pop_2(thr);
74686 }
74687 
74688 /*
74689  *  Declaration binding instantiation conceptually happens when calling a
74690  *  function; for us it essentially means that function prologue.  The
74691  *  conceptual process is described in E5 Section 10.5.
74692  *
74693  *  We need to keep track of all encountered identifiers to (1) create an
74694  *  identifier-to-register map ("varmap"); and (2) detect duplicate
74695  *  declarations.  Identifiers which are not bound to registers still need
74696  *  to be tracked for detecting duplicates.  Currently such identifiers
74697  *  are put into the varmap with a 'null' value, which is later cleaned up.
74698  *
74699  *  To support functions with a large number of variable and function
74700  *  declarations, registers are not allocated beyond a certain limit;
74701  *  after that limit, variables and functions need slow path access.
74702  *  Arguments are currently always register bound, which imposes a hard
74703  *  (and relatively small) argument count limit.
74704  *
74705  *  Some bindings in E5 are not configurable (= deletable) and almost all
74706  *  are mutable (writable).  Exceptions are:
74707  *
74708  *    - The 'arguments' binding, established only if no shadowing argument
74709  *      or function declaration exists.  We handle 'arguments' creation
74710  *      and binding through an explicit slow path environment record.
74711  *
74712  *    - The "name" binding for a named function expression.  This is also
74713  *      handled through an explicit slow path environment record.
74714  */
74715 
74716 /* XXX: add support for variables to not be register bound always, to
74717  * handle cases with a very large number of variables?
74718  */
74719 
74720 DUK_LOCAL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx, duk_regconst_t *out_stmt_value_reg) {
74721 	duk_hthread *thr = comp_ctx->thr;
74722 	duk_hstring *h_name;
74723 	duk_bool_t configurable_bindings;
74724 	duk_uarridx_t num_args;
74725 	duk_uarridx_t num_decls;
74726 	duk_regconst_t rc_name;
74727 	duk_small_uint_t declvar_flags;
74728 	duk_uarridx_t i;
74729 #if defined(DUK_USE_ASSERTIONS)
74730 	duk_idx_t entry_top;
74731 #endif
74732 
74733 #if defined(DUK_USE_ASSERTIONS)
74734 	entry_top = duk_get_top(thr);
74735 #endif
74736 
74737 	/*
74738 	 *  Preliminaries
74739 	 */
74740 
74741 	configurable_bindings = comp_ctx->curr_func.is_eval;
74742 	DUK_DDD(DUK_DDDPRINT("configurable_bindings=%ld", (long) configurable_bindings));
74743 
74744 	/* varmap is already in comp_ctx->curr_func.varmap_idx */
74745 
74746 	/*
74747 	 *  Function formal arguments, always bound to registers
74748 	 *  (there's no support for shuffling them now).
74749 	 */
74750 
74751 	num_args = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.argnames_idx);
74752 	DUK_DDD(DUK_DDDPRINT("num_args=%ld", (long) num_args));
74753 	/* XXX: check num_args */
74754 
74755 	for (i = 0; i < num_args; i++) {
74756 		duk_get_prop_index(thr, comp_ctx->curr_func.argnames_idx, i);
74757 		h_name = duk_known_hstring(thr, -1);
74758 
74759 		if (comp_ctx->curr_func.is_strict) {
74760 			if (duk__hstring_is_eval_or_arguments(comp_ctx, h_name)) {
74761 				DUK_DDD(DUK_DDDPRINT("arg named 'eval' or 'arguments' in strict mode -> SyntaxError"));
74762 				goto error_argname;
74763 			}
74764 			duk_dup_top(thr);
74765 			if (duk_has_prop(thr, comp_ctx->curr_func.varmap_idx)) {
74766 				DUK_DDD(DUK_DDDPRINT("duplicate arg name in strict mode -> SyntaxError"));
74767 				goto error_argname;
74768 			}
74769 
74770 			/* Ensure argument name is not a reserved word in current
74771 			 * (final) strictness.  Formal argument parsing may not
74772 			 * catch reserved names if strictness changes during
74773 			 * parsing.
74774 			 *
74775 			 * We only need to do this in strict mode because non-strict
74776 			 * keyword are always detected in formal argument parsing.
74777 			 */
74778 
74779 			if (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(h_name)) {
74780 				goto error_argname;
74781 			}
74782 		}
74783 
74784 		/* overwrite any previous binding of the same name; the effect is
74785 		 * that last argument of a certain name wins.
74786 		 */
74787 
74788 		/* only functions can have arguments */
74789 		DUK_ASSERT(comp_ctx->curr_func.is_function);
74790 		duk_push_uarridx(thr, i);  /* -> [ ... name index ] */
74791 		duk_put_prop(thr, comp_ctx->curr_func.varmap_idx); /* -> [ ... ] */
74792 
74793 		/* no code needs to be emitted, the regs already have values */
74794 	}
74795 
74796 	/* use temp_next for tracking register allocations */
74797 	DUK__SETTEMP_CHECKMAX(comp_ctx, (duk_regconst_t) num_args);
74798 
74799 	/*
74800 	 *  After arguments, allocate special registers (like shuffling temps)
74801 	 */
74802 
74803 	if (out_stmt_value_reg) {
74804 		*out_stmt_value_reg = DUK__ALLOCTEMP(comp_ctx);
74805 	}
74806 	if (comp_ctx->curr_func.needs_shuffle) {
74807 		duk_regconst_t shuffle_base = DUK__ALLOCTEMPS(comp_ctx, 3);
74808 		comp_ctx->curr_func.shuffle1 = shuffle_base;
74809 		comp_ctx->curr_func.shuffle2 = shuffle_base + 1;
74810 		comp_ctx->curr_func.shuffle3 = shuffle_base + 2;
74811 		DUK_D(DUK_DPRINT("shuffle registers needed by function, allocated: %ld %ld %ld",
74812 		                 (long) comp_ctx->curr_func.shuffle1,
74813 		                 (long) comp_ctx->curr_func.shuffle2,
74814 		                 (long) comp_ctx->curr_func.shuffle3));
74815 	}
74816 	if (comp_ctx->curr_func.temp_next > 0x100) {
74817 		DUK_D(DUK_DPRINT("not enough 8-bit regs: temp_next=%ld", (long) comp_ctx->curr_func.temp_next));
74818 		goto error_outofregs;
74819 	}
74820 
74821 	/*
74822 	 *  Function declarations
74823 	 */
74824 
74825 	num_decls = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.decls_idx);
74826 	DUK_DDD(DUK_DDDPRINT("num_decls=%ld -> %!T",
74827 	                     (long) num_decls,
74828 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.decls_idx)));
74829 	for (i = 0; i < num_decls; i += 2) {
74830 		duk_int_t decl_type;
74831 		duk_int_t fnum;
74832 
74833 		duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i + 1);  /* decl type */
74834 		decl_type = duk_to_int(thr, -1);
74835 		fnum = decl_type >> 8;  /* XXX: macros */
74836 		decl_type = decl_type & 0xff;
74837 		duk_pop(thr);
74838 
74839 		if (decl_type != DUK_DECL_TYPE_FUNC) {
74840 			continue;
74841 		}
74842 
74843 		duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i);  /* decl name */
74844 
74845 		/* XXX: spilling */
74846 		if (comp_ctx->curr_func.is_function) {
74847 			duk_regconst_t reg_bind;
74848 			duk_dup_top(thr);
74849 			if (duk_has_prop(thr, comp_ctx->curr_func.varmap_idx)) {
74850 				/* shadowed; update value */
74851 				duk_dup_top(thr);
74852 				duk_get_prop(thr, comp_ctx->curr_func.varmap_idx);
74853 				reg_bind = duk_to_int(thr, -1);  /* [ ... name reg_bind ] */
74854 				duk__emit_a_bc(comp_ctx,
74855 				               DUK_OP_CLOSURE,
74856 				               reg_bind,
74857 				               (duk_regconst_t) fnum);
74858 			} else {
74859 				/* function: always register bound */
74860 				reg_bind = DUK__ALLOCTEMP(comp_ctx);
74861 				duk__emit_a_bc(comp_ctx,
74862 				               DUK_OP_CLOSURE,
74863 				               reg_bind,
74864 				               (duk_regconst_t) fnum);
74865 				duk_push_int(thr, (duk_int_t) reg_bind);
74866 			}
74867 		} else {
74868 			/* Function declaration for global/eval code is emitted even
74869 			 * for duplicates, because of E5 Section 10.5, step 5.e of
74870 			 * E5.1 (special behavior for variable bound to global object).
74871 			 *
74872 			 * DECLVAR will not re-declare a variable as such, but will
74873 			 * update the binding value.
74874 			 */
74875 
74876 			duk_regconst_t reg_temp = DUK__ALLOCTEMP(comp_ctx);
74877 			duk_dup_top(thr);
74878 			rc_name = duk__getconst(comp_ctx);
74879 			duk_push_null(thr);
74880 
74881 			duk__emit_a_bc(comp_ctx,
74882 			               DUK_OP_CLOSURE,
74883 			               reg_temp,
74884 			               (duk_regconst_t) fnum);
74885 
74886 			declvar_flags = DUK_PROPDESC_FLAG_WRITABLE |
74887 			                DUK_PROPDESC_FLAG_ENUMERABLE |
74888 			                DUK_BC_DECLVAR_FLAG_FUNC_DECL;
74889 
74890 			if (configurable_bindings) {
74891 				declvar_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
74892 			}
74893 
74894 			duk__emit_a_b_c(comp_ctx,
74895 			                DUK_OP_DECLVAR | DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_BC_REGCONST,
74896 			                (duk_regconst_t) declvar_flags /*flags*/,
74897 			                rc_name /*name*/,
74898 			                reg_temp /*value*/);
74899 
74900 			DUK__SETTEMP(comp_ctx, reg_temp);  /* forget temp */
74901 		}
74902 
74903 		DUK_DDD(DUK_DDDPRINT("function declaration to varmap: %!T -> %!T",
74904 		                     (duk_tval *) duk_get_tval(thr, -2),
74905 		                     (duk_tval *) duk_get_tval(thr, -1)));
74906 
74907 #if defined(DUK_USE_FASTINT)
74908 		DUK_ASSERT(DUK_TVAL_IS_NULL(duk_get_tval(thr, -1)) || DUK_TVAL_IS_FASTINT(duk_get_tval(thr, -1)));
74909 #endif
74910 		duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);  /* [ ... name reg/null ] -> [ ... ] */
74911 	}
74912 
74913 	/*
74914 	 *  'arguments' binding is special; if a shadowing argument or
74915 	 *  function declaration exists, an arguments object will
74916 	 *  definitely not be needed, regardless of whether the identifier
74917 	 *  'arguments' is referenced inside the function body.
74918 	 */
74919 
74920 	if (duk_has_prop_stridx(thr, comp_ctx->curr_func.varmap_idx, DUK_STRIDX_LC_ARGUMENTS)) {
74921 		DUK_DDD(DUK_DDDPRINT("'arguments' is shadowed by argument or function declaration "
74922 		                     "-> arguments object creation can be skipped"));
74923 		comp_ctx->curr_func.is_arguments_shadowed = 1;
74924 	}
74925 
74926 	/*
74927 	 *  Variable declarations.
74928 	 *
74929 	 *  Unlike function declarations, variable declaration values don't get
74930 	 *  assigned on entry.  If a binding of the same name already exists, just
74931 	 *  ignore it silently.
74932 	 */
74933 
74934 	for (i = 0; i < num_decls; i += 2) {
74935 		duk_int_t decl_type;
74936 
74937 		duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i + 1);  /* decl type */
74938 		decl_type = duk_to_int(thr, -1);
74939 		decl_type = decl_type & 0xff;
74940 		duk_pop(thr);
74941 
74942 		if (decl_type != DUK_DECL_TYPE_VAR) {
74943 			continue;
74944 		}
74945 
74946 		duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i);  /* decl name */
74947 
74948 		if (duk_has_prop(thr, comp_ctx->curr_func.varmap_idx)) {
74949 			/* shadowed, ignore */
74950 		} else {
74951 			duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i);  /* decl name */
74952 			h_name = duk_known_hstring(thr, -1);
74953 
74954 			if (h_name == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr) &&
74955 			    !comp_ctx->curr_func.is_arguments_shadowed) {
74956 				/* E5 Section steps 7-8 */
74957 				DUK_DDD(DUK_DDDPRINT("'arguments' not shadowed by a function declaration, "
74958 				                     "but appears as a variable declaration -> treat as "
74959 				                     "a no-op for variable declaration purposes"));
74960 				duk_pop(thr);
74961 				continue;
74962 			}
74963 
74964 			/* XXX: spilling */
74965 			if (comp_ctx->curr_func.is_function) {
74966 				duk_regconst_t reg_bind = DUK__ALLOCTEMP(comp_ctx);
74967 				/* no need to init reg, it will be undefined on entry */
74968 				duk_push_int(thr, (duk_int_t) reg_bind);
74969 			} else {
74970 				duk_dup_top(thr);
74971 				rc_name = duk__getconst(comp_ctx);
74972 				duk_push_null(thr);
74973 
74974 				declvar_flags = DUK_PROPDESC_FLAG_WRITABLE |
74975 			                        DUK_PROPDESC_FLAG_ENUMERABLE;
74976 				if (configurable_bindings) {
74977 					declvar_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
74978 				}
74979 
74980 				duk__emit_a_b_c(comp_ctx,
74981 				                DUK_OP_DECLVAR | DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_BC_REGCONST,
74982 				                (duk_regconst_t) declvar_flags /*flags*/,
74983 				                rc_name /*name*/,
74984 				                0 /*value*/);
74985 			}
74986 
74987 			duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);  /* [ ... name reg/null ] -> [ ... ] */
74988 		}
74989 	}
74990 
74991 	/*
74992 	 *  Wrap up
74993 	 */
74994 
74995 	DUK_DDD(DUK_DDDPRINT("varmap: %!T, is_arguments_shadowed=%ld",
74996 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx),
74997 	                     (long) comp_ctx->curr_func.is_arguments_shadowed));
74998 
74999 	DUK_ASSERT_TOP(thr, entry_top);
75000 	return;
75001 
75002  error_outofregs:
75003 	DUK_ERROR_RANGE(thr, DUK_STR_REG_LIMIT);
75004 	DUK_WO_NORETURN(return;);
75005 
75006  error_argname:
75007 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_ARG_NAME);
75008 	DUK_WO_NORETURN(return;);
75009 }
75010 
75011 /*
75012  *  Parse a function-body-like expression (FunctionBody or Program
75013  *  in E5 grammar) using a two-pass parse.  The productions appear
75014  *  in the following contexts:
75015  *
75016  *    - function expression
75017  *    - function statement
75018  *    - function declaration
75019  *    - getter in object literal
75020  *    - setter in object literal
75021  *    - global code
75022  *    - eval code
75023  *    - Function constructor body
75024  *
75025  *  This function only parses the statement list of the body; the argument
75026  *  list and possible function name must be initialized by the caller.
75027  *  For instance, for Function constructor, the argument names are originally
75028  *  on the value stack.  The parsing of statements ends either at an EOF or
75029  *  a closing brace; this is controlled by an input flag.
75030  *
75031  *  Note that there are many differences affecting parsing and even code
75032  *  generation:
75033  *
75034  *    - Global and eval code have an implicit return value generated
75035  *      by the last statement; function code does not
75036  *
75037  *    - Global code, eval code, and Function constructor body end in
75038  *      an EOF, other bodies in a closing brace ('}')
75039  *
75040  *  Upon entry, 'curr_tok' is ignored and the function will pull in the
75041  *  first token on its own.  Upon exit, 'curr_tok' is the terminating
75042  *  token (EOF or closing brace).
75043  */
75044 
75045 DUK_LOCAL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_eof, duk_bool_t implicit_return_value, duk_bool_t regexp_after, duk_small_int_t expect_token) {
75046 	duk_compiler_func *func;
75047 	duk_hthread *thr;
75048 	duk_regconst_t reg_stmt_value = -1;
75049 	duk_lexer_point lex_pt;
75050 	duk_regconst_t temp_first;
75051 	duk_small_int_t compile_round = 1;
75052 
75053 	DUK_ASSERT(comp_ctx != NULL);
75054 
75055 	thr = comp_ctx->thr;
75056 	DUK_ASSERT(thr != NULL);
75057 
75058 	func = &comp_ctx->curr_func;
75059 	DUK_ASSERT(func != NULL);
75060 
75061 	DUK__RECURSION_INCREASE(comp_ctx, thr);
75062 
75063 	duk_require_stack(thr, DUK__FUNCTION_BODY_REQUIRE_SLOTS);
75064 
75065 	/*
75066 	 *  Store lexer position for a later rewind
75067 	 */
75068 
75069 	DUK_LEXER_GETPOINT(&comp_ctx->lex, &lex_pt);
75070 
75071 	/*
75072 	 *  Program code (global and eval code) has an implicit return value
75073 	 *  from the last statement value (e.g. eval("1; 2+3;") returns 3).
75074 	 *  This is not the case with functions.  If implicit statement return
75075 	 *  value is requested, all statements are coerced to a register
75076 	 *  allocated here, and used in the implicit return statement below.
75077 	 */
75078 
75079 	/* XXX: this is pointless here because pass 1 is throw-away */
75080 	if (implicit_return_value) {
75081 		reg_stmt_value = DUK__ALLOCTEMP(comp_ctx);
75082 
75083 		/* If an implicit return value is needed by caller, it must be
75084 		 * initialized to 'undefined' because we don't know whether any
75085 		 * non-empty (where "empty" is a continuation type, and different
75086 		 * from an empty statement) statements will be executed.
75087 		 *
75088 		 * However, since 1st pass is a throwaway one, no need to emit
75089 		 * it here.
75090 		 */
75091 #if 0
75092 		duk__emit_bc(comp_ctx,
75093 		             DUK_OP_LDUNDEF,
75094 		             0);
75095 #endif
75096 	}
75097 
75098 	/*
75099 	 *  First pass.
75100 	 *
75101 	 *  Gather variable/function declarations needed for second pass.
75102 	 *  Code generated is dummy and discarded.
75103 	 */
75104 
75105 	func->in_directive_prologue = 1;
75106 	func->in_scanning = 1;
75107 	func->may_direct_eval = 0;
75108 	func->id_access_arguments = 0;
75109 	func->id_access_slow = 0;
75110 	func->id_access_slow_own = 0;
75111 	func->reg_stmt_value = reg_stmt_value;
75112 #if defined(DUK_USE_DEBUGGER_SUPPORT)
75113 	func->min_line = DUK_INT_MAX;
75114 	func->max_line = 0;
75115 #endif
75116 
75117 	/* duk__parse_stmts() expects curr_tok to be set; parse in "allow
75118 	 * regexp literal" mode with current strictness.
75119 	 */
75120 	if (expect_token >= 0) {
75121 		/* Eating a left curly; regexp mode is allowed by left curly
75122 		 * based on duk__token_lbp[] automatically.
75123 		 */
75124 		DUK_ASSERT(expect_token == DUK_TOK_LCURLY);
75125 		duk__update_lineinfo_currtoken(comp_ctx);
75126 		duk__advance_expect(comp_ctx, expect_token);
75127 	} else {
75128 		/* Need to set curr_token.t because lexing regexp mode depends on current
75129 		 * token type.  Zero value causes "allow regexp" mode.
75130 		 */
75131 		comp_ctx->curr_token.t = 0;
75132 		duk__advance(comp_ctx);
75133 	}
75134 
75135 	DUK_DDD(DUK_DDDPRINT("begin 1st pass"));
75136 	duk__parse_stmts(comp_ctx,
75137 	                 1,             /* allow source elements */
75138 	                 expect_eof,    /* expect EOF instead of } */
75139 	                 regexp_after); /* regexp after */
75140 	DUK_DDD(DUK_DDDPRINT("end 1st pass"));
75141 
75142 	/*
75143 	 *  Second (and possibly third) pass.
75144 	 *
75145 	 *  Generate actual code.  In most cases the need for shuffle
75146 	 *  registers is detected during pass 1, but in some corner cases
75147 	 *  we'll only detect it during pass 2 and a third pass is then
75148 	 *  needed (see GH-115).
75149 	 */
75150 
75151 	for (;;) {
75152 		duk_bool_t needs_shuffle_before = comp_ctx->curr_func.needs_shuffle;
75153 		compile_round++;
75154 
75155 		/*
75156 		 *  Rewind lexer.
75157 		 *
75158 		 *  duk__parse_stmts() expects curr_tok to be set; parse in "allow regexp
75159 		 *  literal" mode with current strictness.
75160 		 *
75161 		 *  curr_token line number info should be initialized for pass 2 before
75162 		 *  generating prologue, to ensure prologue bytecode gets nice line numbers.
75163 		 */
75164 
75165 		DUK_DDD(DUK_DDDPRINT("rewind lexer"));
75166 		DUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);
75167 		comp_ctx->curr_token.t = 0;  /* this is needed for regexp mode */
75168 		comp_ctx->curr_token.start_line = 0;  /* needed for line number tracking (becomes prev_token.start_line) */
75169 		duk__advance(comp_ctx);
75170 
75171 		/*
75172 		 *  Reset function state and perform register allocation, which creates
75173 		 *  'varmap' for second pass.  Function prologue for variable declarations,
75174 		 *  binding value initializations etc is emitted as a by-product.
75175 		 *
75176 		 *  Strict mode restrictions for duplicate and invalid argument
75177 		 *  names are checked here now that we know whether the function
75178 		 *  is actually strict.  See: test-dev-strict-mode-boundary.js.
75179 		 *
75180 		 *  Inner functions are compiled during pass 1 and are not reset.
75181 		 */
75182 
75183 		duk__reset_func_for_pass2(comp_ctx);
75184 		func->in_directive_prologue = 1;
75185 		func->in_scanning = 0;
75186 
75187 		/* must be able to emit code, alloc consts, etc. */
75188 
75189 		duk__init_varmap_and_prologue_for_pass2(comp_ctx,
75190 		                                        (implicit_return_value ? &reg_stmt_value : NULL));
75191 		func->reg_stmt_value = reg_stmt_value;
75192 
75193 		temp_first = DUK__GETTEMP(comp_ctx);
75194 
75195 		func->temp_first = temp_first;
75196 		func->temp_next = temp_first;
75197 		func->stmt_next = 0;
75198 		func->label_next = 0;
75199 
75200 		/* XXX: init or assert catch depth etc -- all values */
75201 		func->id_access_arguments = 0;
75202 		func->id_access_slow = 0;
75203 		func->id_access_slow_own = 0;
75204 
75205 		/*
75206 		 *  Check function name validity now that we know strictness.
75207 		 *  This only applies to function declarations and expressions,
75208 		 *  not setter/getter name.
75209 		 *
75210 		 *  See: test-dev-strict-mode-boundary.js
75211 		 */
75212 
75213 		if (func->is_function && !func->is_setget && func->h_name != NULL) {
75214 			if (func->is_strict) {
75215 				if (duk__hstring_is_eval_or_arguments(comp_ctx, func->h_name)) {
75216 					DUK_DDD(DUK_DDDPRINT("func name is 'eval' or 'arguments' in strict mode"));
75217 					goto error_funcname;
75218 				}
75219 				if (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(func->h_name)) {
75220 					DUK_DDD(DUK_DDDPRINT("func name is a reserved word in strict mode"));
75221 					goto error_funcname;
75222 				}
75223 			} else {
75224 				if (DUK_HSTRING_HAS_RESERVED_WORD(func->h_name) &&
75225 				    !DUK_HSTRING_HAS_STRICT_RESERVED_WORD(func->h_name)) {
75226 					DUK_DDD(DUK_DDDPRINT("func name is a reserved word in non-strict mode"));
75227 					goto error_funcname;
75228 				}
75229 			}
75230 		}
75231 
75232 		/*
75233 		 *  Second pass parsing.
75234 		 */
75235 
75236 		if (implicit_return_value) {
75237 			/* Default implicit return value. */
75238 			duk__emit_bc(comp_ctx,
75239 			             DUK_OP_LDUNDEF,
75240 			             0);
75241 		}
75242 
75243 		DUK_DDD(DUK_DDDPRINT("begin 2nd pass"));
75244 		duk__parse_stmts(comp_ctx,
75245 		                 1,             /* allow source elements */
75246 		                 expect_eof,    /* expect EOF instead of } */
75247 		                 regexp_after); /* regexp after */
75248 		DUK_DDD(DUK_DDDPRINT("end 2nd pass"));
75249 
75250 		duk__update_lineinfo_currtoken(comp_ctx);
75251 
75252 		if (needs_shuffle_before == comp_ctx->curr_func.needs_shuffle) {
75253 			/* Shuffle decision not changed. */
75254 			break;
75255 		}
75256 		if (compile_round >= 3) {
75257 			/* Should never happen but avoid infinite loop just in case. */
75258 			DUK_D(DUK_DPRINT("more than 3 compile passes needed, should never happen"));
75259 			DUK_ERROR_INTERNAL(thr);
75260 			DUK_WO_NORETURN(return;);
75261 		}
75262 		DUK_D(DUK_DPRINT("need additional round to compile function, round now %d", (int) compile_round));
75263 	}
75264 
75265 	/*
75266 	 *  Emit a final RETURN.
75267 	 *
75268 	 *  It would be nice to avoid emitting an unnecessary "return" opcode
75269 	 *  if the current PC is not reachable.  However, this cannot be reliably
75270 	 *  detected; even if the previous instruction is an unconditional jump,
75271 	 *  there may be a previous jump which jumps to current PC (which is the
75272 	 *  case for iteration and conditional statements, for instance).
75273 	 */
75274 
75275 	/* XXX: request a "last statement is terminal" from duk__parse_stmt() and duk__parse_stmts();
75276 	 * we could avoid the last RETURN if we could ensure there is no way to get here
75277 	 * (directly or via a jump)
75278 	 */
75279 
75280 	DUK_ASSERT(comp_ctx->curr_func.catch_depth == 0);
75281 	if (reg_stmt_value >= 0) {
75282 		DUK_ASSERT(DUK__ISREG(reg_stmt_value));
75283 		duk__emit_bc(comp_ctx, DUK_OP_RETREG, reg_stmt_value /*reg*/);
75284 	} else {
75285 		duk__emit_op_only(comp_ctx, DUK_OP_RETUNDEF);
75286 	}
75287 
75288 	/*
75289 	 *  Peephole optimize JUMP chains.
75290 	 */
75291 
75292 	duk__peephole_optimize_bytecode(comp_ctx);
75293 
75294 	/*
75295 	 *  comp_ctx->curr_func is now ready to be converted into an actual
75296 	 *  function template.
75297 	 */
75298 
75299 	DUK__RECURSION_DECREASE(comp_ctx, thr);
75300 	return;
75301 
75302  error_funcname:
75303 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_FUNC_NAME);
75304 	DUK_WO_NORETURN(return;);
75305 }
75306 
75307 /*
75308  *  Parse a function-like expression:
75309  *
75310  *    - function expression
75311  *    - function declaration
75312  *    - function statement (non-standard)
75313  *    - setter/getter
75314  *
75315  *  Adds the function to comp_ctx->curr_func function table and returns the
75316  *  function number.
75317  *
75318  *  On entry, curr_token points to:
75319  *
75320  *    - the token after 'function' for function expression/declaration/statement
75321  *    - the token after 'set' or 'get' for setter/getter
75322  */
75323 
75324 /* Parse formals. */
75325 DUK_LOCAL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx) {
75326 	duk_hthread *thr = comp_ctx->thr;
75327 	duk_bool_t first = 1;
75328 	duk_uarridx_t n;
75329 
75330 	for (;;) {
75331 		if (comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
75332 			break;
75333 		}
75334 
75335 		if (first) {
75336 			/* no comma */
75337 			first = 0;
75338 		} else {
75339 			duk__advance_expect(comp_ctx, DUK_TOK_COMMA);
75340 		}
75341 
75342 		/* Note: when parsing a formal list in non-strict context, e.g.
75343 		 * "implements" is parsed as an identifier.  When the function is
75344 		 * later detected to be strict, the argument list must be rechecked
75345 		 * against a larger set of reserved words (that of strict mode).
75346 		 * This is handled by duk__parse_func_body().  Here we recognize
75347 		 * whatever tokens are considered reserved in current strictness
75348 		 * (which is not always enough).
75349 		 */
75350 
75351 		if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
75352 			DUK_ERROR_SYNTAX(thr, DUK_STR_EXPECTED_IDENTIFIER);
75353 			DUK_WO_NORETURN(return;);
75354 		}
75355 		DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_IDENTIFIER);
75356 		DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
75357 		DUK_DDD(DUK_DDDPRINT("formal argument: %!O",
75358 		                     (duk_heaphdr *) comp_ctx->curr_token.str1));
75359 
75360 		/* XXX: append primitive */
75361 		duk_push_hstring(thr, comp_ctx->curr_token.str1);
75362 		n = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.argnames_idx);
75363 		duk_put_prop_index(thr, comp_ctx->curr_func.argnames_idx, n);
75364 
75365 		duk__advance(comp_ctx);  /* eat identifier */
75366 	}
75367 }
75368 
75369 /* Parse a function-like expression, assuming that 'comp_ctx->curr_func' is
75370  * correctly set up.  Assumes that curr_token is just after 'function' (or
75371  * 'set'/'get' etc).
75372  */
75373 DUK_LOCAL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags) {
75374 	duk_hthread *thr = comp_ctx->thr;
75375 	duk_token *tok;
75376 	duk_bool_t no_advance;
75377 
75378 	DUK_ASSERT(comp_ctx->curr_func.num_formals == 0);
75379 	DUK_ASSERT(comp_ctx->curr_func.is_function == 1);
75380 	DUK_ASSERT(comp_ctx->curr_func.is_eval == 0);
75381 	DUK_ASSERT(comp_ctx->curr_func.is_global == 0);
75382 	DUK_ASSERT(comp_ctx->curr_func.is_setget == ((flags & DUK__FUNC_FLAG_GETSET) != 0));
75383 
75384 	duk__update_lineinfo_currtoken(comp_ctx);
75385 
75386 	/*
75387 	 *  Function name (if any)
75388 	 *
75389 	 *  We don't check for prohibited names here, because we don't
75390 	 *  yet know whether the function will be strict.  Function body
75391 	 *  parsing handles this retroactively.
75392 	 *
75393 	 *  For function expressions and declarations function name must
75394 	 *  be an Identifer (excludes reserved words).  For setter/getter
75395 	 *  it is a PropertyName which allows reserved words and also
75396 	 *  strings and numbers (e.g. "{ get 1() { ... } }").
75397 	 *
75398 	 *  Function parsing may start either from prev_token or curr_token
75399 	 *  (object literal method definition uses prev_token for example).
75400 	 *  This is dealt with for the initial token.
75401 	 */
75402 
75403 	no_advance = (flags & DUK__FUNC_FLAG_USE_PREVTOKEN);
75404 	if (no_advance) {
75405 		tok = &comp_ctx->prev_token;
75406 	} else {
75407 		tok = &comp_ctx->curr_token;
75408 	}
75409 
75410 	if (flags & DUK__FUNC_FLAG_GETSET) {
75411 		/* PropertyName -> IdentifierName | StringLiteral | NumericLiteral */
75412 		if (tok->t_nores == DUK_TOK_IDENTIFIER || tok->t == DUK_TOK_STRING) {
75413 			duk_push_hstring(thr, tok->str1);       /* keep in valstack */
75414 		} else if (tok->t == DUK_TOK_NUMBER) {
75415 			duk_push_number(thr, tok->num);
75416 			duk_to_string(thr, -1);
75417 		} else {
75418 			DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_GETSET_NAME);
75419 			DUK_WO_NORETURN(return;);
75420 		}
75421 		comp_ctx->curr_func.h_name = duk_known_hstring(thr, -1);  /* borrowed reference */
75422 	} else {
75423 		/* Function name is an Identifier (not IdentifierName), but we get
75424 		 * the raw name (not recognizing keywords) here and perform the name
75425 		 * checks only after pass 1.
75426 		 */
75427 		if (tok->t_nores == DUK_TOK_IDENTIFIER) {
75428 			duk_push_hstring(thr, tok->str1);       /* keep in valstack */
75429 			comp_ctx->curr_func.h_name = duk_known_hstring(thr, -1);  /* borrowed reference */
75430 		} else {
75431 			/* valstack will be unbalanced, which is OK */
75432 			DUK_ASSERT((flags & DUK__FUNC_FLAG_GETSET) == 0);
75433 			DUK_ASSERT(comp_ctx->curr_func.h_name == NULL);
75434 			no_advance = 1;
75435 			if (flags & DUK__FUNC_FLAG_DECL) {
75436 				DUK_ERROR_SYNTAX(thr, DUK_STR_FUNC_NAME_REQUIRED);
75437 				DUK_WO_NORETURN(return;);
75438 			}
75439 		}
75440 	}
75441 
75442 	DUK_DD(DUK_DDPRINT("function name: %!O",
75443 	                   (duk_heaphdr *) comp_ctx->curr_func.h_name));
75444 
75445 	if (!no_advance) {
75446 		duk__advance(comp_ctx);
75447 	}
75448 
75449 	/*
75450 	 *  Formal argument list
75451 	 *
75452 	 *  We don't check for prohibited names or for duplicate argument
75453 	 *  names here, becase we don't yet know whether the function will
75454 	 *  be strict.  Function body parsing handles this retroactively.
75455 	 */
75456 
75457 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
75458 
75459 	duk__parse_func_formals(comp_ctx);
75460 
75461 	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RPAREN);
75462 	duk__advance(comp_ctx);
75463 
75464 	/*
75465 	 *  Parse function body
75466 	 */
75467 
75468 	duk__parse_func_body(comp_ctx,
75469 	                     0,   /* expect_eof */
75470 	                     0,   /* implicit_return_value */
75471 	                     flags & DUK__FUNC_FLAG_DECL, /* regexp_after */
75472 	                     DUK_TOK_LCURLY);  /* expect_token */
75473 
75474 	/*
75475 	 *  Convert duk_compiler_func to a function template and add it
75476 	 *  to the parent function table.
75477 	 */
75478 
75479 	duk__convert_to_func_template(comp_ctx);  /* -> [ ... func ] */
75480 }
75481 
75482 /* Parse an inner function, adding the function template to the current function's
75483  * function table.  Return a function number to be used by the outer function.
75484  *
75485  * Avoiding O(depth^2) inner function parsing is handled here.  On the first pass,
75486  * compile and register the function normally into the 'funcs' array, also recording
75487  * a lexer point (offset/line) to the closing brace of the function.  On the second
75488  * pass, skip the function and return the same 'fnum' as on the first pass by using
75489  * a running counter.
75490  *
75491  * An unfortunate side effect of this is that when parsing the inner function, almost
75492  * nothing is known of the outer function, i.e. the inner function's scope.  We don't
75493  * need that information at the moment, but it would allow some optimizations if it
75494  * were used.
75495  */
75496 DUK_LOCAL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags) {
75497 	duk_hthread *thr = comp_ctx->thr;
75498 	duk_compiler_func old_func;
75499 	duk_idx_t entry_top;
75500 	duk_int_t fnum;
75501 
75502 	/*
75503 	 *  On second pass, skip the function.
75504 	 */
75505 
75506 	if (!comp_ctx->curr_func.in_scanning) {
75507 		duk_lexer_point lex_pt;
75508 
75509 		fnum = comp_ctx->curr_func.fnum_next++;
75510 		duk_get_prop_index(thr, comp_ctx->curr_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 1));
75511 		lex_pt.offset = (duk_size_t) duk_to_uint(thr, -1);
75512 		duk_pop(thr);
75513 		duk_get_prop_index(thr, comp_ctx->curr_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 2));
75514 		lex_pt.line = duk_to_int(thr, -1);
75515 		duk_pop(thr);
75516 
75517 		DUK_DDD(DUK_DDDPRINT("second pass of an inner func, skip the function, reparse closing brace; lex offset=%ld, line=%ld",
75518 		                     (long) lex_pt.offset, (long) lex_pt.line));
75519 
75520 		DUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);
75521 		comp_ctx->curr_token.t = 0;  /* this is needed for regexp mode */
75522 		comp_ctx->curr_token.start_line = 0;  /* needed for line number tracking (becomes prev_token.start_line) */
75523 		duk__advance(comp_ctx);
75524 
75525 		/* RegExp is not allowed after a function expression, e.g. in
75526 		 * (function () {} / 123).  A RegExp *is* allowed after a
75527 		 * function declaration!
75528 		 */
75529 		if (flags & DUK__FUNC_FLAG_DECL) {
75530 			comp_ctx->curr_func.allow_regexp_in_adv = 1;
75531 		}
75532 		duk__advance_expect(comp_ctx, DUK_TOK_RCURLY);
75533 
75534 		return fnum;
75535 	}
75536 
75537 	/*
75538 	 *  On first pass, perform actual parsing.  Remember valstack top on entry
75539 	 *  to restore it later, and switch to using a new function in comp_ctx.
75540 	 */
75541 
75542 	entry_top = duk_get_top(thr);
75543 	DUK_DDD(DUK_DDDPRINT("before func: entry_top=%ld, curr_tok.start_offset=%ld",
75544 	                     (long) entry_top, (long) comp_ctx->curr_token.start_offset));
75545 
75546 	duk_memcpy(&old_func, &comp_ctx->curr_func, sizeof(duk_compiler_func));
75547 
75548 	duk_memzero(&comp_ctx->curr_func, sizeof(duk_compiler_func));
75549 	duk__init_func_valstack_slots(comp_ctx);
75550 	DUK_ASSERT(comp_ctx->curr_func.num_formals == 0);
75551 
75552 	/* inherit initial strictness from parent */
75553 	comp_ctx->curr_func.is_strict = old_func.is_strict;
75554 
75555 	/* XXX: It might be better to just store the flags into the curr_func
75556 	 * struct and use them as is without this flag interpretation step
75557 	 * here.
75558 	 */
75559 	DUK_ASSERT(comp_ctx->curr_func.is_notail == 0);
75560 	comp_ctx->curr_func.is_function = 1;
75561 	DUK_ASSERT(comp_ctx->curr_func.is_eval == 0);
75562 	DUK_ASSERT(comp_ctx->curr_func.is_global == 0);
75563 	comp_ctx->curr_func.is_setget = ((flags & DUK__FUNC_FLAG_GETSET) != 0);
75564 	comp_ctx->curr_func.is_namebinding = !(flags & (DUK__FUNC_FLAG_GETSET |
75565 	                                                DUK__FUNC_FLAG_METDEF |
75566 	                                                DUK__FUNC_FLAG_DECL));  /* no name binding for: declarations, objlit getset, objlit method def */
75567 	comp_ctx->curr_func.is_constructable = !(flags & (DUK__FUNC_FLAG_GETSET |
75568 	                                                  DUK__FUNC_FLAG_METDEF));  /* not constructable: objlit getset, objlit method def */
75569 
75570 	/*
75571 	 *  Parse inner function
75572 	 */
75573 
75574 	duk__parse_func_like_raw(comp_ctx, flags);  /* pushes function template */
75575 
75576 	/* prev_token.start_offset points to the closing brace here; when skipping
75577 	 * we're going to reparse the closing brace to ensure semicolon insertion
75578 	 * etc work as expected.
75579 	 */
75580 	DUK_DDD(DUK_DDDPRINT("after func: prev_tok.start_offset=%ld, curr_tok.start_offset=%ld",
75581 	                     (long) comp_ctx->prev_token.start_offset, (long) comp_ctx->curr_token.start_offset));
75582 	DUK_ASSERT(comp_ctx->lex.input[comp_ctx->prev_token.start_offset] == (duk_uint8_t) DUK_ASC_RCURLY);
75583 
75584 	/* XXX: append primitive */
75585 	DUK_ASSERT(duk_get_length(thr, old_func.funcs_idx) == (duk_size_t) (old_func.fnum_next * 3));
75586 	fnum = old_func.fnum_next++;
75587 
75588 	if (fnum > DUK__MAX_FUNCS) {
75589 		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_FUNC_LIMIT);
75590 		DUK_WO_NORETURN(return 0;);
75591 	}
75592 
75593 	/* array writes autoincrement length */
75594 	(void) duk_put_prop_index(thr, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3));
75595 	duk_push_size_t(thr, comp_ctx->prev_token.start_offset);
75596 	(void) duk_put_prop_index(thr, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 1));
75597 	duk_push_int(thr, comp_ctx->prev_token.start_line);
75598 	(void) duk_put_prop_index(thr, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 2));
75599 
75600 	/*
75601 	 *  Cleanup: restore original function, restore valstack state.
75602 	 *
75603 	 *  Function declaration handling needs the function name to be pushed
75604 	 *  on the value stack.
75605 	 */
75606 
75607 	if (flags & DUK__FUNC_FLAG_PUSHNAME_PASS1) {
75608 		DUK_ASSERT(comp_ctx->curr_func.h_name != NULL);
75609 		duk_push_hstring(thr, comp_ctx->curr_func.h_name);
75610 		duk_replace(thr, entry_top);
75611 		duk_set_top(thr, entry_top + 1);
75612 	} else {
75613 		duk_set_top(thr, entry_top);
75614 	}
75615 	duk_memcpy((void *) &comp_ctx->curr_func, (void *) &old_func, sizeof(duk_compiler_func));
75616 
75617 	return fnum;
75618 }
75619 
75620 /*
75621  *  Compile input string into an executable function template without
75622  *  arguments.
75623  *
75624  *  The string is parsed as the "Program" production of ECMAScript E5.
75625  *  Compilation context can be either global code or eval code (see E5
75626  *  Sections 14 and 15.1.2.1).
75627  *
75628  *  Input stack:  [ ... filename ]
75629  *  Output stack: [ ... func_template ]
75630  */
75631 
75632 /* XXX: source code property */
75633 
75634 DUK_LOCAL duk_ret_t duk__js_compile_raw(duk_hthread *thr, void *udata) {
75635 	duk_hstring *h_filename;
75636 	duk__compiler_stkstate *comp_stk;
75637 	duk_compiler_ctx *comp_ctx;
75638 	duk_lexer_point *lex_pt;
75639 	duk_compiler_func *func;
75640 	duk_idx_t entry_top;
75641 	duk_bool_t is_strict;
75642 	duk_bool_t is_eval;
75643 	duk_bool_t is_funcexpr;
75644 	duk_small_uint_t flags;
75645 
75646 	DUK_ASSERT(thr != NULL);
75647 	DUK_ASSERT(udata != NULL);
75648 
75649 	/*
75650 	 *  Arguments check
75651 	 */
75652 
75653 	entry_top = duk_get_top(thr);
75654 	DUK_ASSERT(entry_top >= 1);
75655 
75656 	comp_stk = (duk__compiler_stkstate *) udata;
75657 	comp_ctx = &comp_stk->comp_ctx_alloc;
75658 	lex_pt = &comp_stk->lex_pt_alloc;
75659 	DUK_ASSERT(comp_ctx != NULL);
75660 	DUK_ASSERT(lex_pt != NULL);
75661 
75662 	flags = comp_stk->flags;
75663 	is_eval = (flags & DUK_COMPILE_EVAL ? 1 : 0);
75664 	is_strict = (flags & DUK_COMPILE_STRICT ? 1 : 0);
75665 	is_funcexpr = (flags & DUK_COMPILE_FUNCEXPR ? 1 : 0);
75666 
75667 	h_filename = duk_get_hstring(thr, -1);  /* may be undefined */
75668 
75669 	/*
75670 	 *  Init compiler and lexer contexts
75671 	 */
75672 
75673 	func = &comp_ctx->curr_func;
75674 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
75675 	comp_ctx->thr = NULL;
75676 	comp_ctx->h_filename = NULL;
75677 	comp_ctx->prev_token.str1 = NULL;
75678 	comp_ctx->prev_token.str2 = NULL;
75679 	comp_ctx->curr_token.str1 = NULL;
75680 	comp_ctx->curr_token.str2 = NULL;
75681 #endif
75682 
75683 	duk_require_stack(thr, DUK__COMPILE_ENTRY_SLOTS);
75684 
75685 	duk_push_dynamic_buffer(thr, 0);       /* entry_top + 0 */
75686 	duk_push_undefined(thr);               /* entry_top + 1 */
75687 	duk_push_undefined(thr);               /* entry_top + 2 */
75688 	duk_push_undefined(thr);               /* entry_top + 3 */
75689 	duk_push_undefined(thr);               /* entry_top + 4 */
75690 
75691 	comp_ctx->thr = thr;
75692 	comp_ctx->h_filename = h_filename;
75693 	comp_ctx->tok11_idx = entry_top + 1;
75694 	comp_ctx->tok12_idx = entry_top + 2;
75695 	comp_ctx->tok21_idx = entry_top + 3;
75696 	comp_ctx->tok22_idx = entry_top + 4;
75697 	comp_ctx->recursion_limit = DUK_USE_COMPILER_RECLIMIT;
75698 
75699 	/* comp_ctx->lex has been pre-initialized by caller: it has been
75700 	 * zeroed and input/input_length has been set.
75701 	 */
75702 	comp_ctx->lex.thr = thr;
75703 	/* comp_ctx->lex.input and comp_ctx->lex.input_length filled by caller */
75704 	comp_ctx->lex.slot1_idx = comp_ctx->tok11_idx;
75705 	comp_ctx->lex.slot2_idx = comp_ctx->tok12_idx;
75706 	comp_ctx->lex.buf_idx = entry_top + 0;
75707 	comp_ctx->lex.buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, entry_top + 0);
75708 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(comp_ctx->lex.buf) && !DUK_HBUFFER_HAS_EXTERNAL(comp_ctx->lex.buf));
75709 	comp_ctx->lex.token_limit = DUK_COMPILER_TOKEN_LIMIT;
75710 
75711 	lex_pt->offset = 0;
75712 	lex_pt->line = 1;
75713 	DUK_LEXER_SETPOINT(&comp_ctx->lex, lex_pt);    /* fills window */
75714 	comp_ctx->curr_token.start_line = 0;  /* needed for line number tracking (becomes prev_token.start_line) */
75715 
75716 	/*
75717 	 *  Initialize function state for a zero-argument function
75718 	 */
75719 
75720 	duk__init_func_valstack_slots(comp_ctx);
75721 	DUK_ASSERT(func->num_formals == 0);
75722 
75723 	if (is_funcexpr) {
75724 		/* Name will be filled from function expression, not by caller.
75725 		 * This case is used by Function constructor and duk_compile()
75726 		 * API with the DUK_COMPILE_FUNCTION option.
75727 		 */
75728 		DUK_ASSERT(func->h_name == NULL);
75729 	} else {
75730 		duk_push_hstring_stridx(thr, (is_eval ? DUK_STRIDX_EVAL :
75731 		                                        DUK_STRIDX_GLOBAL));
75732 		func->h_name = duk_get_hstring(thr, -1);
75733 	}
75734 
75735 	/*
75736 	 *  Parse a function body or a function-like expression, depending
75737 	 *  on flags.
75738 	 */
75739 
75740 	DUK_ASSERT(func->is_setget == 0);
75741 	func->is_strict = (duk_uint8_t) is_strict;
75742 	DUK_ASSERT(func->is_notail == 0);
75743 
75744 	if (is_funcexpr) {
75745 		func->is_function = 1;
75746 		DUK_ASSERT(func->is_eval == 0);
75747 		DUK_ASSERT(func->is_global == 0);
75748 		func->is_namebinding = 1;
75749 		func->is_constructable = 1;
75750 
75751 		duk__advance(comp_ctx);  /* init 'curr_token' */
75752 		duk__advance_expect(comp_ctx, DUK_TOK_FUNCTION);
75753 		(void) duk__parse_func_like_raw(comp_ctx, 0 /*flags*/);
75754 	} else {
75755 		DUK_ASSERT(func->is_function == 0);
75756 		DUK_ASSERT(is_eval == 0 || is_eval == 1);
75757 		func->is_eval = (duk_uint8_t) is_eval;
75758 		func->is_global = (duk_uint8_t) !is_eval;
75759 		DUK_ASSERT(func->is_namebinding == 0);
75760 		DUK_ASSERT(func->is_constructable == 0);
75761 
75762 		duk__parse_func_body(comp_ctx,
75763 		                     1,             /* expect_eof */
75764 		                     1,             /* implicit_return_value */
75765 		                     1,             /* regexp_after (does not matter) */
75766 		                     -1);           /* expect_token */
75767 	}
75768 
75769 	/*
75770 	 *  Convert duk_compiler_func to a function template
75771 	 */
75772 
75773 	duk__convert_to_func_template(comp_ctx);
75774 
75775 	/*
75776 	 *  Wrapping duk_safe_call() will mangle the stack, just return stack top
75777 	 */
75778 
75779 	/* [ ... filename (temps) func ] */
75780 
75781 	return 1;
75782 }
75783 
75784 DUK_INTERNAL void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer, duk_size_t src_length, duk_small_uint_t flags) {
75785 	duk__compiler_stkstate comp_stk;
75786 	duk_compiler_ctx *prev_ctx;
75787 	duk_ret_t safe_rc;
75788 
75789 	DUK_ASSERT(thr != NULL);
75790 	DUK_ASSERT(src_buffer != NULL);
75791 
75792 	/* preinitialize lexer state partially */
75793 	duk_memzero(&comp_stk, sizeof(comp_stk));
75794 	comp_stk.flags = flags;
75795 	DUK_LEXER_INITCTX(&comp_stk.comp_ctx_alloc.lex);
75796 	comp_stk.comp_ctx_alloc.lex.input = src_buffer;
75797 	comp_stk.comp_ctx_alloc.lex.input_length = src_length;
75798 	comp_stk.comp_ctx_alloc.lex.flags = flags;  /* Forward flags directly for now. */
75799 
75800 	/* [ ... filename ] */
75801 
75802 	prev_ctx = thr->compile_ctx;
75803 	thr->compile_ctx = &comp_stk.comp_ctx_alloc;  /* for duk_error_augment.c */
75804 	safe_rc = duk_safe_call(thr, duk__js_compile_raw, (void *) &comp_stk /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
75805 	thr->compile_ctx = prev_ctx;  /* must restore reliably before returning */
75806 
75807 	if (safe_rc != DUK_EXEC_SUCCESS) {
75808 		DUK_D(DUK_DPRINT("compilation failed: %!T", duk_get_tval(thr, -1)));
75809 		(void) duk_throw(thr);
75810 		DUK_WO_NORETURN(return;);
75811 	}
75812 
75813 	/* [ ... template ] */
75814 }
75815 
75816 /* automatic undefs */
75817 #undef DUK__ALLOCTEMP
75818 #undef DUK__ALLOCTEMPS
75819 #undef DUK__ALLOW_AUTO_SEMI_ALWAYS
75820 #undef DUK__BC_INITIAL_INSTS
75821 #undef DUK__BP_ADDITIVE
75822 #undef DUK__BP_ASSIGNMENT
75823 #undef DUK__BP_BAND
75824 #undef DUK__BP_BOR
75825 #undef DUK__BP_BXOR
75826 #undef DUK__BP_CALL
75827 #undef DUK__BP_CLOSING
75828 #undef DUK__BP_COMMA
75829 #undef DUK__BP_CONDITIONAL
75830 #undef DUK__BP_EOF
75831 #undef DUK__BP_EQUALITY
75832 #undef DUK__BP_EXPONENTIATION
75833 #undef DUK__BP_FOR_EXPR
75834 #undef DUK__BP_INVALID
75835 #undef DUK__BP_LAND
75836 #undef DUK__BP_LOR
75837 #undef DUK__BP_MEMBER
75838 #undef DUK__BP_MULTIPLICATIVE
75839 #undef DUK__BP_POSTFIX
75840 #undef DUK__BP_RELATIONAL
75841 #undef DUK__BP_SHIFT
75842 #undef DUK__COMPILE_ENTRY_SLOTS
75843 #undef DUK__CONST_MARKER
75844 #undef DUK__DUMP_ISPEC
75845 #undef DUK__DUMP_IVALUE
75846 #undef DUK__EMIT_FLAG_A_IS_SOURCE
75847 #undef DUK__EMIT_FLAG_BC_REGCONST
75848 #undef DUK__EMIT_FLAG_B_IS_TARGET
75849 #undef DUK__EMIT_FLAG_C_IS_TARGET
75850 #undef DUK__EMIT_FLAG_NO_SHUFFLE_A
75851 #undef DUK__EMIT_FLAG_NO_SHUFFLE_B
75852 #undef DUK__EMIT_FLAG_NO_SHUFFLE_C
75853 #undef DUK__EMIT_FLAG_RESERVE_JUMPSLOT
75854 #undef DUK__EXPR_FLAG_ALLOW_EMPTY
75855 #undef DUK__EXPR_FLAG_REJECT_IN
75856 #undef DUK__EXPR_FLAG_REQUIRE_INIT
75857 #undef DUK__EXPR_RBP_MASK
75858 #undef DUK__FUNCTION_BODY_REQUIRE_SLOTS
75859 #undef DUK__FUNCTION_INIT_REQUIRE_SLOTS
75860 #undef DUK__FUNC_FLAG_DECL
75861 #undef DUK__FUNC_FLAG_GETSET
75862 #undef DUK__FUNC_FLAG_METDEF
75863 #undef DUK__FUNC_FLAG_PUSHNAME_PASS1
75864 #undef DUK__FUNC_FLAG_USE_PREVTOKEN
75865 #undef DUK__GETCONST_MAX_CONSTS_CHECK
75866 #undef DUK__GETTEMP
75867 #undef DUK__HAS_TERM
75868 #undef DUK__HAS_VAL
75869 #undef DUK__ISCONST
75870 #undef DUK__ISREG
75871 #undef DUK__ISREG_NOTTEMP
75872 #undef DUK__ISREG_TEMP
75873 #undef DUK__IS_TERMINAL
75874 #undef DUK__IVAL_FLAG_ALLOW_CONST
75875 #undef DUK__IVAL_FLAG_REQUIRE_SHORT
75876 #undef DUK__IVAL_FLAG_REQUIRE_TEMP
75877 #undef DUK__MAX_ARRAY_INIT_VALUES
75878 #undef DUK__MAX_CONSTS
75879 #undef DUK__MAX_FUNCS
75880 #undef DUK__MAX_OBJECT_INIT_PAIRS
75881 #undef DUK__MAX_TEMPS
75882 #undef DUK__MK_LBP
75883 #undef DUK__MK_LBP_FLAGS
75884 #undef DUK__OBJ_LIT_KEY_GET
75885 #undef DUK__OBJ_LIT_KEY_PLAIN
75886 #undef DUK__OBJ_LIT_KEY_SET
75887 #undef DUK__PARSE_EXPR_SLOTS
75888 #undef DUK__PARSE_STATEMENTS_SLOTS
75889 #undef DUK__RECURSION_DECREASE
75890 #undef DUK__RECURSION_INCREASE
75891 #undef DUK__REMOVECONST
75892 #undef DUK__SETTEMP
75893 #undef DUK__SETTEMP_CHECKMAX
75894 #undef DUK__STILL_PROLOGUE
75895 #undef DUK__TOKEN_LBP_BP_MASK
75896 #undef DUK__TOKEN_LBP_FLAG_NO_REGEXP
75897 #undef DUK__TOKEN_LBP_FLAG_TERMINATES
75898 #undef DUK__TOKEN_LBP_FLAG_UNUSED
75899 #undef DUK__TOKEN_LBP_GET_BP
75900 /*
75901  *  ECMAScript bytecode executor.
75902  */
75903 
75904 /* #include duk_internal.h -> already included */
75905 
75906 /*
75907  *  Local declarations.
75908  */
75909 
75910 DUK_LOCAL_DECL void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, duk_activation *entry_act);
75911 
75912 /*
75913  *  Misc helpers.
75914  */
75915 
75916 /* Replace value stack top to value at 'tv_ptr'.  Optimize for
75917  * performance by only applying the net refcount change.
75918  */
75919 #define DUK__REPLACE_TO_TVPTR(thr,tv_ptr) do { \
75920 		duk_hthread *duk__thr; \
75921 		duk_tval *duk__tvsrc; \
75922 		duk_tval *duk__tvdst; \
75923 		duk_tval duk__tvtmp; \
75924 		duk__thr = (thr); \
75925 		duk__tvsrc = DUK_GET_TVAL_NEGIDX(duk__thr, -1); \
75926 		duk__tvdst = (tv_ptr); \
75927 		DUK_TVAL_SET_TVAL(&duk__tvtmp, duk__tvdst); \
75928 		DUK_TVAL_SET_TVAL(duk__tvdst, duk__tvsrc); \
75929 		DUK_TVAL_SET_UNDEFINED(duk__tvsrc);  /* value stack init policy */ \
75930 		duk__thr->valstack_top = duk__tvsrc; \
75931 		DUK_TVAL_DECREF(duk__thr, &duk__tvtmp); \
75932 	} while (0)
75933 
75934 /* XXX: candidate of being an internal shared API call */
75935 #if 0  /* unused */
75936 DUK_LOCAL void duk__push_tvals_incref_only(duk_hthread *thr, duk_tval *tv_src, duk_small_uint_fast_t count) {
75937 	duk_tval *tv_dst;
75938 	duk_size_t copy_size;
75939 	duk_size_t i;
75940 
75941 	tv_dst = thr->valstack_top;
75942 	copy_size = sizeof(duk_tval) * count;
75943 	duk_memcpy((void *) tv_dst, (const void *) tv_src, copy_size);
75944 	for (i = 0; i < count; i++) {
75945 		DUK_TVAL_INCREF(thr, tv_dst);
75946 		tv_dst++;
75947 	}
75948 	thr->valstack_top = tv_dst;
75949 }
75950 #endif
75951 
75952 /*
75953  *  Arithmetic, binary, and logical helpers.
75954  *
75955  *  Note: there is no opcode for logical AND or logical OR; this is on
75956  *  purpose, because the evalution order semantics for them make such
75957  *  opcodes pretty pointless: short circuiting means they are most
75958  *  comfortably implemented as jumps.  However, a logical NOT opcode
75959  *  is useful.
75960  *
75961  *  Note: careful with duk_tval pointers here: they are potentially
75962  *  invalidated by any DECREF and almost any API call.  It's still
75963  *  preferable to work without making a copy but that's not always
75964  *  possible.
75965  */
75966 
75967 DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF duk_double_t duk__compute_mod(duk_double_t d1, duk_double_t d2) {
75968 	return (duk_double_t) duk_js_arith_mod((double) d1, (double) d2);
75969 }
75970 
75971 #if defined(DUK_USE_ES7_EXP_OPERATOR)
75972 DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF duk_double_t duk__compute_exp(duk_double_t d1, duk_double_t d2) {
75973 	return (duk_double_t) duk_js_arith_pow((double) d1, (double) d2);
75974 }
75975 #endif
75976 
75977 DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_arith_add(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_fast_t idx_z) {
75978 	/*
75979 	 *  Addition operator is different from other arithmetic
75980 	 *  operations in that it also provides string concatenation.
75981 	 *  Hence it is implemented separately.
75982 	 *
75983 	 *  There is a fast path for number addition.  Other cases go
75984 	 *  through potentially multiple coercions as described in the
75985 	 *  E5 specification.  It may be possible to reduce the number
75986 	 *  of coercions, but this must be done carefully to preserve
75987 	 *  the exact semantics.
75988 	 *
75989 	 *  E5 Section 11.6.1.
75990 	 *
75991 	 *  Custom types also have special behavior implemented here.
75992 	 */
75993 
75994 	duk_double_union du;
75995 
75996 	DUK_ASSERT(thr != NULL);
75997 	DUK_ASSERT(tv_x != NULL);  /* may be reg or const */
75998 	DUK_ASSERT(tv_y != NULL);  /* may be reg or const */
75999 	DUK_ASSERT_DISABLE(idx_z >= 0);  /* unsigned */
76000 	DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(thr));
76001 
76002 	/*
76003 	 *  Fast paths
76004 	 */
76005 
76006 #if defined(DUK_USE_FASTINT)
76007 	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
76008 		duk_int64_t v1, v2, v3;
76009 		duk_int32_t v3_hi;
76010 		duk_tval *tv_z;
76011 
76012 		/* Input values are signed 48-bit so we can detect overflow
76013 		 * reliably from high bits or just a comparison.
76014 		 */
76015 
76016 		v1 = DUK_TVAL_GET_FASTINT(tv_x);
76017 		v2 = DUK_TVAL_GET_FASTINT(tv_y);
76018 		v3 = v1 + v2;
76019 		v3_hi = (duk_int32_t) (v3 >> 32);
76020 		if (DUK_LIKELY(v3_hi >= DUK_I64_CONSTANT(-0x8000) && v3_hi <= DUK_I64_CONSTANT(0x7fff))) {
76021 			tv_z = thr->valstack_bottom + idx_z;
76022 			DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3);  /* side effects */
76023 			return;
76024 		} else {
76025 			/* overflow, fall through */
76026 			;
76027 		}
76028 	}
76029 #endif  /* DUK_USE_FASTINT */
76030 
76031 	if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
76032 #if !defined(DUK_USE_EXEC_PREFER_SIZE)
76033 		duk_tval *tv_z;
76034 #endif
76035 
76036 		du.d = DUK_TVAL_GET_NUMBER(tv_x) + DUK_TVAL_GET_NUMBER(tv_y);
76037 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76038 		duk_push_number(thr, du.d);  /* will NaN normalize result */
76039 		duk_replace(thr, (duk_idx_t) idx_z);
76040 #else  /* DUK_USE_EXEC_PREFER_SIZE */
76041 		DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
76042 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
76043 		tv_z = thr->valstack_bottom + idx_z;
76044 		DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d);  /* side effects */
76045 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
76046 		return;
76047 	}
76048 
76049 	/*
76050 	 *  Slow path: potentially requires function calls for coercion
76051 	 */
76052 
76053 	duk_push_tval(thr, tv_x);
76054 	duk_push_tval(thr, tv_y);
76055 	duk_to_primitive(thr, -2, DUK_HINT_NONE);  /* side effects -> don't use tv_x, tv_y after */
76056 	duk_to_primitive(thr, -1, DUK_HINT_NONE);
76057 
76058 	/* Since Duktape 2.x plain buffers are treated like ArrayBuffer. */
76059 	if (duk_is_string(thr, -2) || duk_is_string(thr, -1)) {
76060 		/* Symbols shouldn't technically be handled here, but should
76061 		 * go into the default ToNumber() coercion path instead and
76062 		 * fail there with a TypeError.  However, there's a ToString()
76063 		 * in duk_concat_2() which also fails with TypeError so no
76064 		 * explicit check is needed.
76065 		 */
76066 		duk_concat_2(thr);  /* [... s1 s2] -> [... s1+s2] */
76067 	} else {
76068 		duk_double_t d1, d2;
76069 
76070 		d1 = duk_to_number_m2(thr);
76071 		d2 = duk_to_number_m1(thr);
76072 		DUK_ASSERT(duk_is_number(thr, -2));
76073 		DUK_ASSERT(duk_is_number(thr, -1));
76074 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d1);
76075 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d2);
76076 
76077 		du.d = d1 + d2;
76078 		duk_pop_2_unsafe(thr);
76079 		duk_push_number(thr, du.d);  /* will NaN normalize result */
76080 	}
76081 	duk_replace(thr, (duk_idx_t) idx_z);  /* side effects */
76082 }
76083 
76084 DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_arith_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_uint_fast_t idx_z, duk_small_uint_fast_t opcode) {
76085 	/*
76086 	 *  Arithmetic operations other than '+' have number-only semantics
76087 	 *  and are implemented here.  The separate switch-case here means a
76088 	 *  "double dispatch" of the arithmetic opcode, but saves code space.
76089 	 *
76090 	 *  E5 Sections 11.5, 11.5.1, 11.5.2, 11.5.3, 11.6, 11.6.1, 11.6.2, 11.6.3.
76091 	 */
76092 
76093 	duk_double_t d1, d2;
76094 	duk_double_union du;
76095 	duk_small_uint_fast_t opcode_shifted;
76096 #if defined(DUK_USE_FASTINT) || !defined(DUK_USE_EXEC_PREFER_SIZE)
76097 	duk_tval *tv_z;
76098 #endif
76099 
76100 	DUK_ASSERT(thr != NULL);
76101 	DUK_ASSERT(tv_x != NULL);  /* may be reg or const */
76102 	DUK_ASSERT(tv_y != NULL);  /* may be reg or const */
76103 	DUK_ASSERT_DISABLE(idx_z >= 0);  /* unsigned */
76104 	DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(thr));
76105 
76106 	opcode_shifted = opcode >> 2;  /* Get base opcode without reg/const modifiers. */
76107 
76108 #if defined(DUK_USE_FASTINT)
76109 	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
76110 		duk_int64_t v1, v2, v3;
76111 		duk_int32_t v3_hi;
76112 
76113 		v1 = DUK_TVAL_GET_FASTINT(tv_x);
76114 		v2 = DUK_TVAL_GET_FASTINT(tv_y);
76115 
76116 		switch (opcode_shifted) {
76117 		case DUK_OP_SUB >> 2: {
76118 			v3 = v1 - v2;
76119 			break;
76120 		}
76121 		case DUK_OP_MUL >> 2: {
76122 			/* Must ensure result is 64-bit (no overflow); a
76123 			 * simple and sufficient fast path is to allow only
76124 			 * 32-bit inputs.  Avoid zero inputs to avoid
76125 			 * negative zero issues (-1 * 0 = -0, for instance).
76126 			 */
76127 			if (v1 >= DUK_I64_CONSTANT(-0x80000000) && v1 <= DUK_I64_CONSTANT(0x7fffffff) && v1 != 0 &&
76128 			    v2 >= DUK_I64_CONSTANT(-0x80000000) && v2 <= DUK_I64_CONSTANT(0x7fffffff) && v2 != 0) {
76129 				v3 = v1 * v2;
76130 			} else {
76131 				goto skip_fastint;
76132 			}
76133 			break;
76134 		}
76135 		case DUK_OP_DIV >> 2: {
76136 			/* Don't allow a zero divisor.  Fast path check by
76137 			 * "verifying" with multiplication.  Also avoid zero
76138 			 * dividend to avoid negative zero issues (0 / -1 = -0
76139 			 * for instance).
76140 			 */
76141 			if (v1 == 0 || v2 == 0) {
76142 				goto skip_fastint;
76143 			}
76144 			v3 = v1 / v2;
76145 			if (v3 * v2 != v1) {
76146 				goto skip_fastint;
76147 			}
76148 			break;
76149 		}
76150 		case DUK_OP_MOD >> 2: {
76151 			/* Don't allow a zero divisor.  Restrict both v1 and
76152 			 * v2 to positive values to avoid compiler specific
76153 			 * behavior.
76154 			 */
76155 			if (v1 < 1 || v2 < 1) {
76156 				goto skip_fastint;
76157 			}
76158 			v3 = v1 % v2;
76159 			DUK_ASSERT(v3 >= 0);
76160 			DUK_ASSERT(v3 < v2);
76161 			DUK_ASSERT(v1 - (v1 / v2) * v2 == v3);
76162 			break;
76163 		}
76164 		default: {
76165 			/* Possible with DUK_OP_EXP. */
76166 			goto skip_fastint;
76167 		}
76168 		}
76169 
76170 		v3_hi = (duk_int32_t) (v3 >> 32);
76171 		if (DUK_LIKELY(v3_hi >= DUK_I64_CONSTANT(-0x8000) && v3_hi <= DUK_I64_CONSTANT(0x7fff))) {
76172 			tv_z = thr->valstack_bottom + idx_z;
76173 			DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3);  /* side effects */
76174 			return;
76175 		}
76176 		/* fall through if overflow etc */
76177 	}
76178  skip_fastint:
76179 #endif  /* DUK_USE_FASTINT */
76180 
76181 	if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
76182 		/* fast path */
76183 		d1 = DUK_TVAL_GET_NUMBER(tv_x);
76184 		d2 = DUK_TVAL_GET_NUMBER(tv_y);
76185 	} else {
76186 		duk_push_tval(thr, tv_x);
76187 		duk_push_tval(thr, tv_y);
76188 		d1 = duk_to_number_m2(thr);  /* side effects */
76189 		d2 = duk_to_number_m1(thr);
76190 		DUK_ASSERT(duk_is_number(thr, -2));
76191 		DUK_ASSERT(duk_is_number(thr, -1));
76192 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d1);
76193 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d2);
76194 		duk_pop_2_unsafe(thr);
76195 	}
76196 
76197 	switch (opcode_shifted) {
76198 	case DUK_OP_SUB >> 2: {
76199 		du.d = d1 - d2;
76200 		break;
76201 	}
76202 	case DUK_OP_MUL >> 2: {
76203 		du.d = d1 * d2;
76204 		break;
76205 	}
76206 	case DUK_OP_DIV >> 2: {
76207 		/* Division-by-zero is undefined behavior, so
76208 		 * rely on a helper.
76209 		 */
76210 		du.d = duk_double_div(d1, d2);
76211 		break;
76212 	}
76213 	case DUK_OP_MOD >> 2: {
76214 		du.d = duk__compute_mod(d1, d2);
76215 		break;
76216 	}
76217 #if defined(DUK_USE_ES7_EXP_OPERATOR)
76218 	case DUK_OP_EXP >> 2: {
76219 		du.d = duk__compute_exp(d1, d2);
76220 		break;
76221 	}
76222 #endif
76223 	default: {
76224 		DUK_UNREACHABLE();
76225 		du.d = DUK_DOUBLE_NAN;  /* should not happen */
76226 		break;
76227 	}
76228 	}
76229 
76230 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76231 	duk_push_number(thr, du.d);  /* will NaN normalize result */
76232 	duk_replace(thr, (duk_idx_t) idx_z);
76233 #else  /* DUK_USE_EXEC_PREFER_SIZE */
76234 	/* important to use normalized NaN with 8-byte tagged types */
76235 	DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
76236 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
76237 	tv_z = thr->valstack_bottom + idx_z;
76238 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d);  /* side effects */
76239 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
76240 }
76241 
76242 DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_bitwise_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_fast_t idx_z, duk_small_uint_fast_t opcode) {
76243 	/*
76244 	 *  Binary bitwise operations use different coercions (ToInt32, ToUint32)
76245 	 *  depending on the operation.  We coerce the arguments first using
76246 	 *  ToInt32(), and then cast to an 32-bit value if necessary.  Note that
76247 	 *  such casts must be correct even if there is no native 32-bit type
76248 	 *  (e.g., duk_int32_t and duk_uint32_t are 64-bit).
76249 	 *
76250 	 *  E5 Sections 11.10, 11.7.1, 11.7.2, 11.7.3
76251 	 */
76252 
76253 	duk_int32_t i1, i2, i3;
76254 	duk_uint32_t u1, u2, u3;
76255 #if defined(DUK_USE_FASTINT)
76256 	duk_int64_t fi3;
76257 #else
76258 	duk_double_t d3;
76259 #endif
76260 	duk_small_uint_fast_t opcode_shifted;
76261 #if defined(DUK_USE_FASTINT) || !defined(DUK_USE_EXEC_PREFER_SIZE)
76262 	duk_tval *tv_z;
76263 #endif
76264 
76265 	DUK_ASSERT(thr != NULL);
76266 	DUK_ASSERT(tv_x != NULL);  /* may be reg or const */
76267 	DUK_ASSERT(tv_y != NULL);  /* may be reg or const */
76268 	DUK_ASSERT_DISABLE(idx_z >= 0);  /* unsigned */
76269 	DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(thr));
76270 
76271 	opcode_shifted = opcode >> 2;  /* Get base opcode without reg/const modifiers. */
76272 
76273 #if defined(DUK_USE_FASTINT)
76274 	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
76275 		i1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_x);
76276 		i2 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_y);
76277 	}
76278 	else
76279 #endif  /* DUK_USE_FASTINT */
76280 	{
76281 		duk_push_tval(thr, tv_x);
76282 		duk_push_tval(thr, tv_y);
76283 		i1 = duk_to_int32(thr, -2);
76284 		i2 = duk_to_int32(thr, -1);
76285 		duk_pop_2_unsafe(thr);
76286 	}
76287 
76288 	switch (opcode_shifted) {
76289 	case DUK_OP_BAND >> 2: {
76290 		i3 = i1 & i2;
76291 		break;
76292 	}
76293 	case DUK_OP_BOR >> 2: {
76294 		i3 = i1 | i2;
76295 		break;
76296 	}
76297 	case DUK_OP_BXOR >> 2: {
76298 		i3 = i1 ^ i2;
76299 		break;
76300 	}
76301 	case DUK_OP_BASL >> 2: {
76302 		/* Signed shift, named "arithmetic" (asl) because the result
76303 		 * is signed, e.g. 4294967295 << 1 -> -2.  Note that result
76304 		 * must be masked.
76305 		 */
76306 
76307 		u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
76308 		i3 = (duk_int32_t) (((duk_uint32_t) i1) << (u2 & 0x1fUL));  /* E5 Section 11.7.1, steps 7 and 8 */
76309 		i3 = i3 & ((duk_int32_t) 0xffffffffUL);                     /* Note: left shift, should mask */
76310 		break;
76311 	}
76312 	case DUK_OP_BASR >> 2: {
76313 		/* signed shift */
76314 
76315 		u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
76316 		i3 = i1 >> (u2 & 0x1fUL);                      /* E5 Section 11.7.2, steps 7 and 8 */
76317 		break;
76318 	}
76319 	case DUK_OP_BLSR >> 2: {
76320 		/* unsigned shift */
76321 
76322 		u1 = ((duk_uint32_t) i1) & 0xffffffffUL;
76323 		u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
76324 
76325 		/* special result value handling */
76326 		u3 = u1 >> (u2 & 0x1fUL);     /* E5 Section 11.7.2, steps 7 and 8 */
76327 #if defined(DUK_USE_FASTINT)
76328 		fi3 = (duk_int64_t) u3;
76329 		goto fastint_result_set;
76330 #else
76331 		d3 = (duk_double_t) u3;
76332 		goto result_set;
76333 #endif
76334 	}
76335 	default: {
76336 		DUK_UNREACHABLE();
76337 		i3 = 0;  /* should not happen */
76338 		break;
76339 	}
76340 	}
76341 
76342 #if defined(DUK_USE_FASTINT)
76343 	/* Result is always fastint compatible. */
76344 	/* XXX: Set 32-bit result (but must then handle signed and
76345 	 * unsigned results separately).
76346 	 */
76347 	fi3 = (duk_int64_t) i3;
76348 
76349  fastint_result_set:
76350 	tv_z = thr->valstack_bottom + idx_z;
76351 	DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, fi3);  /* side effects */
76352 #else  /* DUK_USE_FASTINT */
76353 	d3 = (duk_double_t) i3;
76354 
76355  result_set:
76356 	DUK_ASSERT(!DUK_ISNAN(d3));            /* 'd3' is never NaN, so no need to normalize */
76357 	DUK_ASSERT_DOUBLE_IS_NORMALIZED(d3);   /* always normalized */
76358 
76359 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76360 	duk_push_number(thr, d3);  /* would NaN normalize result, but unnecessary */
76361 	duk_replace(thr, (duk_idx_t) idx_z);
76362 #else  /* DUK_USE_EXEC_PREFER_SIZE */
76363 	tv_z = thr->valstack_bottom + idx_z;
76364 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, d3);  /* side effects */
76365 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
76366 #endif  /* DUK_USE_FASTINT */
76367 }
76368 
76369 /* In-place unary operation. */
76370 DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_arith_unary_op(duk_hthread *thr, duk_uint_fast_t idx_src, duk_uint_fast_t idx_dst, duk_small_uint_fast_t opcode) {
76371 	/*
76372 	 *  Arithmetic operations other than '+' have number-only semantics
76373 	 *  and are implemented here.  The separate switch-case here means a
76374 	 *  "double dispatch" of the arithmetic opcode, but saves code space.
76375 	 *
76376 	 *  E5 Sections 11.5, 11.5.1, 11.5.2, 11.5.3, 11.6, 11.6.1, 11.6.2, 11.6.3.
76377 	 */
76378 
76379 	duk_tval *tv;
76380 	duk_double_t d1;
76381 	duk_double_union du;
76382 
76383 	DUK_ASSERT(thr != NULL);
76384 	DUK_ASSERT(opcode == DUK_OP_UNM || opcode == DUK_OP_UNP);
76385 	DUK_ASSERT_DISABLE(idx_src >= 0);
76386 	DUK_ASSERT_DISABLE(idx_dst >= 0);
76387 
76388 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_src);
76389 
76390 #if defined(DUK_USE_FASTINT)
76391 	if (DUK_TVAL_IS_FASTINT(tv)) {
76392 		duk_int64_t v1, v2;
76393 
76394 		v1 = DUK_TVAL_GET_FASTINT(tv);
76395 		if (opcode == DUK_OP_UNM) {
76396 			/* The smallest fastint is no longer 48-bit when
76397 			 * negated.  Positive zero becames negative zero
76398 			 * (cannot be represented) when negated.
76399 			 */
76400 			if (DUK_LIKELY(v1 != DUK_FASTINT_MIN && v1 != 0)) {
76401 				v2 = -v1;
76402 				tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
76403 				DUK_TVAL_SET_FASTINT_UPDREF(thr, tv, v2);
76404 				return;
76405 			}
76406 		} else {
76407 			/* ToNumber() for a fastint is a no-op. */
76408 			DUK_ASSERT(opcode == DUK_OP_UNP);
76409 			v2 = v1;
76410 			tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
76411 			DUK_TVAL_SET_FASTINT_UPDREF(thr, tv, v2);
76412 			return;
76413 		}
76414 		/* fall through if overflow etc */
76415 	}
76416 #endif  /* DUK_USE_FASTINT */
76417 
76418 	if (DUK_TVAL_IS_NUMBER(tv)) {
76419 		d1 = DUK_TVAL_GET_NUMBER(tv);
76420 	} else {
76421 		d1 = duk_to_number_tval(thr, tv);  /* side effects */
76422 	}
76423 
76424 	if (opcode == DUK_OP_UNP) {
76425 		/* ToNumber() for a double is a no-op, but unary plus is
76426 		 * used to force a fastint check so do that here.
76427 		 */
76428 		du.d = d1;
76429 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
76430 #if defined(DUK_USE_FASTINT)
76431 		tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
76432 		DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF(thr, tv, du.d);  /* always 'fast', i.e. inlined */
76433 		return;
76434 #endif
76435 	} else {
76436 		DUK_ASSERT(opcode == DUK_OP_UNM);
76437 		du.d = -d1;
76438 		DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);  /* mandatory if du.d is a NaN */
76439 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
76440 	}
76441 
76442 	/* XXX: size optimize: push+replace? */
76443 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
76444 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, du.d);
76445 }
76446 
76447 DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_bitwise_not(duk_hthread *thr, duk_uint_fast_t idx_src, duk_uint_fast_t idx_dst) {
76448 	/*
76449 	 *  E5 Section 11.4.8
76450 	 */
76451 
76452 	duk_tval *tv;
76453 	duk_int32_t i1, i2;
76454 
76455 	DUK_ASSERT(thr != NULL);
76456 	DUK_ASSERT_DISABLE(idx_src >= 0);
76457 	DUK_ASSERT_DISABLE(idx_dst >= 0);
76458 	DUK_ASSERT((duk_uint_t) idx_src < (duk_uint_t) duk_get_top(thr));
76459 	DUK_ASSERT((duk_uint_t) idx_dst < (duk_uint_t) duk_get_top(thr));
76460 
76461 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_src);
76462 
76463 #if defined(DUK_USE_FASTINT)
76464 	if (DUK_TVAL_IS_FASTINT(tv)) {
76465 		i1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv);
76466 	}
76467 	else
76468 #endif  /* DUK_USE_FASTINT */
76469 	{
76470 		duk_push_tval(thr, tv);
76471 		i1 = duk_to_int32(thr, -1);  /* side effects */
76472 		duk_pop_unsafe(thr);
76473 	}
76474 
76475 	/* Result is always fastint compatible. */
76476 	i2 = ~i1;
76477 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
76478 	DUK_TVAL_SET_I32_UPDREF(thr, tv, i2);  /* side effects */
76479 }
76480 
76481 DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_logical_not(duk_hthread *thr, duk_uint_fast_t idx_src, duk_uint_fast_t idx_dst) {
76482 	/*
76483 	 *  E5 Section 11.4.9
76484 	 */
76485 
76486 	duk_tval *tv;
76487 	duk_bool_t res;
76488 
76489 	DUK_ASSERT(thr != NULL);
76490 	DUK_ASSERT_DISABLE(idx_src >= 0);
76491 	DUK_ASSERT_DISABLE(idx_dst >= 0);
76492 	DUK_ASSERT((duk_uint_t) idx_src < (duk_uint_t) duk_get_top(thr));
76493 	DUK_ASSERT((duk_uint_t) idx_dst < (duk_uint_t) duk_get_top(thr));
76494 
76495 	/* ToBoolean() does not require any operations with side effects so
76496 	 * we can do it efficiently.  For footprint it would be better to use
76497 	 * duk_js_toboolean() and then push+replace to the result slot.
76498 	 */
76499 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_src);
76500 	res = duk_js_toboolean(tv);  /* does not modify 'tv' */
76501 	DUK_ASSERT(res == 0 || res == 1);
76502 	res ^= 1;
76503 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
76504 	/* XXX: size optimize: push+replace? */
76505 	DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv, res);  /* side effects */
76506 }
76507 
76508 /* XXX: size optimized variant */
76509 DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__prepost_incdec_reg_helper(duk_hthread *thr, duk_tval *tv_dst, duk_tval *tv_src, duk_small_uint_t op) {
76510 	duk_double_t x, y, z;
76511 
76512 	/* Two lowest bits of opcode are used to distinguish
76513 	 * variants.  Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
76514 	 */
76515 	DUK_ASSERT((DUK_OP_PREINCR & 0x03) == 0x00);
76516 	DUK_ASSERT((DUK_OP_PREDECR & 0x03) == 0x01);
76517 	DUK_ASSERT((DUK_OP_POSTINCR & 0x03) == 0x02);
76518 	DUK_ASSERT((DUK_OP_POSTDECR & 0x03) == 0x03);
76519 
76520 #if defined(DUK_USE_FASTINT)
76521 	if (DUK_TVAL_IS_FASTINT(tv_src)) {
76522 		duk_int64_t x_fi, y_fi, z_fi;
76523 		x_fi = DUK_TVAL_GET_FASTINT(tv_src);
76524 		if (op & 0x01) {
76525 			if (DUK_UNLIKELY(x_fi == DUK_FASTINT_MIN)) {
76526 				goto skip_fastint;
76527 			}
76528 			y_fi = x_fi - 1;
76529 		} else {
76530 			if (DUK_UNLIKELY(x_fi == DUK_FASTINT_MAX)) {
76531 				goto skip_fastint;
76532 			}
76533 			y_fi = x_fi + 1;
76534 		}
76535 
76536 		DUK_TVAL_SET_FASTINT(tv_src, y_fi);  /* no need for refcount update */
76537 
76538 		z_fi = (op & 0x02) ? x_fi : y_fi;
76539 		DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_dst, z_fi);  /* side effects */
76540 		return;
76541 	}
76542  skip_fastint:
76543 #endif
76544 	if (DUK_TVAL_IS_NUMBER(tv_src)) {
76545 		/* Fast path for the case where the register
76546 		 * is a number (e.g. loop counter).
76547 		 */
76548 
76549 		x = DUK_TVAL_GET_NUMBER(tv_src);
76550 		if (op & 0x01) {
76551 			y = x - 1.0;
76552 		} else {
76553 			y = x + 1.0;
76554 		}
76555 
76556 		DUK_TVAL_SET_NUMBER(tv_src, y);  /* no need for refcount update */
76557 	} else {
76558 		/* Preserve duk_tval pointer(s) across a potential valstack
76559 		 * resize by converting them into offsets temporarily.
76560 		 */
76561 		duk_idx_t bc;
76562 		duk_size_t off_dst;
76563 
76564 		off_dst = (duk_size_t) ((duk_uint8_t *) tv_dst - (duk_uint8_t *) thr->valstack_bottom);
76565 		bc = (duk_idx_t) (tv_src - thr->valstack_bottom);  /* XXX: pass index explicitly? */
76566 		tv_src = NULL;  /* no longer referenced */
76567 
76568 		x = duk_to_number(thr, bc);
76569 		if (op & 0x01) {
76570 			y = x - 1.0;
76571 		} else {
76572 			y = x + 1.0;
76573 		}
76574 
76575 		duk_push_number(thr, y);
76576 		duk_replace(thr, bc);
76577 
76578 		tv_dst = (duk_tval *) (void *) (((duk_uint8_t *) thr->valstack_bottom) + off_dst);
76579 	}
76580 
76581 	z = (op & 0x02) ? x : y;
76582 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_dst, z);  /* side effects */
76583 }
76584 
76585 DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__prepost_incdec_var_helper(duk_hthread *thr, duk_small_uint_t idx_dst, duk_tval *tv_id, duk_small_uint_t op, duk_small_uint_t is_strict) {
76586 	duk_activation *act;
76587 	duk_double_t x, y;
76588 	duk_hstring *name;
76589 
76590 	/* XXX: The pre/post inc/dec for an identifier lookup is
76591 	 * missing the important fast path where the identifier
76592 	 * has a storage location e.g. in a scope object so that
76593 	 * it can be updated in-place.  In particular, the case
76594 	 * where the identifier has a storage location AND the
76595 	 * previous value is a number should be optimized because
76596 	 * it's side effect free.
76597 	 */
76598 
76599 	/* Two lowest bits of opcode are used to distinguish
76600 	 * variants.  Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
76601 	 */
76602 	DUK_ASSERT((DUK_OP_PREINCV & 0x03) == 0x00);
76603 	DUK_ASSERT((DUK_OP_PREDECV & 0x03) == 0x01);
76604 	DUK_ASSERT((DUK_OP_POSTINCV & 0x03) == 0x02);
76605 	DUK_ASSERT((DUK_OP_POSTDECV & 0x03) == 0x03);
76606 
76607 	DUK_ASSERT(DUK_TVAL_IS_STRING(tv_id));
76608 	name = DUK_TVAL_GET_STRING(tv_id);
76609 	DUK_ASSERT(name != NULL);
76610 	act = thr->callstack_curr;
76611 	(void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/);  /* -> [ ... val this ] */
76612 
76613 	/* XXX: Fastint fast path would be useful here.  Also fastints
76614 	 * now lose their fastint status in current handling which is
76615 	 * not intuitive.
76616 	 */
76617 
76618 	x = duk_to_number_m2(thr);
76619 	if (op & 0x01) {
76620 		y = x - 1.0;
76621 	} else {
76622 		y = x + 1.0;
76623 	}
76624 
76625 	/* [... x this] */
76626 
76627 	if (op & 0x02) {
76628 		duk_push_number(thr, y);  /* -> [ ... x this y ] */
76629 		DUK_ASSERT(act == thr->callstack_curr);
76630 		duk_js_putvar_activation(thr, act, name, DUK_GET_TVAL_NEGIDX(thr, -1), is_strict);
76631 		duk_pop_2_unsafe(thr);  /* -> [ ... x ] */
76632 	} else {
76633 		duk_pop_2_unsafe(thr);  /* -> [ ... ] */
76634 		duk_push_number(thr, y);  /* -> [ ... y ] */
76635 		DUK_ASSERT(act == thr->callstack_curr);
76636 		duk_js_putvar_activation(thr, act, name, DUK_GET_TVAL_NEGIDX(thr, -1), is_strict);
76637 	}
76638 
76639 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76640 	duk_replace(thr, (duk_idx_t) idx_dst);
76641 #else  /* DUK_USE_EXEC_PREFER_SIZE */
76642 	DUK__REPLACE_TO_TVPTR(thr, DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst));
76643 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
76644 }
76645 
76646 /*
76647  *  Longjmp and other control flow transfer for the bytecode executor.
76648  *
76649  *  The longjmp handler can handle all longjmp types: error, yield, and
76650  *  resume (pseudotypes are never actually thrown).
76651  *
76652  *  Error policy for longjmp: should not ordinarily throw errors; if errors
76653  *  occur (e.g. due to out-of-memory) they bubble outwards rather than being
76654  *  handled recursively.
76655  */
76656 
76657 #define DUK__LONGJMP_RESTART   0  /* state updated, restart bytecode execution */
76658 #define DUK__LONGJMP_RETHROW   1  /* exit bytecode executor by rethrowing an error to caller */
76659 
76660 #define DUK__RETHAND_RESTART   0  /* state updated, restart bytecode execution */
76661 #define DUK__RETHAND_FINISHED  1  /* exit bytecode execution with return value */
76662 
76663 /* XXX: optimize reconfig valstack operations so that resize, clamp, and setting
76664  * top are combined into one pass.
76665  */
76666 
76667 /* Reconfigure value stack for return to an ECMAScript function at
76668  * callstack top (caller unwinds).
76669  */
76670 DUK_LOCAL void duk__reconfig_valstack_ecma_return(duk_hthread *thr) {
76671 	duk_activation *act;
76672 	duk_hcompfunc *h_func;
76673 	duk_idx_t clamp_top;
76674 
76675 	DUK_ASSERT(thr != NULL);
76676 	act = thr->callstack_curr;
76677 	DUK_ASSERT(act != NULL);
76678 	DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
76679 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(act)));
76680 
76681 	/* Clamp so that values at 'clamp_top' and above are wiped and won't
76682 	 * retain reachable garbage.  Then extend to 'nregs' because we're
76683 	 * returning to an ECMAScript function.
76684 	 */
76685 
76686 	h_func = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
76687 
76688 	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->bottom_byteoff);
76689 	DUK_ASSERT(act->retval_byteoff >= act->bottom_byteoff);
76690 	clamp_top = (duk_idx_t) ((act->retval_byteoff - act->bottom_byteoff + sizeof(duk_tval)) / sizeof(duk_tval));  /* +1 = one retval */
76691 	duk_set_top_and_wipe(thr, h_func->nregs, clamp_top);
76692 
76693 	DUK_ASSERT((duk_uint8_t *) thr->valstack_end >= (duk_uint8_t *) thr->valstack + act->reserve_byteoff);
76694 	thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->reserve_byteoff);
76695 
76696 	/* XXX: a best effort shrink check would be OK here */
76697 }
76698 
76699 /* Reconfigure value stack for an ECMAScript catcher.  Use topmost catcher
76700  * in 'act'.
76701  */
76702 DUK_LOCAL void duk__reconfig_valstack_ecma_catcher(duk_hthread *thr, duk_activation *act) {
76703 	duk_catcher *cat;
76704 	duk_hcompfunc *h_func;
76705 	duk_size_t idx_bottom;
76706 	duk_idx_t clamp_top;
76707 
76708 	DUK_ASSERT(thr != NULL);
76709 	DUK_ASSERT(act != NULL);
76710 	DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
76711 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(act)));
76712 	cat = act->cat;
76713 	DUK_ASSERT(cat != NULL);
76714 
76715 	h_func = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
76716 
76717 	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->bottom_byteoff);
76718 	idx_bottom = (duk_size_t) (thr->valstack_bottom - thr->valstack);
76719 	DUK_ASSERT(cat->idx_base >= idx_bottom);
76720 	clamp_top = (duk_idx_t) (cat->idx_base - idx_bottom + 2);  /* +2 = catcher value, catcher lj_type */
76721 	duk_set_top_and_wipe(thr, h_func->nregs, clamp_top);
76722 
76723 	DUK_ASSERT((duk_uint8_t *) thr->valstack_end >= (duk_uint8_t *) thr->valstack + act->reserve_byteoff);
76724 	thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->reserve_byteoff);
76725 
76726 	/* XXX: a best effort shrink check would be OK here */
76727 }
76728 
76729 /* Set catcher regs: idx_base+0 = value, idx_base+1 = lj_type.
76730  * No side effects.
76731  */
76732 DUK_LOCAL void duk__set_catcher_regs_norz(duk_hthread *thr, duk_catcher *cat, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {
76733 	duk_tval *tv1;
76734 
76735 	DUK_ASSERT(thr != NULL);
76736 	DUK_ASSERT(tv_val_unstable != NULL);
76737 
76738 	tv1 = thr->valstack + cat->idx_base;
76739 	DUK_ASSERT(tv1 < thr->valstack_top);
76740 	DUK_TVAL_SET_TVAL_UPDREF_NORZ(thr, tv1, tv_val_unstable);
76741 
76742 	tv1++;
76743 	DUK_ASSERT(tv1 == thr->valstack + cat->idx_base + 1);
76744 	DUK_ASSERT(tv1 < thr->valstack_top);
76745 	DUK_TVAL_SET_U32_UPDREF_NORZ(thr, tv1, (duk_uint32_t) lj_type);
76746 }
76747 
76748 DUK_LOCAL void duk__handle_catch_part1(duk_hthread *thr, duk_tval *tv_val_unstable, duk_small_uint_t lj_type, volatile duk_bool_t *out_delayed_catch_setup) {
76749 	duk_activation *act;
76750 	duk_catcher *cat;
76751 
76752 	DUK_ASSERT(thr != NULL);
76753 	DUK_ASSERT(tv_val_unstable != NULL);
76754 
76755 	act = thr->callstack_curr;
76756 	DUK_ASSERT(act != NULL);
76757 	DUK_DD(DUK_DDPRINT("handle catch, part 1; act=%!A, cat=%!C", act, act->cat));
76758 
76759 	DUK_ASSERT(act->cat != NULL);
76760 	DUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_TCF);
76761 
76762 	/* The part1/part2 split could also be made here at the very top
76763 	 * of catch handling.  Value stack would be reconfigured inside
76764 	 * part2's protection.  Value stack reconfiguration should be free
76765 	 * of allocs, however.
76766 	 */
76767 
76768 	duk__set_catcher_regs_norz(thr, act->cat, tv_val_unstable, lj_type);
76769 
76770 	DUK_ASSERT(thr->callstack_top >= 1);
76771 	DUK_ASSERT(thr->callstack_curr != NULL);
76772 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);
76773 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
76774 
76775 	DUK_ASSERT(thr->callstack_top >= 1);
76776 	DUK_ASSERT(act == thr->callstack_curr);
76777 	DUK_ASSERT(act != NULL);
76778 	duk__reconfig_valstack_ecma_catcher(thr, act);
76779 
76780 	DUK_ASSERT(thr->callstack_top >= 1);
76781 	DUK_ASSERT(act == thr->callstack_curr);
76782 	DUK_ASSERT(act != NULL);
76783 	cat = act->cat;
76784 	DUK_ASSERT(cat != NULL);
76785 
76786 	act->curr_pc = cat->pc_base + 0;  /* +0 = catch */
76787 
76788 	/*
76789 	 *  If the catch block has an automatic catch variable binding,
76790 	 *  we need to create a lexical environment for it which requires
76791 	 *  allocations.  Move out of "error handling state" before the
76792 	 *  allocations to avoid e.g. out-of-memory errors (leading to
76793 	 *  GH-2022 or similar).
76794 	 */
76795 
76796 	if (DUK_CAT_HAS_CATCH_BINDING_ENABLED(cat)) {
76797 		DUK_DDD(DUK_DDDPRINT("catcher has an automatic catch binding, handle in part 2"));
76798 		*out_delayed_catch_setup = 1;
76799 	} else {
76800 		DUK_DDD(DUK_DDDPRINT("catcher has no catch binding"));
76801 	}
76802 
76803 	DUK_CAT_CLEAR_CATCH_ENABLED(cat);
76804 }
76805 
76806 DUK_LOCAL void duk__handle_catch_part2(duk_hthread *thr) {
76807 	duk_activation *act;
76808 	duk_catcher *cat;
76809 	duk_hdecenv *new_env;
76810 
76811 	DUK_ASSERT(thr != NULL);
76812 
76813 	act = thr->callstack_curr;
76814 	DUK_ASSERT(act != NULL);
76815 	DUK_DD(DUK_DDPRINT("handle catch, part 2; act=%!A, cat=%!C", act, act->cat));
76816 
76817 	DUK_ASSERT(act->cat != NULL);
76818 	cat = act->cat;
76819 	DUK_ASSERT(cat != NULL);
76820 	DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF);
76821 	DUK_ASSERT(DUK_CAT_HAS_CATCH_BINDING_ENABLED(cat));
76822 	DUK_ASSERT(thr->valstack + cat->idx_base < thr->valstack_top);
76823 
76824 	/*
76825 	 *  Create lexical environment for the catch clause, containing
76826 	 *  a binding for the caught value.
76827 	 *
76828 	 *  The binding is mutable (= writable) but not deletable.
76829 	 *  Step 4 for the catch production in E5 Section 12.14;
76830 	 *  no value is given for CreateMutableBinding 'D' argument,
76831 	 *  which implies the binding is not deletable.
76832 	 */
76833 
76834 	if (act->lex_env == NULL) {
76835 		DUK_ASSERT(act->var_env == NULL);
76836 		DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
76837 
76838 		duk_js_init_activation_environment_records_delayed(thr, act);
76839 		DUK_ASSERT(act == thr->callstack_curr);
76840 		DUK_ASSERT(act != NULL);
76841 	}
76842 	DUK_ASSERT(act->lex_env != NULL);
76843 	DUK_ASSERT(act->var_env != NULL);
76844 	DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
76845 
76846 	new_env = duk_hdecenv_alloc(thr,
76847 	                            DUK_HOBJECT_FLAG_EXTENSIBLE |
76848 	                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
76849 	DUK_ASSERT(new_env != NULL);
76850 	duk_push_hobject(thr, (duk_hobject *) new_env);
76851 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
76852 	DUK_DDD(DUK_DDDPRINT("new_env allocated: %!iO", (duk_heaphdr *) new_env));
76853 
76854 	/* Note: currently the catch binding is handled without a register
76855 	 * binding because we don't support dynamic register bindings (they
76856 	 * must be fixed for an entire function).  So, there is no need to
76857 	 * record regbases etc.
76858 	 */
76859 
76860 	/* [ ...env ] */
76861 
76862 	DUK_ASSERT(cat->h_varname != NULL);
76863 	duk_push_hstring(thr, cat->h_varname);
76864 	DUK_ASSERT(thr->valstack + cat->idx_base < thr->valstack_top);
76865 	duk_push_tval(thr, thr->valstack + cat->idx_base);
76866 	duk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_W);  /* writable, not configurable */
76867 
76868 	/* [ ... env ] */
76869 
76870 	DUK_ASSERT(act == thr->callstack_curr);
76871 	DUK_ASSERT(act != NULL);
76872 	DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, act->lex_env);
76873 	act->lex_env = (duk_hobject *) new_env;
76874 	DUK_HOBJECT_INCREF(thr, (duk_hobject *) new_env);  /* reachable through activation */
76875 	/* Net refcount change to act->lex_env is 0: incref for new_env's
76876 	 * prototype, decref for act->lex_env overwrite.
76877 	 */
76878 
76879 	DUK_CAT_SET_LEXENV_ACTIVE(cat);
76880 
76881 	duk_pop_unsafe(thr);
76882 
76883 	DUK_DDD(DUK_DDDPRINT("new_env finished: %!iO", (duk_heaphdr *) new_env));
76884 }
76885 
76886 DUK_LOCAL void duk__handle_finally(duk_hthread *thr, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {
76887 	duk_activation *act;
76888 	duk_catcher *cat;
76889 
76890 	DUK_ASSERT(thr != NULL);
76891 	DUK_ASSERT(tv_val_unstable != NULL);
76892 
76893 	act = thr->callstack_curr;
76894 	DUK_ASSERT(act != NULL);
76895 	DUK_ASSERT(act->cat != NULL);
76896 	DUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_TCF);
76897 
76898 	duk__set_catcher_regs_norz(thr, act->cat, tv_val_unstable, lj_type);
76899 
76900 	DUK_ASSERT(thr->callstack_top >= 1);
76901 	DUK_ASSERT(thr->callstack_curr != NULL);
76902 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);
76903 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
76904 
76905 	DUK_ASSERT(thr->callstack_top >= 1);
76906 	DUK_ASSERT(act == thr->callstack_curr);
76907 	DUK_ASSERT(act != NULL);
76908 	duk__reconfig_valstack_ecma_catcher(thr, act);
76909 
76910 	DUK_ASSERT(thr->callstack_top >= 1);
76911 	DUK_ASSERT(act == thr->callstack_curr);
76912 	DUK_ASSERT(act != NULL);
76913 	cat = act->cat;
76914 	DUK_ASSERT(cat != NULL);
76915 
76916 	act->curr_pc = cat->pc_base + 1;  /* +1 = finally */
76917 
76918 	DUK_CAT_CLEAR_FINALLY_ENABLED(cat);
76919 }
76920 
76921 DUK_LOCAL void duk__handle_label(duk_hthread *thr, duk_small_uint_t lj_type) {
76922 	duk_activation *act;
76923 	duk_catcher *cat;
76924 
76925 	DUK_ASSERT(thr != NULL);
76926 
76927 	DUK_ASSERT(thr->callstack_top >= 1);
76928 	act = thr->callstack_curr;
76929 	DUK_ASSERT(act != NULL);
76930 	DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
76931 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(DUK_ACT_GET_FUNC(act)));
76932 
76933 	/* +0 = break, +1 = continue */
76934 	cat = act->cat;
76935 	DUK_ASSERT(cat != NULL);
76936 	DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_LABEL);
76937 
76938 	act->curr_pc = cat->pc_base + (lj_type == DUK_LJ_TYPE_CONTINUE ? 1 : 0);
76939 
76940 	/* valstack should not need changes */
76941 #if defined(DUK_USE_ASSERTIONS)
76942 	DUK_ASSERT(thr->callstack_top >= 1);
76943 	DUK_ASSERT(act == thr->callstack_curr);
76944 	DUK_ASSERT(act != NULL);
76945 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) ==
76946 	           (duk_size_t) ((duk_hcompfunc *) DUK_ACT_GET_FUNC(act))->nregs);
76947 #endif
76948 }
76949 
76950 /* Called for handling both a longjmp() with type DUK_LJ_TYPE_YIELD and
76951  * when a RETURN opcode terminates a thread and yields to the resumer.
76952  * Caller unwinds so that top of callstack is the activation we return to.
76953  */
76954 #if defined(DUK_USE_COROUTINE_SUPPORT)
76955 DUK_LOCAL void duk__handle_yield(duk_hthread *thr, duk_hthread *resumer, duk_tval *tv_val_unstable) {
76956 	duk_activation *act_resumer;
76957 	duk_tval *tv1;
76958 
76959 	DUK_ASSERT(thr != NULL);
76960 	DUK_ASSERT(resumer != NULL);
76961 	DUK_ASSERT(tv_val_unstable != NULL);
76962 	act_resumer = resumer->callstack_curr;
76963 	DUK_ASSERT(act_resumer != NULL);
76964 	DUK_ASSERT(DUK_ACT_GET_FUNC(act_resumer) != NULL);
76965 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(act_resumer)));  /* resume caller must be an ECMAScript func */
76966 
76967 	tv1 = (duk_tval *) (void *) ((duk_uint8_t *) resumer->valstack + act_resumer->retval_byteoff);  /* return value from Duktape.Thread.resume() */
76968 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv_val_unstable);  /* side effects */  /* XXX: avoid side effects */
76969 
76970 	duk__reconfig_valstack_ecma_return(resumer);
76971 
76972 	/* caller must change active thread, and set thr->resumer to NULL */
76973 }
76974 #endif  /* DUK_USE_COROUTINE_SUPPORT */
76975 
76976 DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation *entry_act, volatile duk_bool_t *out_delayed_catch_setup) {
76977 	duk_small_uint_t retval = DUK__LONGJMP_RESTART;
76978 
76979 	DUK_ASSERT(thr != NULL);
76980 	DUK_ASSERT(entry_act != NULL);
76981 
76982 	/* 'thr' is the current thread, as no-one resumes except us and we
76983 	 * switch 'thr' in that case.
76984 	 */
76985 	DUK_ASSERT(thr == thr->heap->curr_thread);
76986 
76987 	/*
76988 	 *  (Re)try handling the longjmp.
76989 	 *
76990 	 *  A longjmp handler may convert the longjmp to a different type and
76991 	 *  "virtually" rethrow by goto'ing to 'check_longjmp'.  Before the goto,
76992 	 *  the following must be updated:
76993 	 *    - the heap 'lj' state
76994 	 *    - 'thr' must reflect the "throwing" thread
76995 	 */
76996 
76997  check_longjmp:
76998 
76999 	DUK_DD(DUK_DDPRINT("handling longjmp: type=%ld, value1=%!T, value2=%!T, iserror=%ld, top=%ld",
77000 	                   (long) thr->heap->lj.type,
77001 	                   (duk_tval *) &thr->heap->lj.value1,
77002 	                   (duk_tval *) &thr->heap->lj.value2,
77003 	                   (long) thr->heap->lj.iserror,
77004 			   (long) duk_get_top(thr)));
77005 
77006 	switch (thr->heap->lj.type) {
77007 
77008 #if defined(DUK_USE_COROUTINE_SUPPORT)
77009 	case DUK_LJ_TYPE_RESUME: {
77010 		/*
77011 		 *  Note: lj.value1 is 'value', lj.value2 is 'resumee'.
77012 		 *  This differs from YIELD.
77013 		 */
77014 
77015 		duk_tval *tv;
77016 		duk_tval *tv2;
77017 		duk_hthread *resumee;
77018 
77019 		/* duk_bi_duk_object_yield() and duk_bi_duk_object_resume() ensure all of these are met */
77020 
77021 		DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);                                                         /* unchanged by Duktape.Thread.resume() */
77022 		DUK_ASSERT(thr->callstack_top >= 2);                                                                         /* ECMAScript activation + Duktape.Thread.resume() activation */
77023 		DUK_ASSERT(thr->callstack_curr != NULL);
77024 		DUK_ASSERT(thr->callstack_curr->parent != NULL);
77025 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL &&
77026 		           DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)) &&
77027 		           ((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->callstack_curr))->func == duk_bi_thread_resume);
77028 
77029 		tv = &thr->heap->lj.value2;  /* resumee */
77030 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
77031 		DUK_ASSERT(DUK_TVAL_GET_OBJECT(tv) != NULL);
77032 		DUK_ASSERT(DUK_HOBJECT_IS_THREAD(DUK_TVAL_GET_OBJECT(tv)));
77033 		resumee = (duk_hthread *) DUK_TVAL_GET_OBJECT(tv);
77034 
77035 		DUK_ASSERT(resumee != NULL);
77036 		DUK_ASSERT(resumee->resumer == NULL);
77037 		DUK_ASSERT(resumee->state == DUK_HTHREAD_STATE_INACTIVE ||
77038 		           resumee->state == DUK_HTHREAD_STATE_YIELDED);                                                     /* checked by Duktape.Thread.resume() */
77039 		DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_YIELDED ||
77040 		           resumee->callstack_top >= 2);                                                                     /* YIELDED: ECMAScript activation + Duktape.Thread.yield() activation */
77041 		DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_YIELDED ||
77042 		           (DUK_ACT_GET_FUNC(resumee->callstack_curr) != NULL &&
77043 		            DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(resumee->callstack_curr)) &&
77044 		            ((duk_hnatfunc *) DUK_ACT_GET_FUNC(resumee->callstack_curr))->func == duk_bi_thread_yield));
77045 		DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_INACTIVE ||
77046 		           resumee->callstack_top == 0);                                                                     /* INACTIVE: no activation, single function value on valstack */
77047 
77048 		if (thr->heap->lj.iserror) {
77049 			/*
77050 			 *  Throw the error in the resumed thread's context; the
77051 			 *  error value is pushed onto the resumee valstack.
77052 			 *
77053 			 *  Note: the callstack of the target may empty in this case
77054 			 *  too (i.e. the target thread has never been resumed).  The
77055 			 *  value stack will contain the initial function in that case,
77056 			 *  which we simply ignore.
77057 			 */
77058 
77059 			DUK_ASSERT(resumee->resumer == NULL);
77060 			resumee->resumer = thr;
77061 			DUK_HTHREAD_INCREF(thr, thr);
77062 			resumee->state = DUK_HTHREAD_STATE_RUNNING;
77063 			thr->state = DUK_HTHREAD_STATE_RESUMED;
77064 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
77065 			thr = resumee;
77066 
77067 			thr->heap->lj.type = DUK_LJ_TYPE_THROW;
77068 
77069 			/* thr->heap->lj.value1 is already the value to throw */
77070 			/* thr->heap->lj.value2 is 'thread', will be wiped out at the end */
77071 
77072 			DUK_ASSERT(thr->heap->lj.iserror);  /* already set */
77073 
77074 			DUK_DD(DUK_DDPRINT("-> resume with an error, converted to a throw in the resumee, propagate"));
77075 			goto check_longjmp;
77076 		} else if (resumee->state == DUK_HTHREAD_STATE_YIELDED) {
77077 			/* Unwind previous Duktape.Thread.yield() call.  The
77078 			 * activation remaining must always be an ECMAScript
77079 			 * call now (yield() accepts calls from ECMAScript
77080 			 * only).
77081 			 */
77082 			duk_activation *act_resumee;
77083 
77084 			DUK_ASSERT(resumee->callstack_top >= 2);
77085 			act_resumee = resumee->callstack_curr;  /* Duktape.Thread.yield() */
77086 			DUK_ASSERT(act_resumee != NULL);
77087 			act_resumee = act_resumee->parent;      /* ECMAScript call site for yield() */
77088 			DUK_ASSERT(act_resumee != NULL);
77089 
77090 			tv = (duk_tval *) (void *) ((duk_uint8_t *) resumee->valstack + act_resumee->retval_byteoff);  /* return value from Duktape.Thread.yield() */
77091 			DUK_ASSERT(tv >= resumee->valstack && tv < resumee->valstack_top);
77092 			tv2 = &thr->heap->lj.value1;
77093 			DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv2);  /* side effects */  /* XXX: avoid side effects */
77094 
77095 			duk_hthread_activation_unwind_norz(resumee);  /* unwind to 'yield' caller */
77096 			/* no need to unwind catch stack */
77097 
77098 			duk__reconfig_valstack_ecma_return(resumee);
77099 
77100 			DUK_ASSERT(resumee->resumer == NULL);
77101 			resumee->resumer = thr;
77102 			DUK_HTHREAD_INCREF(thr, thr);
77103 			resumee->state = DUK_HTHREAD_STATE_RUNNING;
77104 			thr->state = DUK_HTHREAD_STATE_RESUMED;
77105 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
77106 #if 0
77107 			thr = resumee;  /* not needed, as we exit right away */
77108 #endif
77109 			DUK_DD(DUK_DDPRINT("-> resume with a value, restart execution in resumee"));
77110 			retval = DUK__LONGJMP_RESTART;
77111 			goto wipe_and_return;
77112 		} else {
77113 			/* Initial resume call. */
77114 			duk_small_uint_t call_flags;
77115 			duk_int_t setup_rc;
77116 
77117 			/* resumee: [... initial_func]  (currently actually: [initial_func]) */
77118 
77119 			duk_push_undefined(resumee);
77120 			tv = &thr->heap->lj.value1;
77121 			duk_push_tval(resumee, tv);
77122 
77123 			/* resumee: [... initial_func undefined(= this) resume_value ] */
77124 
77125 			call_flags = DUK_CALL_FLAG_ALLOW_ECMATOECMA;  /* not tailcall, ecma-to-ecma (assumed to succeed) */
77126 
77127 			setup_rc = duk_handle_call_unprotected_nargs(resumee, 1 /*nargs*/, call_flags);
77128 			if (setup_rc == 0) {
77129 				/* This shouldn't happen; Duktape.Thread.resume()
77130 				 * should make sure of that.  If it does happen
77131 				 * this internal error will propagate out of the
77132 				 * executor which can be quite misleading.
77133 				 */
77134 				DUK_ERROR_INTERNAL(thr);
77135 				DUK_WO_NORETURN(return 0;);
77136 			}
77137 
77138 			DUK_ASSERT(resumee->resumer == NULL);
77139 			resumee->resumer = thr;
77140 			DUK_HTHREAD_INCREF(thr, thr);
77141 			resumee->state = DUK_HTHREAD_STATE_RUNNING;
77142 			thr->state = DUK_HTHREAD_STATE_RESUMED;
77143 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
77144 #if 0
77145 			thr = resumee;  /* not needed, as we exit right away */
77146 #endif
77147 			DUK_DD(DUK_DDPRINT("-> resume with a value, restart execution in resumee"));
77148 			retval = DUK__LONGJMP_RESTART;
77149 			goto wipe_and_return;
77150 		}
77151 		DUK_UNREACHABLE();
77152 		break;  /* never here */
77153 	}
77154 
77155 	case DUK_LJ_TYPE_YIELD: {
77156 		/*
77157 		 *  Currently only allowed only if yielding thread has only
77158 		 *  ECMAScript activations (except for the Duktape.Thread.yield()
77159 		 *  call at the callstack top) and none of them constructor
77160 		 *  calls.
77161 		 *
77162 		 *  This excludes the 'entry' thread which will always have
77163 		 *  a preventcount > 0.
77164 		 */
77165 
77166 		duk_hthread *resumer;
77167 
77168 		/* duk_bi_duk_object_yield() and duk_bi_duk_object_resume() ensure all of these are met */
77169 
77170 #if 0  /* entry_thread not available for assert */
77171 		DUK_ASSERT(thr != entry_thread);                                                                             /* Duktape.Thread.yield() should prevent */
77172 #endif
77173 		DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);                                                         /* unchanged from Duktape.Thread.yield() */
77174 		DUK_ASSERT(thr->callstack_top >= 2);                                                                         /* ECMAScript activation + Duktape.Thread.yield() activation */
77175 		DUK_ASSERT(thr->callstack_curr != NULL);
77176 		DUK_ASSERT(thr->callstack_curr->parent != NULL);
77177 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL &&
77178 		           DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)) &&
77179 		           ((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->callstack_curr))->func == duk_bi_thread_yield);
77180 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL &&
77181 		           DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr->parent)));                              /* an ECMAScript function */
77182 
77183 		resumer = thr->resumer;
77184 
77185 		DUK_ASSERT(resumer != NULL);
77186 		DUK_ASSERT(resumer->state == DUK_HTHREAD_STATE_RESUMED);                                                     /* written by a previous RESUME handling */
77187 		DUK_ASSERT(resumer->callstack_top >= 2);                                                                     /* ECMAScript activation + Duktape.Thread.resume() activation */
77188 		DUK_ASSERT(resumer->callstack_curr != NULL);
77189 		DUK_ASSERT(resumer->callstack_curr->parent != NULL);
77190 		DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack_curr) != NULL &&
77191 		           DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(resumer->callstack_curr)) &&
77192 		           ((duk_hnatfunc *) DUK_ACT_GET_FUNC(resumer->callstack_curr))->func == duk_bi_thread_resume);
77193 		DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack_curr->parent) != NULL &&
77194 		           DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(resumer->callstack_curr->parent)));                            /* an ECMAScript function */
77195 
77196 		if (thr->heap->lj.iserror) {
77197 			thr->state = DUK_HTHREAD_STATE_YIELDED;
77198 			thr->resumer = NULL;
77199 			DUK_HTHREAD_DECREF_NORZ(thr, resumer);
77200 			resumer->state = DUK_HTHREAD_STATE_RUNNING;
77201 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
77202 			thr = resumer;
77203 
77204 			thr->heap->lj.type = DUK_LJ_TYPE_THROW;
77205 			/* lj.value1 is already set */
77206 			DUK_ASSERT(thr->heap->lj.iserror);  /* already set */
77207 
77208 			DUK_DD(DUK_DDPRINT("-> yield an error, converted to a throw in the resumer, propagate"));
77209 			goto check_longjmp;
77210 		} else {
77211 			/* When handling the yield, the last reference to
77212 			 * 'thr' may disappear.
77213 			 */
77214 
77215 			DUK_GC_TORTURE(resumer->heap);
77216 			duk_hthread_activation_unwind_norz(resumer);
77217 			DUK_GC_TORTURE(resumer->heap);
77218 			thr->state = DUK_HTHREAD_STATE_YIELDED;
77219 			thr->resumer = NULL;
77220 			DUK_HTHREAD_DECREF_NORZ(thr, resumer);
77221 			resumer->state = DUK_HTHREAD_STATE_RUNNING;
77222 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
77223 			duk__handle_yield(thr, resumer, &thr->heap->lj.value1);
77224 			thr = resumer;
77225 			DUK_GC_TORTURE(resumer->heap);
77226 
77227 			DUK_DD(DUK_DDPRINT("-> yield a value, restart execution in resumer"));
77228 			retval = DUK__LONGJMP_RESTART;
77229 			goto wipe_and_return;
77230 		}
77231 		DUK_UNREACHABLE();
77232 		break;  /* never here */
77233 	}
77234 #endif  /* DUK_USE_COROUTINE_SUPPORT */
77235 
77236 	case DUK_LJ_TYPE_THROW: {
77237 		/*
77238 		 *  Three possible outcomes:
77239 		 *    * A try or finally catcher is found => resume there.
77240 		 *      (or)
77241 		 *    * The error propagates to the bytecode executor entry
77242 		 *      level (and we're in the entry thread) => rethrow
77243 		 *      with a new longjmp(), after restoring the previous
77244 		 *      catchpoint.
77245 		 *    * The error is not caught in the current thread, so
77246 		 *      the thread finishes with an error.  This works like
77247 		 *      a yielded error, except that the thread is finished
77248 		 *      and can no longer be resumed.  (There is always a
77249 		 *      resumer in this case.)
77250 		 *
77251 		 *  Note: until we hit the entry level, there can only be
77252 		 *  ECMAScript activations.
77253 		 */
77254 
77255 		duk_activation *act;
77256 		duk_catcher *cat;
77257 		duk_hthread *resumer;
77258 
77259 		for (;;) {
77260 			act = thr->callstack_curr;
77261 			if (act == NULL) {
77262 				break;
77263 			}
77264 
77265 			for (;;) {
77266 				cat = act->cat;
77267 				if (cat == NULL) {
77268 					break;
77269 				}
77270 
77271 				if (DUK_CAT_HAS_CATCH_ENABLED(cat)) {
77272 					DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF);
77273 
77274 					DUK_DDD(DUK_DDDPRINT("before catch part 1: thr=%p, act=%p, cat=%p",
77275 					                     (void *) thr, (void *) act, (void *) act->cat));
77276 					duk__handle_catch_part1(thr,
77277 					                        &thr->heap->lj.value1,
77278 					                        DUK_LJ_TYPE_THROW,
77279 							        out_delayed_catch_setup);
77280 
77281 					DUK_DD(DUK_DDPRINT("-> throw caught by a 'catch' clause, restart execution"));
77282 					retval = DUK__LONGJMP_RESTART;
77283 					goto wipe_and_return;
77284 				}
77285 
77286 				if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
77287 					DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF);
77288 					DUK_ASSERT(!DUK_CAT_HAS_CATCH_ENABLED(cat));
77289 
77290 					duk__handle_finally(thr,
77291 					                    &thr->heap->lj.value1,
77292 					                    DUK_LJ_TYPE_THROW);
77293 
77294 					DUK_DD(DUK_DDPRINT("-> throw caught by a 'finally' clause, restart execution"));
77295 					retval = DUK__LONGJMP_RESTART;
77296 					goto wipe_and_return;
77297 				}
77298 
77299 				duk_hthread_catcher_unwind_norz(thr, act);
77300 			}
77301 
77302 			if (act == entry_act) {
77303 				/* Not caught by anything before entry level; rethrow and let the
77304 				 * final catcher finish unwinding (esp. value stack).
77305 				 */
77306 				DUK_D(DUK_DPRINT("-> throw propagated up to entry level, rethrow and exit bytecode executor"));
77307 				retval = DUK__LONGJMP_RETHROW;
77308 				goto just_return;
77309 			}
77310 
77311 			duk_hthread_activation_unwind_norz(thr);
77312 		}
77313 
77314 		DUK_DD(DUK_DDPRINT("-> throw not caught by current thread, yield error to resumer and recheck longjmp"));
77315 
77316 		/* Not caught by current thread, thread terminates (yield error to resumer);
77317 		 * note that this may cause a cascade if the resumer terminates with an uncaught
77318 		 * exception etc (this is OK, but needs careful testing).
77319 		 */
77320 
77321 		DUK_ASSERT(thr->resumer != NULL);
77322 		DUK_ASSERT(thr->resumer->callstack_top >= 2);  /* ECMAScript activation + Duktape.Thread.resume() activation */
77323 		DUK_ASSERT(thr->resumer->callstack_curr != NULL);
77324 		DUK_ASSERT(thr->resumer->callstack_curr->parent != NULL);
77325 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent) != NULL &&
77326 		           DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent)));  /* an ECMAScript function */
77327 
77328 		resumer = thr->resumer;
77329 
77330 		/* reset longjmp */
77331 
77332 		DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW);  /* already set */
77333 		/* lj.value1 already set */
77334 
77335 		duk_hthread_terminate(thr);  /* updates thread state, minimizes its allocations */
77336 		DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_TERMINATED);
77337 
77338 		thr->resumer = NULL;
77339 		DUK_HTHREAD_DECREF_NORZ(thr, resumer);
77340 		resumer->state = DUK_HTHREAD_STATE_RUNNING;
77341 		DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
77342 		thr = resumer;
77343 		goto check_longjmp;
77344 	}
77345 
77346 	case DUK_LJ_TYPE_BREAK:  /* pseudotypes, not used in actual longjmps */
77347 	case DUK_LJ_TYPE_CONTINUE:
77348 	case DUK_LJ_TYPE_RETURN:
77349 	case DUK_LJ_TYPE_NORMAL:
77350 	default: {
77351 		/* should never happen, but be robust */
77352 		DUK_D(DUK_DPRINT("caught unknown longjmp type %ld, treat as internal error", (long) thr->heap->lj.type));
77353 		goto convert_to_internal_error;
77354 	}
77355 
77356 	}  /* end switch */
77357 
77358 	DUK_UNREACHABLE();
77359 
77360  wipe_and_return:
77361 	DUK_DD(DUK_DDPRINT("handling longjmp done, wipe-and-return, top=%ld",
77362 	                   (long) duk_get_top(thr)));
77363 	thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
77364 	thr->heap->lj.iserror = 0;
77365 
77366 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value1);  /* side effects */
77367 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value2);  /* side effects */
77368 
77369 	DUK_GC_TORTURE(thr->heap);
77370 
77371  just_return:
77372 	return retval;
77373 
77374  convert_to_internal_error:
77375 	/* This could also be thrown internally (set the error, goto check_longjmp),
77376 	 * but it's better for internal errors to bubble outwards so that we won't
77377 	 * infinite loop in this catchpoint.
77378 	 */
77379 	DUK_ERROR_INTERNAL(thr);
77380 	DUK_WO_NORETURN(return 0;);
77381 }
77382 
77383 /* Handle a BREAK/CONTINUE opcode.  Avoid using longjmp() for BREAK/CONTINUE
77384  * handling because it has a measurable performance impact in ordinary
77385  * environments and an extreme impact in Emscripten (GH-342).
77386  */
77387 DUK_LOCAL DUK_EXEC_NOINLINE_PERF void duk__handle_break_or_continue(duk_hthread *thr,
77388                                                                     duk_uint_t label_id,
77389                                                                     duk_small_uint_t lj_type) {
77390 	duk_activation *act;
77391 	duk_catcher *cat;
77392 
77393 	DUK_ASSERT(thr != NULL);
77394 
77395 	/* Find a matching label catcher or 'finally' catcher in
77396 	 * the same function, unwinding catchers as we go.
77397 	 *
77398 	 * A label catcher must always exist and will match unless
77399 	 * a 'finally' captures the break/continue first.  It is the
77400 	 * compiler's responsibility to ensure that labels are used
77401 	 * correctly.
77402 	 */
77403 
77404 	act = thr->callstack_curr;
77405 	DUK_ASSERT(act != NULL);
77406 
77407 	for (;;) {
77408 		cat = act->cat;
77409 		if (cat == NULL) {
77410 			break;
77411 		}
77412 
77413 		DUK_DDD(DUK_DDDPRINT("considering catcher %p: type=%ld label=%ld",
77414 		                     (void *) cat,
77415 		                     (long) DUK_CAT_GET_TYPE(cat),
77416 		                     (long) DUK_CAT_GET_LABEL(cat)));
77417 
77418 		/* XXX: bit mask test; FINALLY <-> TCF, single bit mask would suffice? */
77419 
77420 		if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&
77421 		    DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
77422 			duk_tval tv_tmp;
77423 
77424 			DUK_TVAL_SET_U32(&tv_tmp, (duk_uint32_t) label_id);
77425 			duk__handle_finally(thr, &tv_tmp, lj_type);
77426 
77427 			DUK_DD(DUK_DDPRINT("-> break/continue caught by 'finally', restart execution"));
77428 			return;
77429 		}
77430 		if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_LABEL &&
77431 		    (duk_uint_t) DUK_CAT_GET_LABEL(cat) == label_id) {
77432 			duk__handle_label(thr, lj_type);
77433 
77434 			DUK_DD(DUK_DDPRINT("-> break/continue caught by a label catcher (in the same function), restart execution"));
77435 			return;
77436 		}
77437 
77438 		duk_hthread_catcher_unwind_norz(thr, act);
77439 	}
77440 
77441 	/* Should never happen, but be robust. */
77442 	DUK_D(DUK_DPRINT("-> break/continue not caught by anything in the current function (should never happen), throw internal error"));
77443 	DUK_ERROR_INTERNAL(thr);
77444 	DUK_WO_NORETURN(return;);
77445 }
77446 
77447 /* Handle a RETURN opcode.  Avoid using longjmp() for return handling because
77448  * it has a measurable performance impact in ordinary environments and an extreme
77449  * impact in Emscripten (GH-342).  Return value is on value stack top.
77450  */
77451 DUK_LOCAL duk_small_uint_t duk__handle_return(duk_hthread *thr, duk_activation *entry_act) {
77452 	duk_tval *tv1;
77453 	duk_tval *tv2;
77454 #if defined(DUK_USE_COROUTINE_SUPPORT)
77455 	duk_hthread *resumer;
77456 #endif
77457 	duk_activation *act;
77458 	duk_catcher *cat;
77459 
77460 	/* We can directly access value stack here. */
77461 
77462 	DUK_ASSERT(thr != NULL);
77463 	DUK_ASSERT(entry_act != NULL);
77464 	DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
77465 	tv1 = thr->valstack_top - 1;
77466 	DUK_TVAL_CHKFAST_INPLACE_FAST(tv1);  /* fastint downgrade check for return values */
77467 
77468 	/*
77469 	 *  Four possible outcomes:
77470 	 *
77471 	 *    1. A 'finally' in the same function catches the 'return'.
77472 	 *       It may continue to propagate when 'finally' is finished,
77473 	 *       or it may be neutralized by 'finally' (both handled by
77474 	 *       ENDFIN).
77475 	 *
77476 	 *    2. The return happens at the entry level of the bytecode
77477 	 *       executor, so return from the executor (in C stack).
77478 	 *
77479 	 *    3. There is a calling (ECMAScript) activation in the call
77480 	 *       stack => return to it, in the same executor instance.
77481 	 *
77482 	 *    4. There is no calling activation, and the thread is
77483 	 *       terminated.  There is always a resumer in this case,
77484 	 *       which gets the return value similarly to a 'yield'
77485 	 *       (except that the current thread can no longer be
77486 	 *       resumed).
77487 	 */
77488 
77489 	DUK_ASSERT(thr != NULL);
77490 	DUK_ASSERT(thr->callstack_top >= 1);
77491 
77492 	act = thr->callstack_curr;
77493 	DUK_ASSERT(act != NULL);
77494 
77495 	for (;;) {
77496 		cat = act->cat;
77497 		if (cat == NULL) {
77498 			break;
77499 		}
77500 
77501 		if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&
77502 		    DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
77503 			DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
77504 			duk__handle_finally(thr, thr->valstack_top - 1, DUK_LJ_TYPE_RETURN);
77505 
77506 			DUK_DD(DUK_DDPRINT("-> return caught by 'finally', restart execution"));
77507 			return DUK__RETHAND_RESTART;
77508 		}
77509 
77510 		duk_hthread_catcher_unwind_norz(thr, act);
77511 	}
77512 
77513 	if (act == entry_act) {
77514 		/* Return to the bytecode executor caller who will unwind stacks
77515 		 * and handle constructor post-processing.
77516 		 * Return value is already on the stack top: [ ... retval ].
77517 		 */
77518 
77519 		DUK_DDD(DUK_DDDPRINT("-> return propagated up to entry level, exit bytecode executor"));
77520 		return DUK__RETHAND_FINISHED;
77521 	}
77522 
77523 	if (thr->callstack_top >= 2) {
77524 		/* There is a caller; it MUST be an ECMAScript caller (otherwise it would
77525 		 * match entry_act check).
77526 		 */
77527 		DUK_DDD(DUK_DDDPRINT("return to ECMAScript caller, retval_byteoff=%ld, lj_value1=%!T",
77528 		                     (long) (thr->callstack_curr->parent->retval_byteoff),
77529 		                     (duk_tval *) &thr->heap->lj.value1));
77530 
77531 		DUK_ASSERT(thr->callstack_curr != NULL);
77532 		DUK_ASSERT(thr->callstack_curr->parent != NULL);
77533 		DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr->parent)));   /* must be ECMAScript */
77534 
77535 #if defined(DUK_USE_ES6_PROXY)
77536 		if (thr->callstack_curr->flags & (DUK_ACT_FLAG_CONSTRUCT | DUK_ACT_FLAG_CONSTRUCT_PROXY)) {
77537 			duk_call_construct_postprocess(thr, thr->callstack_curr->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY);  /* side effects */
77538 		}
77539 #else
77540 		if (thr->callstack_curr->flags & DUK_ACT_FLAG_CONSTRUCT) {
77541 			duk_call_construct_postprocess(thr, 0);  /* side effects */
77542 		}
77543 #endif
77544 
77545 		tv1 = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + thr->callstack_curr->parent->retval_byteoff);
77546 		DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
77547 		tv2 = thr->valstack_top - 1;
77548 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
77549 
77550 		/* Catch stack unwind happens inline in callstack unwind. */
77551 		duk_hthread_activation_unwind_norz(thr);
77552 
77553 		duk__reconfig_valstack_ecma_return(thr);
77554 
77555 		DUK_DD(DUK_DDPRINT("-> return not intercepted, restart execution in caller"));
77556 		return DUK__RETHAND_RESTART;
77557 	}
77558 
77559 #if defined(DUK_USE_COROUTINE_SUPPORT)
77560 	DUK_DD(DUK_DDPRINT("no calling activation, thread finishes (similar to yield)"));
77561 
77562 	DUK_ASSERT(thr->resumer != NULL);
77563 	DUK_ASSERT(thr->resumer->callstack_top >= 2);  /* ECMAScript activation + Duktape.Thread.resume() activation */
77564 	DUK_ASSERT(thr->resumer->callstack_curr != NULL);
77565 	DUK_ASSERT(thr->resumer->callstack_curr->parent != NULL);
77566 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr) != NULL &&
77567 			DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr)) &&
77568 			((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->resumer->callstack_curr))->func == duk_bi_thread_resume);  /* Duktape.Thread.resume() */
77569 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent) != NULL &&
77570 			DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent)));  /* an ECMAScript function */
77571 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
77572 	DUK_ASSERT(thr->resumer->state == DUK_HTHREAD_STATE_RESUMED);
77573 
77574 	resumer = thr->resumer;
77575 
77576 	/* Share yield longjmp handler.
77577 	 *
77578 	 * This sequence of steps is a bit fragile (see GH-1845):
77579 	 * - We need the return value from 'thr' (resumed thread) value stack.
77580 	 *   The termination unwinds its value stack, losing the value.
77581 	 * - We need a refcounted reference for 'thr', which may only exist
77582 	 *   in the caller value stack.  We can't unwind or reconfigure the
77583 	 *   caller's value stack without potentially freeing 'thr'.
77584 	 *
77585 	 * Current approach is to capture the 'thr' return value and store
77586 	 * a reference to 'thr' in the caller value stack temporarily.  This
77587 	 * keeps 'thr' reachable until final yield/return handling which
77588 	 * removes the references atomatically.
77589 	 */
77590 
77591 	DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
77592 	duk_hthread_activation_unwind_norz(resumer);  /* May remove last reference to 'thr', but is NORZ. */
77593 	duk_push_tval(resumer, thr->valstack_top - 1);  /* Capture return value, side effect free. */
77594 	duk_push_hthread(resumer, thr);  /* Make 'thr' reachable again, before side effects. */
77595 
77596 	duk_hthread_terminate(thr);  /* Updates thread state, minimizes its allocations. */
77597 	thr->resumer = NULL;
77598 	DUK_HTHREAD_DECREF(thr, resumer);
77599 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_TERMINATED);
77600 
77601 	resumer->state = DUK_HTHREAD_STATE_RUNNING;
77602 	DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
77603 
77604 	DUK_ASSERT(resumer->valstack_top - 2 >= resumer->valstack_bottom);
77605 	duk__handle_yield(thr, resumer, resumer->valstack_top - 2);
77606 	thr = NULL;  /* 'thr' invalidated by call */
77607 
77608 #if 0
77609 	thr = resumer;  /* not needed */
77610 #endif
77611 
77612 	DUK_DD(DUK_DDPRINT("-> return not caught, thread terminated; handle like yield, restart execution in resumer"));
77613 	return DUK__RETHAND_RESTART;
77614 #else
77615 	/* Without coroutine support this case should never happen. */
77616 	DUK_ERROR_INTERNAL(thr);
77617 	DUK_WO_NORETURN(return 0;);
77618 #endif
77619 }
77620 
77621 /*
77622  *  Executor interrupt handling
77623  *
77624  *  The handler is called whenever the interrupt countdown reaches zero
77625  *  (or below).  The handler must perform whatever checks are activated,
77626  *  e.g. check for cumulative step count to impose an execution step
77627  *  limit or check for breakpoints or other debugger interaction.
77628  *
77629  *  When the actions are done, the handler must reinit the interrupt
77630  *  init and counter values.  The 'init' value must indicate how many
77631  *  bytecode instructions are executed before the next interrupt.  The
77632  *  counter must interface with the bytecode executor loop.  Concretely,
77633  *  the new init value is normally one higher than the new counter value.
77634  *  For instance, to execute exactly one bytecode instruction the init
77635  *  value is set to 1 and the counter to 0.  If an error is thrown by the
77636  *  interrupt handler, the counters are set to the same value (e.g. both
77637  *  to 0 to cause an interrupt when the next bytecode instruction is about
77638  *  to be executed after error handling).
77639  *
77640  *  Maintaining the init/counter value properly is important for accurate
77641  *  behavior.  For instance, executor step limit needs a cumulative step
77642  *  count which is simply computed as a sum of 'init' values.  This must
77643  *  work accurately even when single stepping.
77644  */
77645 
77646 #if defined(DUK_USE_INTERRUPT_COUNTER)
77647 
77648 #define DUK__INT_NOACTION    0    /* no specific action, resume normal execution */
77649 #define DUK__INT_RESTART     1    /* must "goto restart_execution", e.g. breakpoints changed */
77650 
77651 #if defined(DUK_USE_DEBUGGER_SUPPORT)
77652 DUK_LOCAL void duk__interrupt_handle_debugger(duk_hthread *thr, duk_bool_t *out_immediate, duk_small_uint_t *out_interrupt_retval) {
77653 	duk_activation *act;
77654 	duk_breakpoint *bp;
77655 	duk_breakpoint **bp_active;
77656 	duk_uint_fast32_t line = 0;
77657 	duk_bool_t process_messages;
77658 	duk_bool_t processed_messages = 0;
77659 
77660 	DUK_ASSERT(thr->heap->dbg_processing == 0);  /* don't re-enter e.g. during Eval */
77661 
77662 	act = thr->callstack_curr;
77663 	DUK_ASSERT(act != NULL);
77664 
77665 	/* It might seem that replacing 'thr->heap' with just 'heap' below
77666 	 * might be a good idea, but it increases code size slightly
77667 	 * (probably due to unnecessary spilling) at least on x64.
77668 	 */
77669 
77670 	/*
77671 	 *  Single opcode step check
77672 	 */
77673 
77674 	if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_ONE_OPCODE_ACTIVE) {
77675 		DUK_D(DUK_DPRINT("PAUSE TRIGGERED by one opcode step"));
77676 		duk_debug_set_paused(thr->heap);
77677 	}
77678 
77679 	/*
77680 	 *  Breakpoint and step state checks
77681 	 */
77682 
77683 	if (act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE ||
77684 	    (thr->heap->dbg_pause_act == thr->callstack_curr)) {
77685 		line = duk_debug_curr_line(thr);
77686 
77687 		if (act->prev_line != line) {
77688 			/* Stepped?  Step out is handled by callstack unwind. */
77689 			if ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) &&
77690 			    (thr->heap->dbg_pause_act == thr->callstack_curr) &&
77691 			    (line != thr->heap->dbg_pause_startline)) {
77692 				DUK_D(DUK_DPRINT("PAUSE TRIGGERED by line change, at line %ld",
77693 				                 (long) line));
77694 				duk_debug_set_paused(thr->heap);
77695 			}
77696 
77697 			/* Check for breakpoints only on line transition.
77698 			 * Breakpoint is triggered when we enter the target
77699 			 * line from a different line, and the previous line
77700 			 * was within the same function.
77701 			 *
77702 			 * This condition is tricky: the condition used to be
77703 			 * that transition to -or across- the breakpoint line
77704 			 * triggered the breakpoint.  This seems intuitively
77705 			 * better because it handles breakpoints on lines with
77706 			 * no emitted opcodes; but this leads to the issue
77707 			 * described in: https://github.com/svaarala/duktape/issues/263.
77708 			 */
77709 			bp_active = thr->heap->dbg_breakpoints_active;
77710 			for (;;) {
77711 				bp = *bp_active++;
77712 				if (bp == NULL) {
77713 					break;
77714 				}
77715 
77716 				DUK_ASSERT(bp->filename != NULL);
77717 				if (act->prev_line != bp->line && line == bp->line) {
77718 					DUK_D(DUK_DPRINT("PAUSE TRIGGERED by breakpoint at %!O:%ld",
77719 					                 (duk_heaphdr *) bp->filename, (long) bp->line));
77720 					duk_debug_set_paused(thr->heap);
77721 				}
77722 			}
77723 		} else {
77724 			;
77725 		}
77726 
77727 		act->prev_line = (duk_uint32_t) line;
77728 	}
77729 
77730 	/*
77731 	 *  Rate limit check for sending status update or peeking into
77732 	 *  the debug transport.  Both can be expensive operations that
77733 	 *  we don't want to do on every opcode.
77734 	 *
77735 	 *  Making sure the interval remains reasonable on a wide variety
77736 	 *  of targets and bytecode is difficult without a timestamp, so
77737 	 *  we use a Date-provided timestamp for the rate limit check.
77738 	 *  But since it's also expensive to get a timestamp, a bytecode
77739 	 *  counter is used to rate limit getting timestamps.
77740 	 */
77741 
77742 	process_messages = 0;
77743 	if (thr->heap->dbg_state_dirty || DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) || thr->heap->dbg_detaching) {
77744 		/* Enter message processing loop for sending Status notifys and
77745 		 * to finish a pending detach.
77746 		 */
77747 		process_messages = 1;
77748 	}
77749 
77750 	/* XXX: remove heap->dbg_exec_counter, use heap->inst_count_interrupt instead? */
77751 	DUK_ASSERT(thr->interrupt_init >= 0);
77752 	thr->heap->dbg_exec_counter += (duk_uint_t) thr->interrupt_init;
77753 	if (thr->heap->dbg_exec_counter - thr->heap->dbg_last_counter >= DUK_HEAP_DBG_RATELIMIT_OPCODES) {
77754 		/* Overflow of the execution counter is fine and doesn't break
77755 		 * anything here.
77756 		 */
77757 
77758 		duk_double_t now, diff_last;
77759 
77760 		thr->heap->dbg_last_counter = thr->heap->dbg_exec_counter;
77761 		now = duk_time_get_monotonic_time(thr);
77762 
77763 		diff_last = now - thr->heap->dbg_last_time;
77764 		if (diff_last < 0.0 || diff_last >= (duk_double_t) DUK_HEAP_DBG_RATELIMIT_MILLISECS) {
77765 			/* Monotonic time should not experience time jumps,
77766 			 * but the provider may be missing and we're actually
77767 			 * using ECMAScript time.  So, tolerate negative values
77768 			 * so that a time jump works reasonably.
77769 			 *
77770 			 * Same interval is now used for status sending and
77771 			 * peeking.
77772 			 */
77773 
77774 			thr->heap->dbg_last_time = now;
77775 			thr->heap->dbg_state_dirty = 1;
77776 			process_messages = 1;
77777 		}
77778 	}
77779 
77780 	/*
77781 	 *  Process messages and send status if necessary.
77782 	 *
77783 	 *  If we're paused, we'll block for new messages.  If we're not
77784 	 *  paused, we'll process anything we can peek but won't block
77785 	 *  for more.  Detach (and re-attach) handling is all localized
77786 	 *  to duk_debug_process_messages() too.
77787 	 *
77788 	 *  Debugger writes outside the message loop may cause debugger
77789 	 *  detach1 phase to run, after which dbg_read_cb == NULL and
77790 	 *  dbg_detaching != 0.  The message loop will finish the detach
77791 	 *  by running detach2 phase, so enter the message loop also when
77792 	 *  detaching.
77793 	 */
77794 
77795 	if (process_messages) {
77796 		DUK_ASSERT(thr->heap->dbg_processing == 0);
77797 		processed_messages = duk_debug_process_messages(thr, 0 /*no_block*/);
77798 		DUK_ASSERT(thr->heap->dbg_processing == 0);
77799 	}
77800 
77801 	/* Continue checked execution if there are breakpoints or we're stepping.
77802 	 * Also use checked execution if paused flag is active - it shouldn't be
77803 	 * because the debug message loop shouldn't terminate if it was.  Step out
77804 	 * is handled by callstack unwind and doesn't need checked execution.
77805 	 * Note that debugger may have detached due to error or explicit request
77806 	 * above, so we must recheck attach status.
77807 	 */
77808 
77809 	if (duk_debug_is_attached(thr->heap)) {
77810 		DUK_ASSERT(act == thr->callstack_curr);
77811 		DUK_ASSERT(act != NULL);
77812 		if (act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE ||
77813 		    (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_ONE_OPCODE) ||
77814 		    ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) &&
77815 		     thr->heap->dbg_pause_act == thr->callstack_curr) ||
77816 		     DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap)) {
77817 			*out_immediate = 1;
77818 		}
77819 
77820 		/* If we processed any debug messages breakpoints may have
77821 		 * changed; restart execution to re-check active breakpoints.
77822 		 */
77823 		if (processed_messages) {
77824 			DUK_D(DUK_DPRINT("processed debug messages, restart execution to recheck possibly changed breakpoints"));
77825 			*out_interrupt_retval = DUK__INT_RESTART;
77826 		} else {
77827 			if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_ONE_OPCODE) {
77828 				/* Set 'pause after one opcode' active only when we're
77829 				 * actually just about to execute code.
77830 				 */
77831 				thr->heap->dbg_pause_flags |= DUK_PAUSE_FLAG_ONE_OPCODE_ACTIVE;
77832 			}
77833 		}
77834 	} else {
77835 		DUK_D(DUK_DPRINT("debugger became detached, resume normal execution"));
77836 	}
77837 }
77838 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
77839 
77840 DUK_LOCAL DUK_EXEC_NOINLINE_PERF DUK_COLD duk_small_uint_t duk__executor_interrupt(duk_hthread *thr) {
77841 	duk_int_t ctr;
77842 	duk_activation *act;
77843 	duk_hcompfunc *fun;
77844 	duk_bool_t immediate = 0;
77845 	duk_small_uint_t retval;
77846 
77847 	DUK_ASSERT(thr != NULL);
77848 	DUK_ASSERT(thr->heap != NULL);
77849 	DUK_ASSERT(thr->callstack_top > 0);
77850 
77851 #if defined(DUK_USE_DEBUG)
77852 	thr->heap->inst_count_interrupt += thr->interrupt_init;
77853 	DUK_DD(DUK_DDPRINT("execution interrupt, counter=%ld, init=%ld, "
77854 	                   "instruction counts: executor=%ld, interrupt=%ld",
77855 	                   (long) thr->interrupt_counter, (long) thr->interrupt_init,
77856 	                   (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt));
77857 #endif
77858 
77859 	retval = DUK__INT_NOACTION;
77860 	ctr = DUK_HTHREAD_INTCTR_DEFAULT;
77861 
77862 	/*
77863 	 *  Avoid nested calls.  Concretely this happens during debugging, e.g.
77864 	 *  when we eval() an expression.
77865 	 *
77866 	 *  Also don't interrupt if we're currently doing debug processing
77867 	 *  (which can be initiated outside the bytecode executor) as this
77868 	 *  may cause the debugger to be called recursively.  Check required
77869 	 *  for correct operation of throw intercept and other "exotic" halting
77870 	 * scenarios.
77871 	 */
77872 
77873 #if defined(DUK_USE_DEBUGGER_SUPPORT)
77874 	if (DUK_HEAP_HAS_INTERRUPT_RUNNING(thr->heap) || thr->heap->dbg_processing) {
77875 #else
77876 	if (DUK_HEAP_HAS_INTERRUPT_RUNNING(thr->heap)) {
77877 #endif
77878 		DUK_DD(DUK_DDPRINT("nested executor interrupt, ignoring"));
77879 
77880 		/* Set a high interrupt counter; the original executor
77881 		 * interrupt invocation will rewrite before exiting.
77882 		 */
77883 		thr->interrupt_init = ctr;
77884 		thr->interrupt_counter = ctr - 1;
77885 		return DUK__INT_NOACTION;
77886 	}
77887 	DUK_HEAP_SET_INTERRUPT_RUNNING(thr->heap);
77888 
77889 	act = thr->callstack_curr;
77890 	DUK_ASSERT(act != NULL);
77891 
77892 	fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
77893 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC((duk_hobject *) fun));
77894 
77895 	DUK_UNREF(fun);
77896 
77897 #if defined(DUK_USE_EXEC_TIMEOUT_CHECK)
77898 	/*
77899 	 *  Execution timeout check
77900 	 */
77901 
77902 	if (DUK_USE_EXEC_TIMEOUT_CHECK(thr->heap->heap_udata)) {
77903 		/* Keep throwing an error whenever we get here.  The unusual values
77904 		 * are set this way because no instruction is ever executed, we just
77905 		 * throw an error until all try/catch/finally and other catchpoints
77906 		 * have been exhausted.  Duktape/C code gets control at each protected
77907 		 * call but whenever it enters back into Duktape the RangeError gets
77908 		 * raised.  User exec timeout check must consistently indicate a timeout
77909 		 * until we've fully bubbled out of Duktape.
77910 		 */
77911 		DUK_D(DUK_DPRINT("execution timeout, throwing a RangeError"));
77912 		thr->interrupt_init = 0;
77913 		thr->interrupt_counter = 0;
77914 		DUK_HEAP_CLEAR_INTERRUPT_RUNNING(thr->heap);
77915 		DUK_ERROR_RANGE(thr, "execution timeout");
77916 		DUK_WO_NORETURN(return 0;);
77917 	}
77918 #endif  /* DUK_USE_EXEC_TIMEOUT_CHECK */
77919 
77920 #if defined(DUK_USE_DEBUGGER_SUPPORT)
77921 	if (!thr->heap->dbg_processing &&
77922 	    (thr->heap->dbg_read_cb != NULL || thr->heap->dbg_detaching)) {
77923 		/* Avoid recursive re-entry; enter when we're attached or
77924 		 * detaching (to finish off the pending detach).
77925 		 */
77926 		duk__interrupt_handle_debugger(thr, &immediate, &retval);
77927 		DUK_ASSERT(act == thr->callstack_curr);
77928 	}
77929 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
77930 
77931 	/*
77932 	 *  Update the interrupt counter
77933 	 */
77934 
77935 	if (immediate) {
77936 		/* Cause an interrupt after executing one instruction. */
77937 		ctr = 1;
77938 	}
77939 
77940 	/* The counter value is one less than the init value: init value should
77941 	 * indicate how many instructions are executed before interrupt.  To
77942 	 * execute 1 instruction (after interrupt handler return), counter must
77943 	 * be 0.
77944 	 */
77945 	DUK_ASSERT(ctr >= 1);
77946 	thr->interrupt_init = ctr;
77947 	thr->interrupt_counter = ctr - 1;
77948 	DUK_HEAP_CLEAR_INTERRUPT_RUNNING(thr->heap);
77949 
77950 	return retval;
77951 }
77952 #endif  /* DUK_USE_INTERRUPT_COUNTER */
77953 
77954 /*
77955  *  Debugger handling for executor restart
77956  *
77957  *  Check for breakpoints, stepping, etc, and figure out if we should execute
77958  *  in checked or normal mode.  Note that we can't do this when an activation
77959  *  is created, because breakpoint status (and stepping status) may change
77960  *  later, so we must recheck every time we're executing an activation.
77961  *  This primitive should be side effect free to avoid changes during check.
77962  */
77963 
77964 #if defined(DUK_USE_DEBUGGER_SUPPORT)
77965 DUK_LOCAL void duk__executor_recheck_debugger(duk_hthread *thr, duk_activation *act, duk_hcompfunc *fun) {
77966 	duk_heap *heap;
77967 	duk_tval *tv_tmp;
77968 	duk_hstring *filename;
77969 	duk_small_uint_t bp_idx;
77970 	duk_breakpoint **bp_active;
77971 
77972 	DUK_ASSERT(thr != NULL);
77973 	DUK_ASSERT(act != NULL);
77974 	DUK_ASSERT(fun != NULL);
77975 
77976 	heap = thr->heap;
77977 	bp_active = heap->dbg_breakpoints_active;
77978 	act->flags &= ~DUK_ACT_FLAG_BREAKPOINT_ACTIVE;
77979 
77980 	tv_tmp = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, (duk_hobject *) fun, DUK_STRIDX_FILE_NAME);
77981 	if (tv_tmp && DUK_TVAL_IS_STRING(tv_tmp)) {
77982 		filename = DUK_TVAL_GET_STRING(tv_tmp);
77983 
77984 		/* Figure out all active breakpoints.  A breakpoint is
77985 		 * considered active if the current function's fileName
77986 		 * matches the breakpoint's fileName, AND there is no
77987 		 * inner function that has matching line numbers
77988 		 * (otherwise a breakpoint would be triggered both
77989 		 * inside and outside of the inner function which would
77990 		 * be confusing).  Example:
77991 		 *
77992 		 *     function foo() {
77993 		 *         print('foo');
77994 		 *         function bar() {    <-.  breakpoints in these
77995 		 *             print('bar');     |  lines should not affect
77996 		 *         }                   <-'  foo() execution
77997 		 *         bar();
77998 		 *     }
77999 		 *
78000 		 * We need a few things that are only available when
78001 		 * debugger support is enabled: (1) a line range for
78002 		 * each function, and (2) access to the function
78003 		 * template to access the inner functions (and their
78004 		 * line ranges).
78005 		 *
78006 		 * It's important to have a narrow match for active
78007 		 * breakpoints so that we don't enter checked execution
78008 		 * when that's not necessary.  For instance, if we're
78009 		 * running inside a certain function and there's
78010 		 * breakpoint outside in (after the call site), we
78011 		 * don't want to slow down execution of the function.
78012 		 */
78013 
78014 		for (bp_idx = 0; bp_idx < heap->dbg_breakpoint_count; bp_idx++) {
78015 			duk_breakpoint *bp = heap->dbg_breakpoints + bp_idx;
78016 			duk_hobject **funcs, **funcs_end;
78017 			duk_hcompfunc *inner_fun;
78018 			duk_bool_t bp_match;
78019 
78020 			if (bp->filename == filename &&
78021 			    bp->line >= fun->start_line && bp->line <= fun->end_line) {
78022 				bp_match = 1;
78023 				DUK_DD(DUK_DDPRINT("breakpoint filename and line match: "
78024 				                   "%s:%ld vs. %s (line %ld vs. %ld-%ld)",
78025 				                   DUK_HSTRING_GET_DATA(bp->filename),
78026 				                   (long) bp->line,
78027 				                   DUK_HSTRING_GET_DATA(filename),
78028 				                   (long) bp->line,
78029 				                   (long) fun->start_line,
78030 				                   (long) fun->end_line));
78031 
78032 				funcs = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, fun);
78033 				funcs_end = DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, fun);
78034 				while (funcs != funcs_end) {
78035 					inner_fun = (duk_hcompfunc *) *funcs;
78036 					DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) inner_fun));
78037 					if (bp->line >= inner_fun->start_line && bp->line <= inner_fun->end_line) {
78038 						DUK_DD(DUK_DDPRINT("inner function masks ('captures') breakpoint"));
78039 						bp_match = 0;
78040 						break;
78041 					}
78042 					funcs++;
78043 				}
78044 
78045 				if (bp_match) {
78046 					/* No need to check for size of bp_active list,
78047 					 * it's always larger than maximum number of
78048 					 * breakpoints.
78049 					 */
78050 					act->flags |= DUK_ACT_FLAG_BREAKPOINT_ACTIVE;
78051 					*bp_active = heap->dbg_breakpoints + bp_idx;
78052 					bp_active++;
78053 				}
78054 			}
78055 		}
78056 	}
78057 
78058 	*bp_active = NULL;  /* terminate */
78059 
78060 	DUK_DD(DUK_DDPRINT("ACTIVE BREAKPOINTS: %ld", (long) (bp_active - thr->heap->dbg_breakpoints_active)));
78061 
78062 	/* Force pause if we were doing "step into" in another activation. */
78063 	if ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_FUNC_ENTRY) &&
78064 	    thr->heap->dbg_pause_act != thr->callstack_curr) {
78065 		DUK_D(DUK_DPRINT("PAUSE TRIGGERED by function entry"));
78066 		duk_debug_set_paused(thr->heap);
78067 	}
78068 
78069 	/* Force interrupt right away if we're paused or in "checked mode".
78070 	 * Step out is handled by callstack unwind.
78071 	 */
78072 	if ((act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE) ||
78073 	    DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) ||
78074 	    ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) &&
78075 	     thr->heap->dbg_pause_act == thr->callstack_curr)) {
78076 		/* We'll need to interrupt early so recompute the init
78077 		 * counter to reflect the number of bytecode instructions
78078 		 * executed so that step counts for e.g. debugger rate
78079 		 * limiting are accurate.
78080 		 */
78081 		DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);
78082 		thr->interrupt_init = thr->interrupt_init - thr->interrupt_counter;
78083 		thr->interrupt_counter = 0;
78084 	}
78085 }
78086 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
78087 
78088 /*
78089  *  Opcode handlers for opcodes with a lot of code and which are relatively
78090  *  rare; NOINLINE to reduce amount of code in main bytecode dispatcher.
78091  */
78092 
78093 DUK_LOCAL DUK_EXEC_NOINLINE_PERF void duk__handle_op_initset_initget(duk_hthread *thr, duk_uint_fast32_t ins) {
78094 	duk_bool_t is_set = (DUK_DEC_OP(ins) == DUK_OP_INITSET);
78095 	duk_uint_fast_t idx;
78096 	duk_uint_t defprop_flags;
78097 
78098 	/* A -> object register (acts as a source)
78099 	 * BC -> BC+0 contains key, BC+1 closure (value)
78100 	 */
78101 
78102 	/* INITSET/INITGET are only used to initialize object literal keys.
78103 	 * There may be a previous propery in ES2015 because duplicate property
78104 	 * names are allowed.
78105 	 */
78106 
78107 	/* This could be made more optimal by accessing internals directly. */
78108 
78109 	idx = (duk_uint_fast_t) DUK_DEC_BC(ins);
78110 	duk_dup(thr, (duk_idx_t) (idx + 0));  /* key */
78111 	duk_dup(thr, (duk_idx_t) (idx + 1));  /* getter/setter */
78112 	if (is_set) {
78113 	        defprop_flags = DUK_DEFPROP_HAVE_SETTER |
78114 	                        DUK_DEFPROP_FORCE |
78115 	                        DUK_DEFPROP_SET_ENUMERABLE |
78116 	                        DUK_DEFPROP_SET_CONFIGURABLE;
78117 	} else {
78118 	        defprop_flags = DUK_DEFPROP_HAVE_GETTER |
78119 	                        DUK_DEFPROP_FORCE |
78120 	                        DUK_DEFPROP_SET_ENUMERABLE |
78121 	                        DUK_DEFPROP_SET_CONFIGURABLE;
78122 	}
78123 	duk_def_prop(thr, (duk_idx_t) DUK_DEC_A(ins), defprop_flags);
78124 }
78125 
78126 DUK_LOCAL DUK_EXEC_NOINLINE_PERF void duk__handle_op_trycatch(duk_hthread *thr, duk_uint_fast32_t ins, duk_instr_t *curr_pc) {
78127 	duk_activation *act;
78128 	duk_catcher *cat;
78129 	duk_tval *tv1;
78130 	duk_small_uint_fast_t a;
78131 	duk_small_uint_fast_t bc;
78132 
78133 	/* A -> flags
78134 	 * BC -> reg_catch; base register for two registers used both during
78135 	 *       trycatch setup and when catch is triggered
78136 	 *
78137 	 *      If DUK_BC_TRYCATCH_FLAG_CATCH_BINDING set:
78138 	 *          reg_catch + 0: catch binding variable name (string).
78139 	 *          Automatic declarative environment is established for
78140 	 *          the duration of the 'catch' clause.
78141 	 *
78142 	 *      If DUK_BC_TRYCATCH_FLAG_WITH_BINDING set:
78143 	 *          reg_catch + 0: with 'target value', which is coerced to
78144 	 *          an object and then used as a bindind object for an
78145 	 *          environment record.  The binding is initialized here, for
78146 	 *          the 'try' clause.
78147 	 *
78148 	 * Note that a TRYCATCH generated for a 'with' statement has no
78149 	 * catch or finally parts.
78150 	 */
78151 
78152 	/* XXX: TRYCATCH handling should be reworked to avoid creating
78153 	 * an explicit scope unless it is actually needed (e.g. function
78154 	 * instances or eval is executed inside the catch block).  This
78155 	 * rework is not trivial because the compiler doesn't have an
78156 	 * intermediate representation.  When the rework is done, the
78157 	 * opcode format can also be made more straightforward.
78158 	 */
78159 
78160 	/* XXX: side effect handling is quite awkward here */
78161 
78162 	DUK_DDD(DUK_DDDPRINT("TRYCATCH: reg_catch=%ld, have_catch=%ld, "
78163 	                     "have_finally=%ld, catch_binding=%ld, with_binding=%ld (flags=0x%02lx)",
78164 	                     (long) DUK_DEC_BC(ins),
78165 	                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH ? 1 : 0),
78166 	                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY ? 1 : 0),
78167 	                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_CATCH_BINDING ? 1 : 0),
78168 	                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_WITH_BINDING ? 1 : 0),
78169 	                     (unsigned long) DUK_DEC_A(ins)));
78170 
78171 	a = DUK_DEC_A(ins);
78172 	bc = DUK_DEC_BC(ins);
78173 
78174 	/* Registers 'bc' and 'bc + 1' are written in longjmp handling
78175 	 * and if their previous values (which are temporaries) become
78176 	 * unreachable -and- have a finalizer, there'll be a function
78177 	 * call during error handling which is not supported now (GH-287).
78178 	 * Ensure that both 'bc' and 'bc + 1' have primitive values to
78179 	 * guarantee no finalizer calls in error handling.  Scrubbing also
78180 	 * ensures finalizers for the previous values run here rather than
78181 	 * later.  Error handling related values are also written to 'bc'
78182 	 * and 'bc + 1' but those values never become unreachable during
78183 	 * error handling, so there's no side effect problem even if the
78184 	 * error value has a finalizer.
78185 	 */
78186 	duk_dup(thr, (duk_idx_t) bc);  /* Stabilize value. */
78187 	duk_to_undefined(thr, (duk_idx_t) bc);
78188 	duk_to_undefined(thr, (duk_idx_t) (bc + 1));
78189 
78190 	/* Allocate catcher and populate it.  Doesn't have to
78191 	 * be fully atomic, but the catcher must be in a
78192 	 * consistent state if side effects (such as finalizer
78193 	 * calls) occur.
78194 	 */
78195 
78196 	cat = duk_hthread_catcher_alloc(thr);
78197 	DUK_ASSERT(cat != NULL);
78198 
78199 	cat->flags = DUK_CAT_TYPE_TCF;
78200 	cat->h_varname = NULL;
78201 	cat->pc_base = (duk_instr_t *) curr_pc;  /* pre-incremented, points to first jump slot */
78202 	cat->idx_base = (duk_size_t) (thr->valstack_bottom - thr->valstack) + bc;
78203 
78204 	act = thr->callstack_curr;
78205 	DUK_ASSERT(act != NULL);
78206 	cat->parent = act->cat;
78207 	act->cat = cat;
78208 
78209 	if (a & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) {
78210 		cat->flags |= DUK_CAT_FLAG_CATCH_ENABLED;
78211 	}
78212 	if (a & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY) {
78213 		cat->flags |= DUK_CAT_FLAG_FINALLY_ENABLED;
78214 	}
78215 	if (a & DUK_BC_TRYCATCH_FLAG_CATCH_BINDING) {
78216 		DUK_DDD(DUK_DDDPRINT("catch binding flag set to catcher"));
78217 		cat->flags |= DUK_CAT_FLAG_CATCH_BINDING_ENABLED;
78218 		tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
78219 		DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
78220 
78221 		/* borrowed reference; although 'tv1' comes from a register,
78222 		 * its value was loaded using LDCONST so the constant will
78223 		 * also exist and be reachable.
78224 		 */
78225 		cat->h_varname = DUK_TVAL_GET_STRING(tv1);
78226 	} else if (a & DUK_BC_TRYCATCH_FLAG_WITH_BINDING) {
78227 		duk_hobjenv *env;
78228 		duk_hobject *target;
78229 
78230 		/* Delayed env initialization for activation (if needed). */
78231 		DUK_ASSERT(thr->callstack_top >= 1);
78232 		DUK_ASSERT(act == thr->callstack_curr);
78233 		DUK_ASSERT(act != NULL);
78234 		if (act->lex_env == NULL) {
78235 			DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
78236 			DUK_ASSERT(act->var_env == NULL);
78237 
78238 			duk_js_init_activation_environment_records_delayed(thr, act);
78239 			DUK_ASSERT(act == thr->callstack_curr);
78240 			DUK_UNREF(act);  /* 'act' is no longer accessed, scanbuild fix */
78241 		}
78242 		DUK_ASSERT(act->lex_env != NULL);
78243 		DUK_ASSERT(act->var_env != NULL);
78244 
78245 		/* Coerce 'with' target. */
78246 		target = duk_to_hobject(thr, -1);
78247 		DUK_ASSERT(target != NULL);
78248 
78249 		/* Create an object environment; it is not pushed
78250 		 * so avoid side effects very carefully until it is
78251 		 * referenced.
78252 		 */
78253 		env = duk_hobjenv_alloc(thr,
78254 		                        DUK_HOBJECT_FLAG_EXTENSIBLE |
78255 		                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
78256 		DUK_ASSERT(env != NULL);
78257 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) env) == NULL);
78258 		env->target = target;  /* always provideThis=true */
78259 		DUK_HOBJECT_INCREF(thr, target);
78260 		env->has_this = 1;
78261 		DUK_HOBJENV_ASSERT_VALID(env);
78262 		DUK_DDD(DUK_DDDPRINT("environment for with binding: %!iO", env));
78263 
78264 		DUK_ASSERT(act == thr->callstack_curr);
78265 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) env) == NULL);
78266 		DUK_ASSERT(act->lex_env != NULL);
78267 		DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) env, act->lex_env);
78268 		act->lex_env = (duk_hobject *) env;  /* Now reachable. */
78269 		DUK_HOBJECT_INCREF(thr, (duk_hobject *) env);
78270 		/* Net refcount change to act->lex_env is 0: incref for env's
78271 		 * prototype, decref for act->lex_env overwrite.
78272 		 */
78273 
78274 		/* Set catcher lex_env active (affects unwind)
78275 		 * only when the whole setup is complete.
78276 		 */
78277 		cat = act->cat;  /* XXX: better to relookup? not mandatory because 'cat' is stable */
78278 		cat->flags |= DUK_CAT_FLAG_LEXENV_ACTIVE;
78279 	} else {
78280 		;
78281 	}
78282 
78283 	DUK_DDD(DUK_DDDPRINT("TRYCATCH catcher: flags=0x%08lx, pc_base=%ld, "
78284 	                     "idx_base=%ld, h_varname=%!O",
78285 	                     (unsigned long) cat->flags,
78286 	                     (long) cat->pc_base, (long) cat->idx_base, (duk_heaphdr *) cat->h_varname));
78287 
78288 	duk_pop_unsafe(thr);
78289 }
78290 
78291 DUK_LOCAL DUK_EXEC_NOINLINE_PERF duk_instr_t *duk__handle_op_endtry(duk_hthread *thr, duk_uint_fast32_t ins) {
78292 	duk_activation *act;
78293 	duk_catcher *cat;
78294 	duk_tval *tv1;
78295 	duk_instr_t *pc_base;
78296 
78297 	DUK_UNREF(ins);
78298 
78299 	DUK_ASSERT(thr->callstack_top >= 1);
78300 	act = thr->callstack_curr;
78301 	DUK_ASSERT(act != NULL);
78302 	cat = act->cat;
78303 	DUK_ASSERT(cat != NULL);
78304 	DUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_TCF);
78305 
78306 	DUK_DDD(DUK_DDDPRINT("ENDTRY: clearing catch active flag (regardless of whether it was set or not)"));
78307 	DUK_CAT_CLEAR_CATCH_ENABLED(cat);
78308 
78309 	pc_base = cat->pc_base;
78310 
78311 	if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
78312 		DUK_DDD(DUK_DDDPRINT("ENDTRY: finally part is active, jump through 2nd jump slot with 'normal continuation'"));
78313 
78314 		tv1 = thr->valstack + cat->idx_base;
78315 		DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
78316 		DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */
78317 		tv1 = NULL;
78318 
78319 		tv1 = thr->valstack + cat->idx_base + 1;
78320 		DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
78321 		DUK_TVAL_SET_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL);  /* side effects */
78322 		tv1 = NULL;
78323 
78324 		DUK_CAT_CLEAR_FINALLY_ENABLED(cat);
78325 	} else {
78326 		DUK_DDD(DUK_DDDPRINT("ENDTRY: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)"));
78327 
78328 		duk_hthread_catcher_unwind_norz(thr, act);  /* lexenv may be set for 'with' binding */
78329 		/* no need to unwind callstack */
78330 	}
78331 
78332 	return pc_base + 1;  /* new curr_pc value */
78333 }
78334 
78335 DUK_LOCAL DUK_EXEC_NOINLINE_PERF duk_instr_t *duk__handle_op_endcatch(duk_hthread *thr, duk_uint_fast32_t ins) {
78336 	duk_activation *act;
78337 	duk_catcher *cat;
78338 	duk_tval *tv1;
78339 	duk_instr_t *pc_base;
78340 
78341 	DUK_UNREF(ins);
78342 
78343 	DUK_ASSERT(thr->callstack_top >= 1);
78344 	act = thr->callstack_curr;
78345 	DUK_ASSERT(act != NULL);
78346 	cat = act->cat;
78347 	DUK_ASSERT(cat != NULL);
78348 	DUK_ASSERT(!DUK_CAT_HAS_CATCH_ENABLED(cat));  /* cleared before entering catch part */
78349 
78350 	if (DUK_CAT_HAS_LEXENV_ACTIVE(cat)) {
78351 		duk_hobject *prev_env;
78352 
78353 		/* 'with' binding has no catch clause, so can't be here unless a normal try-catch */
78354 		DUK_ASSERT(DUK_CAT_HAS_CATCH_BINDING_ENABLED(cat));
78355 		DUK_ASSERT(act->lex_env != NULL);
78356 
78357 		DUK_DDD(DUK_DDDPRINT("ENDCATCH: popping catcher part lexical environment"));
78358 
78359 		prev_env = act->lex_env;
78360 		DUK_ASSERT(prev_env != NULL);
78361 		act->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, prev_env);
78362 		DUK_CAT_CLEAR_LEXENV_ACTIVE(cat);
78363 		DUK_HOBJECT_INCREF(thr, act->lex_env);
78364 		DUK_HOBJECT_DECREF(thr, prev_env);  /* side effects */
78365 
78366 		DUK_ASSERT(act == thr->callstack_curr);
78367 		DUK_ASSERT(act != NULL);
78368 	}
78369 
78370 	pc_base = cat->pc_base;
78371 
78372 	if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
78373 		DUK_DDD(DUK_DDDPRINT("ENDCATCH: finally part is active, jump through 2nd jump slot with 'normal continuation'"));
78374 
78375 		tv1 = thr->valstack + cat->idx_base;
78376 		DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
78377 		DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */
78378 		tv1 = NULL;
78379 
78380 		tv1 = thr->valstack + cat->idx_base + 1;
78381 		DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
78382 		DUK_TVAL_SET_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL);  /* side effects */
78383 		tv1 = NULL;
78384 
78385 		DUK_CAT_CLEAR_FINALLY_ENABLED(cat);
78386 	} else {
78387 		DUK_DDD(DUK_DDDPRINT("ENDCATCH: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)"));
78388 
78389 		duk_hthread_catcher_unwind_norz(thr, act);
78390 		/* no need to unwind callstack */
78391 	}
78392 
78393 	return pc_base + 1;  /* new curr_pc value */
78394 }
78395 
78396 DUK_LOCAL DUK_EXEC_NOINLINE_PERF duk_small_uint_t duk__handle_op_endfin(duk_hthread *thr, duk_uint_fast32_t ins, duk_activation *entry_act) {
78397 	duk_activation *act;
78398 	duk_tval *tv1;
78399 	duk_uint_t reg_catch;
78400 	duk_small_uint_t cont_type;
78401 	duk_small_uint_t ret_result;
78402 
78403 	DUK_ASSERT(thr->ptr_curr_pc == NULL);
78404 	DUK_ASSERT(thr->callstack_top >= 1);
78405 	act = thr->callstack_curr;
78406 	DUK_ASSERT(act != NULL);
78407 	reg_catch = DUK_DEC_ABC(ins);
78408 
78409 	/* CATCH flag may be enabled or disabled here; it may be enabled if
78410 	 * the statement has a catch block but the try block does not throw
78411 	 * an error.
78412 	 */
78413 
78414 	DUK_DDD(DUK_DDDPRINT("ENDFIN: completion value=%!T, type=%!T",
78415 	                     (duk_tval *) (thr->valstack_bottom + reg_catch + 0),
78416 	                     (duk_tval *) (thr->valstack_bottom + reg_catch + 1)));
78417 
78418 	tv1 = thr->valstack_bottom + reg_catch + 1;  /* type */
78419 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
78420 #if defined(DUK_USE_FASTINT)
78421 	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
78422 	cont_type = (duk_small_uint_t) DUK_TVAL_GET_FASTINT_U32(tv1);
78423 #else
78424 	cont_type = (duk_small_uint_t) DUK_TVAL_GET_NUMBER(tv1);
78425 #endif
78426 
78427 	tv1--;  /* value */
78428 
78429 	switch (cont_type) {
78430 	case DUK_LJ_TYPE_NORMAL: {
78431 		DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with 'normal' (non-abrupt) completion -> "
78432 		                     "dismantle catcher, resume execution after ENDFIN"));
78433 
78434 		duk_hthread_catcher_unwind_norz(thr, act);
78435 		/* no need to unwind callstack */
78436 		return 0;  /* restart execution */
78437 	}
78438 	case DUK_LJ_TYPE_RETURN: {
78439 		DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with 'return' complation -> dismantle "
78440 		                     "catcher, handle return, lj.value1=%!T", tv1));
78441 
78442 		/* Not necessary to unwind catch stack: return handling will
78443 		 * do it.  The finally flag of 'cat' is no longer set.  The
78444 		 * catch flag may be set, but it's not checked by return handling.
78445 		 */
78446 
78447 		duk_push_tval(thr, tv1);
78448 		ret_result = duk__handle_return(thr, entry_act);
78449 		if (ret_result == DUK__RETHAND_RESTART) {
78450 			return 0;  /* restart execution */
78451 		}
78452 		DUK_ASSERT(ret_result == DUK__RETHAND_FINISHED);
78453 
78454 		DUK_DDD(DUK_DDDPRINT("exiting executor after ENDFIN and RETURN (pseudo) longjmp type"));
78455 		return 1;  /* exit executor */
78456 	}
78457 	case DUK_LJ_TYPE_BREAK:
78458 	case DUK_LJ_TYPE_CONTINUE: {
78459 		duk_uint_t label_id;
78460 		duk_small_uint_t lj_type;
78461 
78462 		/* Not necessary to unwind catch stack: break/continue
78463 		 * handling will do it.  The finally flag of 'cat' is
78464 		 * no longer set.  The catch flag may be set, but it's
78465 		 * not checked by break/continue handling.
78466 		 */
78467 
78468 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
78469 #if defined(DUK_USE_FASTINT)
78470 		DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
78471 		label_id = (duk_small_uint_t) DUK_TVAL_GET_FASTINT_U32(tv1);
78472 #else
78473 		label_id = (duk_small_uint_t) DUK_TVAL_GET_NUMBER(tv1);
78474 #endif
78475 		lj_type = cont_type;
78476 		duk__handle_break_or_continue(thr, label_id, lj_type);
78477 		return 0;  /* restart execution */
78478 	}
78479 	default: {
78480 		DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with abrupt completion, lj_type=%ld -> "
78481 		                     "dismantle catcher, re-throw error",
78482 		                     (long) cont_type));
78483 
78484 		duk_err_setup_ljstate1(thr, (duk_small_uint_t) cont_type, tv1);
78485 		/* No debugger Throw notify check on purpose (rethrow). */
78486 
78487 		DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* always in executor */
78488 		duk_err_longjmp(thr);
78489 		DUK_UNREACHABLE();
78490 	}
78491 	}
78492 
78493 	DUK_UNREACHABLE();
78494 	return 0;
78495 }
78496 
78497 DUK_LOCAL DUK_EXEC_NOINLINE_PERF void duk__handle_op_initenum(duk_hthread *thr, duk_uint_fast32_t ins) {
78498 	duk_small_uint_t b;
78499 	duk_small_uint_t c;
78500 
78501 	/*
78502 	 *  Enumeration semantics come from for-in statement, E5 Section 12.6.4.
78503 	 *  If called with 'null' or 'undefined', this opcode returns 'null' as
78504 	 *  the enumerator, which is special cased in NEXTENUM.  This simplifies
78505 	 *  the compiler part
78506 	 */
78507 
78508 	/* B -> register for writing enumerator object
78509 	 * C -> value to be enumerated (register)
78510 	 */
78511 	b = DUK_DEC_B(ins);
78512 	c = DUK_DEC_C(ins);
78513 
78514 	if (duk_is_null_or_undefined(thr, (duk_idx_t) c)) {
78515 		duk_push_null(thr);
78516 		duk_replace(thr, (duk_idx_t) b);
78517 	} else {
78518 		duk_dup(thr, (duk_idx_t) c);
78519 		duk_to_object(thr, -1);
78520 		duk_hobject_enumerator_create(thr, 0 /*enum_flags*/);  /* [ ... val ] --> [ ... enum ] */
78521 		duk_replace(thr, (duk_idx_t) b);
78522 	}
78523 }
78524 
78525 DUK_LOCAL DUK_EXEC_NOINLINE_PERF duk_small_uint_t duk__handle_op_nextenum(duk_hthread *thr, duk_uint_fast32_t ins) {
78526 	duk_small_uint_t b;
78527 	duk_small_uint_t c;
78528 	duk_small_uint_t pc_skip = 0;
78529 
78530 	/*
78531 	 *  NEXTENUM checks whether the enumerator still has unenumerated
78532 	 *  keys.  If so, the next key is loaded to the target register
78533 	 *  and the next instruction is skipped.  Otherwise the next instruction
78534 	 *  will be executed, jumping out of the enumeration loop.
78535 	 */
78536 
78537 	/* B -> target register for next key
78538 	 * C -> enum register
78539 	 */
78540 	b = DUK_DEC_B(ins);
78541 	c = DUK_DEC_C(ins);
78542 
78543 	DUK_DDD(DUK_DDDPRINT("NEXTENUM: b->%!T, c->%!T",
78544 	                     (duk_tval *) duk_get_tval(thr, (duk_idx_t) b),
78545 	                     (duk_tval *) duk_get_tval(thr, (duk_idx_t) c)));
78546 
78547 	if (duk_is_object(thr, (duk_idx_t) c)) {
78548 		/* XXX: assert 'c' is an enumerator */
78549 		duk_dup(thr, (duk_idx_t) c);
78550 		if (duk_hobject_enumerator_next(thr, 0 /*get_value*/)) {
78551 			/* [ ... enum ] -> [ ... next_key ] */
78552 			DUK_DDD(DUK_DDDPRINT("enum active, next key is %!T, skip jump slot ",
78553 			                     (duk_tval *) duk_get_tval(thr, -1)));
78554 			pc_skip = 1;
78555 		} else {
78556 			/* [ ... enum ] -> [ ... ] */
78557 			DUK_DDD(DUK_DDDPRINT("enum finished, execute jump slot"));
78558 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* valstack policy */
78559 			thr->valstack_top++;
78560 		}
78561 		duk_replace(thr, (duk_idx_t) b);
78562 	} else {
78563 		/* 'null' enumerator case -> behave as with an empty enumerator */
78564 		DUK_ASSERT(duk_is_null(thr, (duk_idx_t) c));
78565 		DUK_DDD(DUK_DDDPRINT("enum is null, execute jump slot"));
78566 	}
78567 
78568 	return pc_skip;
78569 }
78570 
78571 /*
78572  *  Call handling helpers.
78573  */
78574 
78575 DUK_LOCAL duk_bool_t duk__executor_handle_call(duk_hthread *thr, duk_idx_t idx, duk_idx_t nargs, duk_small_uint_t call_flags) {
78576 	duk_bool_t rc;
78577 
78578 	duk_set_top_unsafe(thr, (duk_idx_t) (idx + nargs + 2));   /* [ ... func this arg1 ... argN ] */
78579 
78580 	/* Attempt an Ecma-to-Ecma call setup.  If the call
78581 	 * target is (directly or indirectly) Reflect.construct(),
78582 	 * the call may change into a constructor call on the fly.
78583 	 */
78584 	rc = (duk_bool_t) duk_handle_call_unprotected(thr, idx, call_flags);
78585 	if (rc != 0) {
78586 		/* Ecma-to-ecma call possible, may or may not
78587 		 * be a tail call.  Avoid C recursion by
78588 		 * reusing current executor instance.
78589 		 */
78590 		DUK_DDD(DUK_DDDPRINT("ecma-to-ecma call setup possible, restart execution"));
78591 		/* curr_pc synced by duk_handle_call_unprotected() */
78592 		DUK_ASSERT(thr->ptr_curr_pc == NULL);
78593 		return rc;
78594 	} else {
78595 		/* Call was handled inline. */
78596 	}
78597 	DUK_ASSERT(thr->ptr_curr_pc != NULL);
78598 	return rc;
78599 }
78600 
78601 /*
78602  *  ECMAScript bytecode executor.
78603  *
78604  *  Resume execution for the current thread from its current activation.
78605  *  Returns when execution would return from the entry level activation,
78606  *  leaving a single return value on top of the stack.  Function calls
78607  *  and thread resumptions are handled internally.  If an error occurs,
78608  *  a longjmp() with type DUK_LJ_TYPE_THROW is called on the entry level
78609  *  setjmp() jmpbuf.
78610  *
78611  *  ECMAScript function calls and coroutine resumptions are handled
78612  *  internally (by the outer executor function) without recursive C calls.
78613  *  Other function calls are handled using duk_handle_call(), increasing
78614  *  C recursion depth.
78615  *
78616  *  Abrupt completions (= long control tranfers) are handled either
78617  *  directly by reconfiguring relevant stacks and restarting execution,
78618  *  or via a longjmp.  Longjmp-free handling is preferable for performance
78619  *  (especially Emscripten performance), and is used for: break, continue,
78620  *  and return.
78621  *
78622  *  For more detailed notes, see doc/execution.rst.
78623  *
78624  *  Also see doc/code-issues.rst for discussion of setjmp(), longjmp(),
78625  *  and volatile.
78626  */
78627 
78628 /* Presence of 'fun' is config based, there's a marginal performance
78629  * difference and the best option is architecture dependent.
78630  */
78631 #if defined(DUK_USE_EXEC_FUN_LOCAL)
78632 #define DUK__FUN()          fun
78633 #else
78634 #define DUK__FUN()          ((duk_hcompfunc *) DUK_ACT_GET_FUNC((thr)->callstack_curr))
78635 #endif
78636 
78637 /* Strict flag. */
78638 #define DUK__STRICT()       ((duk_small_uint_t) DUK_HOBJECT_HAS_STRICT((duk_hobject *) DUK__FUN()))
78639 
78640 /* Reg/const access macros: these are very footprint and performance sensitive
78641  * so modify with care.  Arguments are sometimes evaluated multiple times which
78642  * is not ideal.
78643  */
78644 #define DUK__REG(x)         (*(thr->valstack_bottom + (x)))
78645 #define DUK__REGP(x)        (thr->valstack_bottom + (x))
78646 #define DUK__CONST(x)       (*(consts + (x)))
78647 #define DUK__CONSTP(x)      (consts + (x))
78648 
78649 /* Reg/const access macros which take the 32-bit instruction and avoid an
78650  * explicit field decoding step by using shifts and masks.  These must be
78651  * kept in sync with duk_js_bytecode.h.  The shift/mask values are chosen
78652  * so that 'ins' can be shifted and masked and used as a -byte- offset
78653  * instead of a duk_tval offset which needs further shifting (which is an
78654  * issue on some, but not all, CPUs).
78655  */
78656 #define DUK__RCBIT_B           DUK_BC_REGCONST_B
78657 #define DUK__RCBIT_C           DUK_BC_REGCONST_C
78658 #if defined(DUK_USE_EXEC_REGCONST_OPTIMIZE)
78659 #if defined(DUK_USE_PACKED_TVAL)
78660 #define DUK__TVAL_SHIFT        3  /* sizeof(duk_tval) == 8 */
78661 #else
78662 #define DUK__TVAL_SHIFT        4  /* sizeof(duk_tval) == 16; not always the case so also asserted for */
78663 #endif
78664 #define DUK__SHIFT_A           (DUK_BC_SHIFT_A - DUK__TVAL_SHIFT)
78665 #define DUK__SHIFT_B           (DUK_BC_SHIFT_B - DUK__TVAL_SHIFT)
78666 #define DUK__SHIFT_C           (DUK_BC_SHIFT_C - DUK__TVAL_SHIFT)
78667 #define DUK__SHIFT_BC          (DUK_BC_SHIFT_BC - DUK__TVAL_SHIFT)
78668 #define DUK__MASK_A            (DUK_BC_UNSHIFTED_MASK_A << DUK__TVAL_SHIFT)
78669 #define DUK__MASK_B            (DUK_BC_UNSHIFTED_MASK_B << DUK__TVAL_SHIFT)
78670 #define DUK__MASK_C            (DUK_BC_UNSHIFTED_MASK_C << DUK__TVAL_SHIFT)
78671 #define DUK__MASK_BC           (DUK_BC_UNSHIFTED_MASK_BC << DUK__TVAL_SHIFT)
78672 #define DUK__BYTEOFF_A(ins)    (((ins) >> DUK__SHIFT_A) & DUK__MASK_A)
78673 #define DUK__BYTEOFF_B(ins)    (((ins) >> DUK__SHIFT_B) & DUK__MASK_B)
78674 #define DUK__BYTEOFF_C(ins)    (((ins) >> DUK__SHIFT_C) & DUK__MASK_C)
78675 #define DUK__BYTEOFF_BC(ins)   (((ins) >> DUK__SHIFT_BC) & DUK__MASK_BC)
78676 
78677 #define DUK__REGP_A(ins)       ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_A((ins))))
78678 #define DUK__REGP_B(ins)       ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_B((ins))))
78679 #define DUK__REGP_C(ins)       ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_C((ins))))
78680 #define DUK__REGP_BC(ins)      ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_BC((ins))))
78681 #define DUK__CONSTP_A(ins)     ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_A((ins))))
78682 #define DUK__CONSTP_B(ins)     ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_B((ins))))
78683 #define DUK__CONSTP_C(ins)     ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_C((ins))))
78684 #define DUK__CONSTP_BC(ins)    ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_BC((ins))))
78685 #define DUK__REGCONSTP_B(ins)  ((duk_tval *) (void *) ((duk_uint8_t *) (((ins) & DUK__RCBIT_B) ? consts : thr->valstack_bottom) + DUK__BYTEOFF_B((ins))))
78686 #define DUK__REGCONSTP_C(ins)  ((duk_tval *) (void *) ((duk_uint8_t *) (((ins) & DUK__RCBIT_C) ? consts : thr->valstack_bottom) + DUK__BYTEOFF_C((ins))))
78687 #else  /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
78688 /* Safe alternatives, no assumption about duk_tval size. */
78689 #define DUK__REGP_A(ins)       DUK__REGP(DUK_DEC_A((ins)))
78690 #define DUK__REGP_B(ins)       DUK__REGP(DUK_DEC_B((ins)))
78691 #define DUK__REGP_C(ins)       DUK__REGP(DUK_DEC_C((ins)))
78692 #define DUK__REGP_BC(ins)      DUK__REGP(DUK_DEC_BC((ins)))
78693 #define DUK__CONSTP_A(ins)     DUK__CONSTP(DUK_DEC_A((ins)))
78694 #define DUK__CONSTP_B(ins)     DUK__CONSTP(DUK_DEC_B((ins)))
78695 #define DUK__CONSTP_C(ins)     DUK__CONSTP(DUK_DEC_C((ins)))
78696 #define DUK__CONSTP_BC(ins)    DUK__CONSTP(DUK_DEC_BC((ins)))
78697 #define DUK__REGCONSTP_B(ins)  ((((ins) & DUK__RCBIT_B) ? consts : thr->valstack_bottom) + DUK_DEC_B((ins)))
78698 #define DUK__REGCONSTP_C(ins)  ((((ins) & DUK__RCBIT_C) ? consts : thr->valstack_bottom) + DUK_DEC_C((ins)))
78699 #endif  /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
78700 
78701 #if defined(DUK_USE_VERBOSE_EXECUTOR_ERRORS)
78702 #define DUK__INTERNAL_ERROR(msg)  do { \
78703 		DUK_ERROR_ERROR(thr, (msg)); \
78704 		DUK_WO_NORETURN(return;); \
78705 	} while (0)
78706 #else
78707 #define DUK__INTERNAL_ERROR(msg)  do { \
78708 		goto internal_error; \
78709 	} while (0)
78710 #endif
78711 
78712 #define DUK__SYNC_CURR_PC()  do { \
78713 		duk_activation *duk__act; \
78714 		duk__act = thr->callstack_curr; \
78715 		duk__act->curr_pc = curr_pc; \
78716 	} while (0)
78717 #define DUK__SYNC_AND_NULL_CURR_PC()  do { \
78718 		duk_activation *duk__act; \
78719 		duk__act = thr->callstack_curr; \
78720 		duk__act->curr_pc = curr_pc; \
78721 		thr->ptr_curr_pc = NULL; \
78722 	} while (0)
78723 
78724 #if defined(DUK_USE_EXEC_PREFER_SIZE)
78725 #define DUK__LOOKUP_INDIRECT(idx) do { \
78726 		(idx) = (duk_uint_fast_t) duk_get_uint(thr, (duk_idx_t) (idx)); \
78727 	} while (0)
78728 #elif defined(DUK_USE_FASTINT)
78729 #define DUK__LOOKUP_INDIRECT(idx) do { \
78730 		duk_tval *tv_ind; \
78731 		tv_ind = DUK__REGP((idx)); \
78732 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind)); \
78733 		DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv_ind));  /* compiler guarantees */ \
78734 		(idx) = (duk_uint_fast_t) DUK_TVAL_GET_FASTINT_U32(tv_ind); \
78735 	} while (0)
78736 #else
78737 #define DUK__LOOKUP_INDIRECT(idx) do { \
78738 		duk_tval *tv_ind; \
78739 		tv_ind = DUK__REGP(idx); \
78740 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind)); \
78741 		idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind); \
78742 	} while (0)
78743 #endif
78744 
78745 DUK_LOCAL void duk__handle_executor_error(duk_heap *heap,
78746                                           duk_activation *entry_act,
78747                                           duk_int_t entry_call_recursion_depth,
78748                                           duk_jmpbuf *entry_jmpbuf_ptr,
78749                                           volatile duk_bool_t *out_delayed_catch_setup) {
78750 	duk_small_uint_t lj_ret;
78751 
78752 	/* Longjmp callers are required to sync-and-null thr->ptr_curr_pc
78753 	 * before longjmp.
78754 	 */
78755 	DUK_ASSERT(heap->curr_thread != NULL);
78756 	DUK_ASSERT(heap->curr_thread->ptr_curr_pc == NULL);
78757 
78758 	/* XXX: signalling the need to shrink check (only if unwound) */
78759 
78760 	/* Must be restored here to handle e.g. yields properly. */
78761 	heap->call_recursion_depth = entry_call_recursion_depth;
78762 
78763 	/* Switch to caller's setjmp() catcher so that if an error occurs
78764 	 * during error handling, it is always propagated outwards instead
78765 	 * of causing an infinite loop in our own handler.
78766 	 */
78767 	heap->lj.jmpbuf_ptr = (duk_jmpbuf *) entry_jmpbuf_ptr;
78768 
78769 	lj_ret = duk__handle_longjmp(heap->curr_thread, entry_act, out_delayed_catch_setup);
78770 
78771 	/* Error handling complete, remove side effect protections.
78772 	 */
78773 #if defined(DUK_USE_ASSERTIONS)
78774 	DUK_ASSERT(heap->error_not_allowed == 1);
78775 	heap->error_not_allowed = 0;
78776 #endif
78777 	DUK_ASSERT(heap->pf_prevent_count > 0);
78778 	heap->pf_prevent_count--;
78779 	DUK_DD(DUK_DDPRINT("executor error handled, pf_prevent_count updated to %ld", (long) heap->pf_prevent_count));
78780 
78781 	if (lj_ret == DUK__LONGJMP_RESTART) {
78782 		/* Restart bytecode execution, possibly with a changed thread. */
78783 		DUK_REFZERO_CHECK_SLOW(heap->curr_thread);
78784 	} else {
78785 		/* If an error is propagated, don't run refzero checks here.
78786 		 * The next catcher will deal with that.  Pf_prevent_count
78787 		 * will be re-bumped by the longjmp.
78788 		 */
78789 
78790 		DUK_ASSERT(lj_ret == DUK__LONGJMP_RETHROW);  /* Rethrow error to calling state. */
78791 		DUK_ASSERT(heap->lj.jmpbuf_ptr == entry_jmpbuf_ptr);  /* Longjmp handling has restored jmpbuf_ptr. */
78792 
78793 		/* Thread may have changed, e.g. YIELD converted to THROW. */
78794 		duk_err_longjmp(heap->curr_thread);
78795 		DUK_UNREACHABLE();
78796 	}
78797 }
78798 
78799 /* Outer executor with setjmp/longjmp handling. */
78800 DUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) {
78801 	/* Entry level info. */
78802 	duk_hthread *entry_thread;
78803 	duk_activation *entry_act;
78804 	duk_int_t entry_call_recursion_depth;
78805 	duk_jmpbuf *entry_jmpbuf_ptr;
78806 	duk_jmpbuf our_jmpbuf;
78807 	duk_heap *heap;
78808 	volatile duk_bool_t delayed_catch_setup = 0;
78809 
78810 	DUK_ASSERT(exec_thr != NULL);
78811 	DUK_ASSERT(exec_thr->heap != NULL);
78812 	DUK_ASSERT(exec_thr->heap->curr_thread != NULL);
78813 	DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR((duk_heaphdr *) exec_thr);
78814 	DUK_ASSERT(exec_thr->callstack_top >= 1);  /* at least one activation, ours */
78815 	DUK_ASSERT(exec_thr->callstack_curr != NULL);
78816 	DUK_ASSERT(DUK_ACT_GET_FUNC(exec_thr->callstack_curr) != NULL);
78817 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(exec_thr->callstack_curr)));
78818 
78819 	DUK_GC_TORTURE(exec_thr->heap);
78820 
78821 	entry_thread = exec_thr;
78822 	heap = entry_thread->heap;
78823 	entry_act = entry_thread->callstack_curr;
78824 	DUK_ASSERT(entry_act != NULL);
78825 	entry_call_recursion_depth = entry_thread->heap->call_recursion_depth;
78826 	entry_jmpbuf_ptr = entry_thread->heap->lj.jmpbuf_ptr;
78827 
78828 	/*
78829 	 *  Note: we currently assume that the setjmp() catchpoint is
78830 	 *  not re-entrant (longjmp() cannot be called more than once
78831 	 *  for a single setjmp()).
78832 	 *
78833 	 *  See doc/code-issues.rst for notes on variable assignment
78834 	 *  before and after setjmp().
78835 	 */
78836 
78837 	for (;;) {
78838 		heap->lj.jmpbuf_ptr = &our_jmpbuf;
78839 		DUK_ASSERT(heap->lj.jmpbuf_ptr != NULL);
78840 
78841 #if defined(DUK_USE_CPP_EXCEPTIONS)
78842 		try {
78843 #else
78844 		DUK_ASSERT(heap->lj.jmpbuf_ptr == &our_jmpbuf);
78845 		if (DUK_SETJMP(our_jmpbuf.jb) == 0) {
78846 #endif
78847 			DUK_DDD(DUK_DDDPRINT("after setjmp, delayed catch setup: %ld\n", (long) delayed_catch_setup));
78848 
78849 			if (DUK_UNLIKELY(delayed_catch_setup != 0)) {
78850 				duk_hthread *thr = entry_thread->heap->curr_thread;
78851 
78852 				delayed_catch_setup = 0;
78853 				duk__handle_catch_part2(thr);
78854 				DUK_ASSERT(delayed_catch_setup == 0);
78855 				DUK_DDD(DUK_DDDPRINT("top after delayed catch setup: %ld", (long) duk_get_top(entry_thread)));
78856 			}
78857 
78858 			/* Execute bytecode until returned or longjmp(). */
78859 			duk__js_execute_bytecode_inner(entry_thread, entry_act);
78860 
78861 			/* Successful return: restore jmpbuf and return to caller. */
78862 			heap->lj.jmpbuf_ptr = entry_jmpbuf_ptr;
78863 
78864 			return;
78865 #if defined(DUK_USE_CPP_EXCEPTIONS)
78866 		} catch (duk_internal_exception &exc) {
78867 #else
78868 		} else {
78869 #endif
78870 #if defined(DUK_USE_CPP_EXCEPTIONS)
78871 			DUK_UNREF(exc);
78872 #endif
78873 			DUK_DDD(DUK_DDDPRINT("longjmp caught by bytecode executor"));
78874 			DUK_STATS_INC(exec_thr->heap, stats_exec_throw);
78875 
78876 			duk__handle_executor_error(heap,
78877 			                           entry_act,
78878 			                           entry_call_recursion_depth,
78879 			                           entry_jmpbuf_ptr,
78880 						   &delayed_catch_setup);
78881 		}
78882 #if defined(DUK_USE_CPP_EXCEPTIONS)
78883 		catch (duk_fatal_exception &exc) {
78884 			DUK_D(DUK_DPRINT("rethrow duk_fatal_exception"));
78885 			DUK_UNREF(exc);
78886 			throw;
78887 		} catch (std::exception &exc) {
78888 			const char *what = exc.what();
78889 			if (!what) {
78890 				what = "unknown";
78891 			}
78892 			DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
78893 			DUK_STATS_INC(exec_thr->heap, stats_exec_throw);
78894 			try {
78895 				DUK_ASSERT(heap->curr_thread != NULL);
78896 				DUK_ERROR_FMT1(heap->curr_thread, DUK_ERR_TYPE_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
78897 				DUK_WO_NORETURN(return;);
78898 			} catch (duk_internal_exception exc) {
78899 				DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
78900 				DUK_UNREF(exc);
78901 				duk__handle_executor_error(heap,
78902 				                           entry_act,
78903 				                           entry_call_recursion_depth,
78904 				                           entry_jmpbuf_ptr,
78905 							   &delayed_catch_setup);
78906 			}
78907 		} catch (...) {
78908 			DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
78909 			DUK_STATS_INC(exec_thr->heap, stats_exec_throw);
78910 			try {
78911 				DUK_ASSERT(heap->curr_thread != NULL);
78912 				DUK_ERROR_TYPE(heap->curr_thread, "caught invalid c++ exception (perhaps thrown by user code)");
78913 				DUK_WO_NORETURN(return;);
78914 			} catch (duk_internal_exception exc) {
78915 				DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
78916 				DUK_UNREF(exc);
78917 				duk__handle_executor_error(heap,
78918 				                           entry_act,
78919 				                           entry_call_recursion_depth,
78920 				                           entry_jmpbuf_ptr,
78921 							   &delayed_catch_setup);
78922 			}
78923 		}
78924 #endif
78925 	}
78926 
78927 	DUK_WO_NORETURN(return;);
78928 }
78929 
78930 /* Inner executor, performance critical. */
78931 DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, duk_activation *entry_act) {
78932 	/* Current PC, accessed by other functions through thr->ptr_to_curr_pc.
78933 	 * Critical for performance.  It would be safest to make this volatile,
78934 	 * but that eliminates performance benefits; aliasing guarantees
78935 	 * should be enough though.
78936 	 */
78937 	duk_instr_t *curr_pc;         /* bytecode has a stable pointer */
78938 
78939 	/* Hot variables for interpretation.  Critical for performance,
78940 	 * but must add sparingly to minimize register shuffling.
78941 	 */
78942 	duk_hthread *thr;             /* stable */
78943 	duk_tval *consts;             /* stable */
78944 	duk_uint_fast32_t ins;
78945 	/* 'funcs' is quite rarely used, so no local for it */
78946 #if defined(DUK_USE_EXEC_FUN_LOCAL)
78947 	duk_hcompfunc *fun;
78948 #else
78949 	/* 'fun' is quite rarely used, so no local for it */
78950 #endif
78951 
78952 #if defined(DUK_USE_INTERRUPT_COUNTER)
78953 	duk_int_t int_ctr;
78954 #endif
78955 
78956 #if defined(DUK_USE_ASSERTIONS)
78957 	duk_size_t valstack_top_base;    /* valstack top, should match before interpreting each op (no leftovers) */
78958 #endif
78959 
78960 	/* Optimized reg/const access macros assume sizeof(duk_tval) to be
78961 	 * either 8 or 16.  Heap allocation checks this even without asserts
78962 	 * enabled now because it can't be autodetected in duk_config.h.
78963 	 */
78964 #if 1
78965 #if defined(DUK_USE_PACKED_TVAL)
78966 	DUK_ASSERT(sizeof(duk_tval) == 8);
78967 #else
78968 	DUK_ASSERT(sizeof(duk_tval) == 16);
78969 #endif
78970 #endif
78971 
78972 	DUK_GC_TORTURE(entry_thread->heap);
78973 
78974 	/*
78975 	 *  Restart execution by reloading thread state.
78976 	 *
78977 	 *  Note that 'thr' and any thread configuration may have changed,
78978 	 *  so all local variables are suspect and we need to reinitialize.
78979 	 *
78980 	 *  The number of local variables should be kept to a minimum: if
78981 	 *  the variables are spilled, they will need to be loaded from
78982 	 *  memory anyway.
78983 	 *
78984 	 *  Any 'goto restart_execution;' code path in opcode dispatch must
78985 	 *  ensure 'curr_pc' is synced back to act->curr_pc before the goto
78986 	 *  takes place.
78987 	 *
78988 	 *  The interpreter must be very careful with memory pointers, as
78989 	 *  many pointers are not guaranteed to be 'stable' and may be
78990 	 *  reallocated and relocated on-the-fly quite easily (e.g. by a
78991 	 *  memory allocation or a property access).
78992 	 *
78993 	 *  The following are assumed to have stable pointers:
78994 	 *    - the current thread
78995 	 *    - the current function
78996 	 *    - the bytecode, constant table, inner function table of the
78997 	 *      current function (as they are a part of the function allocation)
78998 	 *
78999 	 *  The following are assumed to have semi-stable pointers:
79000 	 *    - the current activation entry: stable as long as callstack
79001 	 *      is not changed (reallocated by growing or shrinking), or
79002 	 *      by any garbage collection invocation (through finalizers)
79003 	 *    - Note in particular that ANY DECREF can invalidate the
79004 	 *      activation pointer, so for the most part a fresh lookup
79005 	 *      is required
79006 	 *
79007 	 *  The following are not assumed to have stable pointers at all:
79008 	 *    - the value stack (registers) of the current thread
79009 	 *
79010 	 *  See execution.rst for discussion.
79011 	 */
79012 
79013  restart_execution:
79014 
79015 	/* Lookup current thread; use the stable 'entry_thread' for this to
79016 	 * avoid clobber warnings.  Any valid, reachable 'thr' value would be
79017 	 * fine for this, so using 'entry_thread' is just to silence warnings.
79018 	 */
79019 	thr = entry_thread->heap->curr_thread;
79020 	DUK_ASSERT(thr != NULL);
79021 	DUK_ASSERT(thr->callstack_top >= 1);
79022 	DUK_ASSERT(thr->callstack_curr != NULL);
79023 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);
79024 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
79025 
79026 	DUK_GC_TORTURE(thr->heap);
79027 
79028 	thr->ptr_curr_pc = &curr_pc;
79029 
79030 	/* Relookup and initialize dispatch loop variables.  Debugger check. */
79031 	{
79032 		duk_activation *act;
79033 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
79034 		duk_hcompfunc *fun;
79035 #endif
79036 
79037 		/* Assume interrupt init/counter are properly initialized here. */
79038 		/* Assume that thr->valstack_bottom has been set-up before getting here. */
79039 
79040 		act = thr->callstack_curr;
79041 		DUK_ASSERT(act != NULL);
79042 		fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
79043 		DUK_ASSERT(fun != NULL);
79044 		DUK_ASSERT(thr->valstack_top - thr->valstack_bottom == fun->nregs);
79045 		consts = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, fun);
79046 		DUK_ASSERT(consts != NULL);
79047 
79048 #if defined(DUK_USE_DEBUGGER_SUPPORT)
79049 		if (DUK_UNLIKELY(duk_debug_is_attached(thr->heap) && !thr->heap->dbg_processing)) {
79050 			duk__executor_recheck_debugger(thr, act, fun);
79051 			DUK_ASSERT(act == thr->callstack_curr);
79052 			DUK_ASSERT(act != NULL);
79053 		}
79054 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
79055 
79056 #if defined(DUK_USE_ASSERTIONS)
79057 		valstack_top_base = (duk_size_t) (thr->valstack_top - thr->valstack);
79058 #endif
79059 
79060 		/* Set up curr_pc for opcode dispatch. */
79061 		curr_pc = act->curr_pc;
79062 	}
79063 
79064 	DUK_DD(DUK_DDPRINT("restarting execution, thr %p, act idx %ld, fun %p,"
79065 	                   "consts %p, funcs %p, lev %ld, regbot %ld, regtop %ld, "
79066 	                   "preventcount=%ld",
79067 	                   (void *) thr,
79068 	                   (long) (thr->callstack_top - 1),
79069 	                   (void *) DUK__FUN(),
79070 	                   (void *) DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, DUK__FUN()),
79071 	                   (void *) DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, DUK__FUN()),
79072 	                   (long) (thr->callstack_top - 1),
79073 	                   (long) (thr->valstack_bottom - thr->valstack),
79074 	                   (long) (thr->valstack_top - thr->valstack),
79075 	                   (long) thr->callstack_preventcount));
79076 
79077 	/* Dispatch loop. */
79078 
79079 	for (;;) {
79080 		duk_uint8_t op;
79081 
79082 		DUK_ASSERT(thr->callstack_top >= 1);
79083 		DUK_ASSERT(thr->valstack_top - thr->valstack_bottom == DUK__FUN()->nregs);
79084 		DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) == valstack_top_base);
79085 
79086 		/* Executor interrupt counter check, used to implement breakpoints,
79087 		 * debugging interface, execution timeouts, etc.  The counter is heap
79088 		 * specific but is maintained in the current thread to make the check
79089 		 * as fast as possible.  The counter is copied back to the heap struct
79090 		 * whenever a thread switch occurs by the DUK_HEAP_SWITCH_THREAD() macro.
79091 		 */
79092 #if defined(DUK_USE_INTERRUPT_COUNTER)
79093 		int_ctr = thr->interrupt_counter;
79094 		if (DUK_LIKELY(int_ctr > 0)) {
79095 			thr->interrupt_counter = int_ctr - 1;
79096 		} else {
79097 			/* Trigger at zero or below */
79098 			duk_small_uint_t exec_int_ret;
79099 
79100 			DUK_STATS_INC(thr->heap, stats_exec_interrupt);
79101 
79102 			/* Write curr_pc back for the debugger. */
79103 			{
79104 				duk_activation *act;
79105 				DUK_ASSERT(thr->callstack_top > 0);
79106 				act = thr->callstack_curr;
79107 				DUK_ASSERT(act != NULL);
79108 				act->curr_pc = (duk_instr_t *) curr_pc;
79109 			}
79110 
79111 			/* Forced restart caused by a function return; must recheck
79112 			 * debugger breakpoints before checking line transitions,
79113 			 * see GH-303.  Restart and then handle interrupt_counter
79114 			 * zero again.
79115 			 */
79116 #if defined(DUK_USE_DEBUGGER_SUPPORT)
79117 			if (thr->heap->dbg_force_restart) {
79118 				DUK_DD(DUK_DDPRINT("dbg_force_restart flag forced restart execution"));  /* GH-303 */
79119 				thr->heap->dbg_force_restart = 0;
79120 				goto restart_execution;
79121 			}
79122 #endif
79123 
79124 			exec_int_ret = duk__executor_interrupt(thr);
79125 			if (exec_int_ret == DUK__INT_RESTART) {
79126 				/* curr_pc synced back above */
79127 				goto restart_execution;
79128 			}
79129 		}
79130 #endif  /* DUK_USE_INTERRUPT_COUNTER */
79131 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
79132 		/* For cross-checking during development: ensure dispatch count
79133 		 * matches cumulative interrupt counter init value sums.
79134 		 */
79135 		thr->heap->inst_count_exec++;
79136 #endif
79137 
79138 #if defined(DUK_USE_ASSERTIONS) || defined(DUK_USE_DEBUG)
79139 		{
79140 			duk_activation *act;
79141 			act = thr->callstack_curr;
79142 			DUK_ASSERT(curr_pc >= DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, DUK__FUN()));
79143 			DUK_ASSERT(curr_pc < DUK_HCOMPFUNC_GET_CODE_END(thr->heap, DUK__FUN()));
79144 			DUK_UNREF(act);  /* if debugging disabled */
79145 
79146 			DUK_DDD(DUK_DDDPRINT("executing bytecode: pc=%ld, ins=0x%08lx, op=%ld, valstack_top=%ld/%ld, nregs=%ld  -->  %!I",
79147 			                     (long) (curr_pc - DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, DUK__FUN())),
79148 			                     (unsigned long) *curr_pc,
79149 			                     (long) DUK_DEC_OP(*curr_pc),
79150 			                     (long) (thr->valstack_top - thr->valstack),
79151 			                     (long) (thr->valstack_end - thr->valstack),
79152 			                     (long) (DUK__FUN() ? DUK__FUN()->nregs : -1),
79153 			                     (duk_instr_t) *curr_pc));
79154 		}
79155 #endif
79156 
79157 #if defined(DUK_USE_ASSERTIONS)
79158 		/* Quite heavy assert: check valstack policy.  Improper
79159 		 * shuffle instructions can write beyond valstack_top/end
79160 		 * so this check catches them in the act.
79161 		 */
79162 		{
79163 			duk_tval *tv;
79164 			tv = thr->valstack_top;
79165 			while (tv != thr->valstack_end) {
79166 				DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
79167 				tv++;
79168 			}
79169 		}
79170 #endif
79171 
79172 		ins = *curr_pc++;
79173 		DUK_STATS_INC(thr->heap, stats_exec_opcodes);
79174 
79175 		/* Typing: use duk_small_(u)int_fast_t when decoding small
79176 		 * opcode fields (op, A, B, C, BC) which fit into 16 bits
79177 		 * and duk_(u)int_fast_t when decoding larger fields (e.g.
79178 		 * ABC).  Use unsigned variant by default, signed when the
79179 		 * value is used in signed arithmetic.  Using variable names
79180 		 * such as 'a', 'b', 'c', 'bc', etc makes it easier to spot
79181 		 * typing mismatches.
79182 		 */
79183 
79184 		/* Switch based on opcode.  Cast to 8-bit unsigned value and
79185 		 * use a fully populated case clauses so that the compiler
79186 		 * will (at least usually) omit a bounds check.
79187 		 */
79188 		op = (duk_uint8_t) DUK_DEC_OP(ins);
79189 		switch (op) {
79190 
79191 		/* Some useful macros.  These access inner executor variables
79192 		 * directly so they only apply within the executor.
79193 		 */
79194 #if defined(DUK_USE_EXEC_PREFER_SIZE)
79195 #define DUK__REPLACE_TOP_A_BREAK() { goto replace_top_a; }
79196 #define DUK__REPLACE_TOP_BC_BREAK() { goto replace_top_bc; }
79197 #define DUK__REPLACE_BOOL_A_BREAK(bval) { \
79198 		duk_bool_t duk__bval; \
79199 		duk__bval = (bval); \
79200 		DUK_ASSERT(duk__bval == 0 || duk__bval == 1); \
79201 		duk_push_boolean(thr, duk__bval); \
79202 		DUK__REPLACE_TOP_A_BREAK(); \
79203 	}
79204 #else
79205 #define DUK__REPLACE_TOP_A_BREAK() { DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_A(ins)); break; }
79206 #define DUK__REPLACE_TOP_BC_BREAK() { DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_BC(ins)); break; }
79207 #define DUK__REPLACE_BOOL_A_BREAK(bval) { \
79208 		duk_bool_t duk__bval; \
79209 		duk_tval *duk__tvdst; \
79210 		duk__bval = (bval); \
79211 		DUK_ASSERT(duk__bval == 0 || duk__bval == 1); \
79212 		duk__tvdst = DUK__REGP_A(ins); \
79213 		DUK_TVAL_SET_BOOLEAN_UPDREF(thr, duk__tvdst, duk__bval); \
79214 		break; \
79215 	}
79216 #endif
79217 
79218 		/* XXX: 12 + 12 bit variant might make sense too, for both reg and
79219 		 * const loads.
79220 		 */
79221 
79222 		/* For LDREG, STREG, LDCONST footprint optimized variants would just
79223 		 * duk_dup() + duk_replace(), but because they're used quite a lot
79224 		 * they're currently intentionally not size optimized.
79225 		 */
79226 		case DUK_OP_LDREG: {
79227 			duk_tval *tv1, *tv2;
79228 
79229 			tv1 = DUK__REGP_A(ins);
79230 			tv2 = DUK__REGP_BC(ins);
79231 			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2);  /* side effects */
79232 			break;
79233 		}
79234 
79235 		case DUK_OP_STREG: {
79236 			duk_tval *tv1, *tv2;
79237 
79238 			tv1 = DUK__REGP_A(ins);
79239 			tv2 = DUK__REGP_BC(ins);
79240 			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv2, tv1);  /* side effects */
79241 			break;
79242 		}
79243 
79244 		case DUK_OP_LDCONST: {
79245 			duk_tval *tv1, *tv2;
79246 
79247 			tv1 = DUK__REGP_A(ins);
79248 			tv2 = DUK__CONSTP_BC(ins);
79249 			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2);  /* side effects */
79250 			break;
79251 		}
79252 
79253 		/* LDINT and LDINTX are intended to load an arbitrary signed
79254 		 * 32-bit value.  Only an LDINT+LDINTX sequence is supported.
79255 		 * This also guarantees all values remain fastints.
79256 		 */
79257 #if defined(DUK_USE_EXEC_PREFER_SIZE)
79258 		case DUK_OP_LDINT: {
79259 			duk_int32_t val;
79260 
79261 			val = (duk_int32_t) DUK_DEC_BC(ins) - (duk_int32_t) DUK_BC_LDINT_BIAS;
79262 			duk_push_int(thr, val);
79263 			DUK__REPLACE_TOP_A_BREAK();
79264 		}
79265 		case DUK_OP_LDINTX: {
79266 			duk_int32_t val;
79267 
79268 			val = (duk_int32_t) duk_get_int(thr, DUK_DEC_A(ins));
79269 			val = (val << DUK_BC_LDINTX_SHIFT) + (duk_int32_t) DUK_DEC_BC(ins);  /* no bias */
79270 			duk_push_int(thr, val);
79271 			DUK__REPLACE_TOP_A_BREAK();
79272 		}
79273 #else  /* DUK_USE_EXEC_PREFER_SIZE */
79274 		case DUK_OP_LDINT: {
79275 			duk_tval *tv1;
79276 			duk_int32_t val;
79277 
79278 			val = (duk_int32_t) DUK_DEC_BC(ins) - (duk_int32_t) DUK_BC_LDINT_BIAS;
79279 			tv1 = DUK__REGP_A(ins);
79280 			DUK_TVAL_SET_I32_UPDREF(thr, tv1, val);  /* side effects */
79281 			break;
79282 		}
79283 		case DUK_OP_LDINTX: {
79284 			duk_tval *tv1;
79285 			duk_int32_t val;
79286 
79287 			tv1 = DUK__REGP_A(ins);
79288 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
79289 #if defined(DUK_USE_FASTINT)
79290 			DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
79291 			val = DUK_TVAL_GET_FASTINT_I32(tv1);
79292 #else
79293 			/* XXX: fast double-to-int conversion, we know number is integer in [-0x80000000,0xffffffff]. */
79294 			val = (duk_int32_t) DUK_TVAL_GET_NUMBER(tv1);
79295 #endif
79296 			val = (duk_int32_t) ((duk_uint32_t) val << DUK_BC_LDINTX_SHIFT) + (duk_int32_t) DUK_DEC_BC(ins);  /* no bias */
79297 			DUK_TVAL_SET_I32_UPDREF(thr, tv1, val);  /* side effects */
79298 			break;
79299 		}
79300 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
79301 
79302 #if defined(DUK_USE_EXEC_PREFER_SIZE)
79303 		case DUK_OP_LDTHIS: {
79304 			duk_push_this(thr);
79305 			DUK__REPLACE_TOP_BC_BREAK();
79306 		}
79307 		case DUK_OP_LDUNDEF: {
79308 			duk_to_undefined(thr, (duk_idx_t) DUK_DEC_BC(ins));
79309 			break;
79310 		}
79311 		case DUK_OP_LDNULL: {
79312 			duk_to_null(thr, (duk_idx_t) DUK_DEC_BC(ins));
79313 			break;
79314 		}
79315 		case DUK_OP_LDTRUE: {
79316 			duk_push_true(thr);
79317 			DUK__REPLACE_TOP_BC_BREAK();
79318 		}
79319 		case DUK_OP_LDFALSE: {
79320 			duk_push_false(thr);
79321 			DUK__REPLACE_TOP_BC_BREAK();
79322 		}
79323 #else  /* DUK_USE_EXEC_PREFER_SIZE */
79324 		case DUK_OP_LDTHIS: {
79325 			/* Note: 'this' may be bound to any value, not just an object */
79326 			duk_tval *tv1, *tv2;
79327 
79328 			tv1 = DUK__REGP_BC(ins);
79329 			tv2 = thr->valstack_bottom - 1;  /* 'this binding' is just under bottom */
79330 			DUK_ASSERT(tv2 >= thr->valstack);
79331 			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2);  /* side effects */
79332 			break;
79333 		}
79334 		case DUK_OP_LDUNDEF: {
79335 			duk_tval *tv1;
79336 
79337 			tv1 = DUK__REGP_BC(ins);
79338 			DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */
79339 			break;
79340 		}
79341 		case DUK_OP_LDNULL: {
79342 			duk_tval *tv1;
79343 
79344 			tv1 = DUK__REGP_BC(ins);
79345 			DUK_TVAL_SET_NULL_UPDREF(thr, tv1);  /* side effects */
79346 			break;
79347 		}
79348 		case DUK_OP_LDTRUE: {
79349 			duk_tval *tv1;
79350 
79351 			tv1 = DUK__REGP_BC(ins);
79352 			DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv1, 1);  /* side effects */
79353 			break;
79354 		}
79355 		case DUK_OP_LDFALSE: {
79356 			duk_tval *tv1;
79357 
79358 			tv1 = DUK__REGP_BC(ins);
79359 			DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv1, 0);  /* side effects */
79360 			break;
79361 		}
79362 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
79363 
79364 		case DUK_OP_BNOT: {
79365 			duk__vm_bitwise_not(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins));
79366 			break;
79367 		}
79368 
79369 		case DUK_OP_LNOT: {
79370 			duk__vm_logical_not(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins));
79371 			break;
79372 		}
79373 
79374 #if defined(DUK_USE_EXEC_PREFER_SIZE)
79375 		case DUK_OP_UNM:
79376 		case DUK_OP_UNP: {
79377 			duk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), op);
79378 			break;
79379 		}
79380 #else  /* DUK_USE_EXEC_PREFER_SIZE */
79381 		case DUK_OP_UNM: {
79382 			duk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), DUK_OP_UNM);
79383 			break;
79384 		}
79385 		case DUK_OP_UNP: {
79386 			duk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), DUK_OP_UNP);
79387 			break;
79388 		}
79389 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
79390 
79391 #if defined(DUK_USE_EXEC_PREFER_SIZE)
79392 		case DUK_OP_TYPEOF: {
79393 			duk_small_uint_t stridx;
79394 
79395 			stridx = duk_js_typeof_stridx(DUK__REGP_BC(ins));
79396 			DUK_ASSERT_STRIDX_VALID(stridx);
79397 			duk_push_hstring_stridx(thr, stridx);
79398 			DUK__REPLACE_TOP_A_BREAK();
79399 		}
79400 #else  /* DUK_USE_EXEC_PREFER_SIZE */
79401 		case DUK_OP_TYPEOF: {
79402 			duk_tval *tv;
79403 			duk_small_uint_t stridx;
79404 			duk_hstring *h_str;
79405 
79406 			tv = DUK__REGP_BC(ins);
79407 			stridx = duk_js_typeof_stridx(tv);
79408 			DUK_ASSERT_STRIDX_VALID(stridx);
79409 			h_str = DUK_HTHREAD_GET_STRING(thr, stridx);
79410 			tv = DUK__REGP_A(ins);
79411 			DUK_TVAL_SET_STRING_UPDREF(thr, tv, h_str);
79412 			break;
79413 		}
79414 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
79415 
79416 		case DUK_OP_TYPEOFID: {
79417 			duk_small_uint_t stridx;
79418 #if !defined(DUK_USE_EXEC_PREFER_SIZE)
79419 			duk_hstring *h_str;
79420 #endif
79421 			duk_activation *act;
79422 			duk_hstring *name;
79423 			duk_tval *tv;
79424 
79425 			/* A -> target register
79426 			 * BC -> constant index of identifier name
79427 			 */
79428 
79429 			tv = DUK__CONSTP_BC(ins);
79430 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv));
79431 			name = DUK_TVAL_GET_STRING(tv);
79432 			tv = NULL;  /* lookup has side effects */
79433 			act = thr->callstack_curr;
79434 			if (duk_js_getvar_activation(thr, act, name, 0 /*throw*/)) {
79435 				/* -> [... val this] */
79436 				tv = DUK_GET_TVAL_NEGIDX(thr, -2);
79437 				stridx = duk_js_typeof_stridx(tv);
79438 				tv = NULL;  /* no longer needed */
79439 				duk_pop_2_unsafe(thr);
79440 			} else {
79441 				/* unresolvable, no stack changes */
79442 				stridx = DUK_STRIDX_LC_UNDEFINED;
79443 			}
79444 			DUK_ASSERT_STRIDX_VALID(stridx);
79445 #if defined(DUK_USE_EXEC_PREFER_SIZE)
79446 			duk_push_hstring_stridx(thr, stridx);
79447 			DUK__REPLACE_TOP_A_BREAK();
79448 #else  /* DUK_USE_EXEC_PREFER_SIZE */
79449 			h_str = DUK_HTHREAD_GET_STRING(thr, stridx);
79450 			tv = DUK__REGP_A(ins);
79451 			DUK_TVAL_SET_STRING_UPDREF(thr, tv, h_str);
79452 			break;
79453 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
79454 		}
79455 
79456 		/* Equality: E5 Sections 11.9.1, 11.9.3 */
79457 
79458 #define DUK__EQ_BODY(barg,carg) { \
79459 		duk_bool_t tmp; \
79460 		tmp = duk_js_equals(thr, (barg), (carg)); \
79461 		DUK_ASSERT(tmp == 0 || tmp == 1); \
79462 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
79463 	}
79464 #define DUK__NEQ_BODY(barg,carg) { \
79465 		duk_bool_t tmp; \
79466 		tmp = duk_js_equals(thr, (barg), (carg)); \
79467 		DUK_ASSERT(tmp == 0 || tmp == 1); \
79468 		tmp ^= 1; \
79469 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
79470 	}
79471 #define DUK__SEQ_BODY(barg,carg) { \
79472 		duk_bool_t tmp; \
79473 		tmp = duk_js_strict_equals((barg), (carg)); \
79474 		DUK_ASSERT(tmp == 0 || tmp == 1); \
79475 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
79476 	}
79477 #define DUK__SNEQ_BODY(barg,carg) { \
79478 		duk_bool_t tmp; \
79479 		tmp = duk_js_strict_equals((barg), (carg)); \
79480 		DUK_ASSERT(tmp == 0 || tmp == 1); \
79481 		tmp ^= 1; \
79482 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
79483 	}
79484 #if defined(DUK_USE_EXEC_PREFER_SIZE)
79485 		case DUK_OP_EQ_RR:
79486 		case DUK_OP_EQ_CR:
79487 		case DUK_OP_EQ_RC:
79488 		case DUK_OP_EQ_CC:
79489 			DUK__EQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
79490 		case DUK_OP_NEQ_RR:
79491 		case DUK_OP_NEQ_CR:
79492 		case DUK_OP_NEQ_RC:
79493 		case DUK_OP_NEQ_CC:
79494 			DUK__NEQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
79495 		case DUK_OP_SEQ_RR:
79496 		case DUK_OP_SEQ_CR:
79497 		case DUK_OP_SEQ_RC:
79498 		case DUK_OP_SEQ_CC:
79499 			DUK__SEQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
79500 		case DUK_OP_SNEQ_RR:
79501 		case DUK_OP_SNEQ_CR:
79502 		case DUK_OP_SNEQ_RC:
79503 		case DUK_OP_SNEQ_CC:
79504 			DUK__SNEQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
79505 #else  /* DUK_USE_EXEC_PREFER_SIZE */
79506 		case DUK_OP_EQ_RR:
79507 			DUK__EQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
79508 		case DUK_OP_EQ_CR:
79509 			DUK__EQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
79510 		case DUK_OP_EQ_RC:
79511 			DUK__EQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
79512 		case DUK_OP_EQ_CC:
79513 			DUK__EQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
79514 		case DUK_OP_NEQ_RR:
79515 			DUK__NEQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
79516 		case DUK_OP_NEQ_CR:
79517 			DUK__NEQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
79518 		case DUK_OP_NEQ_RC:
79519 			DUK__NEQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
79520 		case DUK_OP_NEQ_CC:
79521 			DUK__NEQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
79522 		case DUK_OP_SEQ_RR:
79523 			DUK__SEQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
79524 		case DUK_OP_SEQ_CR:
79525 			DUK__SEQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
79526 		case DUK_OP_SEQ_RC:
79527 			DUK__SEQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
79528 		case DUK_OP_SEQ_CC:
79529 			DUK__SEQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
79530 		case DUK_OP_SNEQ_RR:
79531 			DUK__SNEQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
79532 		case DUK_OP_SNEQ_CR:
79533 			DUK__SNEQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
79534 		case DUK_OP_SNEQ_RC:
79535 			DUK__SNEQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
79536 		case DUK_OP_SNEQ_CC:
79537 			DUK__SNEQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
79538 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
79539 
79540 #define DUK__COMPARE_BODY(arg1,arg2,flags) { \
79541 		duk_bool_t tmp; \
79542 		tmp = duk_js_compare_helper(thr, (arg1), (arg2), (flags)); \
79543 		DUK_ASSERT(tmp == 0 || tmp == 1); \
79544 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
79545 	}
79546 #define DUK__GT_BODY(barg,carg) DUK__COMPARE_BODY((carg), (barg), 0)
79547 #define DUK__GE_BODY(barg,carg) DUK__COMPARE_BODY((barg), (carg), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST | DUK_COMPARE_FLAG_NEGATE)
79548 #define DUK__LT_BODY(barg,carg) DUK__COMPARE_BODY((barg), (carg), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST)
79549 #define DUK__LE_BODY(barg,carg) DUK__COMPARE_BODY((carg), (barg), DUK_COMPARE_FLAG_NEGATE)
79550 #if defined(DUK_USE_EXEC_PREFER_SIZE)
79551 		case DUK_OP_GT_RR:
79552 		case DUK_OP_GT_CR:
79553 		case DUK_OP_GT_RC:
79554 		case DUK_OP_GT_CC:
79555 			DUK__GT_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
79556 		case DUK_OP_GE_RR:
79557 		case DUK_OP_GE_CR:
79558 		case DUK_OP_GE_RC:
79559 		case DUK_OP_GE_CC:
79560 			DUK__GE_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
79561 		case DUK_OP_LT_RR:
79562 		case DUK_OP_LT_CR:
79563 		case DUK_OP_LT_RC:
79564 		case DUK_OP_LT_CC:
79565 			DUK__LT_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
79566 		case DUK_OP_LE_RR:
79567 		case DUK_OP_LE_CR:
79568 		case DUK_OP_LE_RC:
79569 		case DUK_OP_LE_CC:
79570 			DUK__LE_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
79571 #else  /* DUK_USE_EXEC_PREFER_SIZE */
79572 		case DUK_OP_GT_RR:
79573 			DUK__GT_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
79574 		case DUK_OP_GT_CR:
79575 			DUK__GT_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
79576 		case DUK_OP_GT_RC:
79577 			DUK__GT_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
79578 		case DUK_OP_GT_CC:
79579 			DUK__GT_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
79580 		case DUK_OP_GE_RR:
79581 			DUK__GE_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
79582 		case DUK_OP_GE_CR:
79583 			DUK__GE_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
79584 		case DUK_OP_GE_RC:
79585 			DUK__GE_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
79586 		case DUK_OP_GE_CC:
79587 			DUK__GE_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
79588 		case DUK_OP_LT_RR:
79589 			DUK__LT_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
79590 		case DUK_OP_LT_CR:
79591 			DUK__LT_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
79592 		case DUK_OP_LT_RC:
79593 			DUK__LT_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
79594 		case DUK_OP_LT_CC:
79595 			DUK__LT_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
79596 		case DUK_OP_LE_RR:
79597 			DUK__LE_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
79598 		case DUK_OP_LE_CR:
79599 			DUK__LE_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
79600 		case DUK_OP_LE_RC:
79601 			DUK__LE_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
79602 		case DUK_OP_LE_CC:
79603 			DUK__LE_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
79604 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
79605 
79606 		/* No size optimized variant at present for IF. */
79607 		case DUK_OP_IFTRUE_R: {
79608 			if (duk_js_toboolean(DUK__REGP_BC(ins)) != 0) {
79609 				curr_pc++;
79610 			}
79611 			break;
79612 		}
79613 		case DUK_OP_IFTRUE_C: {
79614 			if (duk_js_toboolean(DUK__CONSTP_BC(ins)) != 0) {
79615 				curr_pc++;
79616 			}
79617 			break;
79618 		}
79619 		case DUK_OP_IFFALSE_R: {
79620 			if (duk_js_toboolean(DUK__REGP_BC(ins)) == 0) {
79621 				curr_pc++;
79622 			}
79623 			break;
79624 		}
79625 		case DUK_OP_IFFALSE_C: {
79626 			if (duk_js_toboolean(DUK__CONSTP_BC(ins)) == 0) {
79627 				curr_pc++;
79628 			}
79629 			break;
79630 		}
79631 
79632 #if defined(DUK_USE_EXEC_PREFER_SIZE)
79633 		case DUK_OP_ADD_RR:
79634 		case DUK_OP_ADD_CR:
79635 		case DUK_OP_ADD_RC:
79636 		case DUK_OP_ADD_CC: {
79637 			/* XXX: could leave value on stack top and goto replace_top_a; */
79638 			duk__vm_arith_add(thr, DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins), DUK_DEC_A(ins));
79639 			break;
79640 		}
79641 #else  /* DUK_USE_EXEC_PREFER_SIZE */
79642 		case DUK_OP_ADD_RR: {
79643 			duk__vm_arith_add(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins));
79644 			break;
79645 		}
79646 		case DUK_OP_ADD_CR: {
79647 			duk__vm_arith_add(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins));
79648 			break;
79649 		}
79650 		case DUK_OP_ADD_RC: {
79651 			duk__vm_arith_add(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins));
79652 			break;
79653 		}
79654 		case DUK_OP_ADD_CC: {
79655 			duk__vm_arith_add(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins));
79656 			break;
79657 		}
79658 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
79659 
79660 #if defined(DUK_USE_EXEC_PREFER_SIZE)
79661 		case DUK_OP_SUB_RR:
79662 		case DUK_OP_SUB_CR:
79663 		case DUK_OP_SUB_RC:
79664 		case DUK_OP_SUB_CC:
79665 		case DUK_OP_MUL_RR:
79666 		case DUK_OP_MUL_CR:
79667 		case DUK_OP_MUL_RC:
79668 		case DUK_OP_MUL_CC:
79669 		case DUK_OP_DIV_RR:
79670 		case DUK_OP_DIV_CR:
79671 		case DUK_OP_DIV_RC:
79672 		case DUK_OP_DIV_CC:
79673 		case DUK_OP_MOD_RR:
79674 		case DUK_OP_MOD_CR:
79675 		case DUK_OP_MOD_RC:
79676 		case DUK_OP_MOD_CC:
79677 #if defined(DUK_USE_ES7_EXP_OPERATOR)
79678 		case DUK_OP_EXP_RR:
79679 		case DUK_OP_EXP_CR:
79680 		case DUK_OP_EXP_RC:
79681 		case DUK_OP_EXP_CC:
79682 #endif  /* DUK_USE_ES7_EXP_OPERATOR */
79683 		{
79684 			/* XXX: could leave value on stack top and goto replace_top_a; */
79685 			duk__vm_arith_binary_op(thr, DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins), DUK_DEC_A(ins), op);
79686 			break;
79687 		}
79688 #else  /* DUK_USE_EXEC_PREFER_SIZE */
79689 		case DUK_OP_SUB_RR: {
79690 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
79691 			break;
79692 		}
79693 		case DUK_OP_SUB_CR: {
79694 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
79695 			break;
79696 		}
79697 		case DUK_OP_SUB_RC: {
79698 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
79699 			break;
79700 		}
79701 		case DUK_OP_SUB_CC: {
79702 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
79703 			break;
79704 		}
79705 		case DUK_OP_MUL_RR: {
79706 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
79707 			break;
79708 		}
79709 		case DUK_OP_MUL_CR: {
79710 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
79711 			break;
79712 		}
79713 		case DUK_OP_MUL_RC: {
79714 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
79715 			break;
79716 		}
79717 		case DUK_OP_MUL_CC: {
79718 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
79719 			break;
79720 		}
79721 		case DUK_OP_DIV_RR: {
79722 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
79723 			break;
79724 		}
79725 		case DUK_OP_DIV_CR: {
79726 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
79727 			break;
79728 		}
79729 		case DUK_OP_DIV_RC: {
79730 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
79731 			break;
79732 		}
79733 		case DUK_OP_DIV_CC: {
79734 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
79735 			break;
79736 		}
79737 		case DUK_OP_MOD_RR: {
79738 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
79739 			break;
79740 		}
79741 		case DUK_OP_MOD_CR: {
79742 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
79743 			break;
79744 		}
79745 		case DUK_OP_MOD_RC: {
79746 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
79747 			break;
79748 		}
79749 		case DUK_OP_MOD_CC: {
79750 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
79751 			break;
79752 		}
79753 #if defined(DUK_USE_ES7_EXP_OPERATOR)
79754 		case DUK_OP_EXP_RR: {
79755 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
79756 			break;
79757 		}
79758 		case DUK_OP_EXP_CR: {
79759 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
79760 			break;
79761 		}
79762 		case DUK_OP_EXP_RC: {
79763 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
79764 			break;
79765 		}
79766 		case DUK_OP_EXP_CC: {
79767 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
79768 			break;
79769 		}
79770 #endif  /* DUK_USE_ES7_EXP_OPERATOR */
79771 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
79772 
79773 #if defined(DUK_USE_EXEC_PREFER_SIZE)
79774 		case DUK_OP_BAND_RR:
79775 		case DUK_OP_BAND_CR:
79776 		case DUK_OP_BAND_RC:
79777 		case DUK_OP_BAND_CC:
79778 		case DUK_OP_BOR_RR:
79779 		case DUK_OP_BOR_CR:
79780 		case DUK_OP_BOR_RC:
79781 		case DUK_OP_BOR_CC:
79782 		case DUK_OP_BXOR_RR:
79783 		case DUK_OP_BXOR_CR:
79784 		case DUK_OP_BXOR_RC:
79785 		case DUK_OP_BXOR_CC:
79786 		case DUK_OP_BASL_RR:
79787 		case DUK_OP_BASL_CR:
79788 		case DUK_OP_BASL_RC:
79789 		case DUK_OP_BASL_CC:
79790 		case DUK_OP_BLSR_RR:
79791 		case DUK_OP_BLSR_CR:
79792 		case DUK_OP_BLSR_RC:
79793 		case DUK_OP_BLSR_CC:
79794 		case DUK_OP_BASR_RR:
79795 		case DUK_OP_BASR_CR:
79796 		case DUK_OP_BASR_RC:
79797 		case DUK_OP_BASR_CC: {
79798 			/* XXX: could leave value on stack top and goto replace_top_a; */
79799 			duk__vm_bitwise_binary_op(thr, DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins), DUK_DEC_A(ins), op);
79800 			break;
79801 		}
79802 #else  /* DUK_USE_EXEC_PREFER_SIZE */
79803 		case DUK_OP_BAND_RR: {
79804 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
79805 			break;
79806 		}
79807 		case DUK_OP_BAND_CR: {
79808 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
79809 			break;
79810 		}
79811 		case DUK_OP_BAND_RC: {
79812 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
79813 			break;
79814 		}
79815 		case DUK_OP_BAND_CC: {
79816 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
79817 			break;
79818 		}
79819 		case DUK_OP_BOR_RR: {
79820 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
79821 			break;
79822 		}
79823 		case DUK_OP_BOR_CR: {
79824 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
79825 			break;
79826 		}
79827 		case DUK_OP_BOR_RC: {
79828 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
79829 			break;
79830 		}
79831 		case DUK_OP_BOR_CC: {
79832 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
79833 			break;
79834 		}
79835 		case DUK_OP_BXOR_RR: {
79836 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
79837 			break;
79838 		}
79839 		case DUK_OP_BXOR_CR: {
79840 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
79841 			break;
79842 		}
79843 		case DUK_OP_BXOR_RC: {
79844 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
79845 			break;
79846 		}
79847 		case DUK_OP_BXOR_CC: {
79848 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
79849 			break;
79850 		}
79851 		case DUK_OP_BASL_RR: {
79852 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
79853 			break;
79854 		}
79855 		case DUK_OP_BASL_CR: {
79856 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
79857 			break;
79858 		}
79859 		case DUK_OP_BASL_RC: {
79860 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
79861 			break;
79862 		}
79863 		case DUK_OP_BASL_CC: {
79864 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
79865 			break;
79866 		}
79867 		case DUK_OP_BLSR_RR: {
79868 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
79869 			break;
79870 		}
79871 		case DUK_OP_BLSR_CR: {
79872 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
79873 			break;
79874 		}
79875 		case DUK_OP_BLSR_RC: {
79876 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
79877 			break;
79878 		}
79879 		case DUK_OP_BLSR_CC: {
79880 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
79881 			break;
79882 		}
79883 		case DUK_OP_BASR_RR: {
79884 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
79885 			break;
79886 		}
79887 		case DUK_OP_BASR_CR: {
79888 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
79889 			break;
79890 		}
79891 		case DUK_OP_BASR_RC: {
79892 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
79893 			break;
79894 		}
79895 		case DUK_OP_BASR_CC: {
79896 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
79897 			break;
79898 		}
79899 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
79900 
79901 		/* For INSTOF and IN, B is always a register. */
79902 #define DUK__INSTOF_BODY(barg,carg) { \
79903 		duk_bool_t tmp; \
79904 		tmp = duk_js_instanceof(thr, (barg), (carg)); \
79905 		DUK_ASSERT(tmp == 0 || tmp == 1); \
79906 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
79907 	}
79908 #define DUK__IN_BODY(barg,carg) { \
79909 		duk_bool_t tmp; \
79910 		tmp = duk_js_in(thr, (barg), (carg)); \
79911 		DUK_ASSERT(tmp == 0 || tmp == 1); \
79912 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
79913 	}
79914 #if defined(DUK_USE_EXEC_PREFER_SIZE)
79915 		case DUK_OP_INSTOF_RR:
79916 		case DUK_OP_INSTOF_CR:
79917 		case DUK_OP_INSTOF_RC:
79918 		case DUK_OP_INSTOF_CC:
79919 			DUK__INSTOF_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
79920 		case DUK_OP_IN_RR:
79921 		case DUK_OP_IN_CR:
79922 		case DUK_OP_IN_RC:
79923 		case DUK_OP_IN_CC:
79924 			DUK__IN_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
79925 #else  /* DUK_USE_EXEC_PREFER_SIZE */
79926 		case DUK_OP_INSTOF_RR:
79927 			DUK__INSTOF_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
79928 		case DUK_OP_INSTOF_CR:
79929 			DUK__INSTOF_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
79930 		case DUK_OP_INSTOF_RC:
79931 			DUK__INSTOF_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
79932 		case DUK_OP_INSTOF_CC:
79933 			DUK__INSTOF_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
79934 		case DUK_OP_IN_RR:
79935 			DUK__IN_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
79936 		case DUK_OP_IN_CR:
79937 			DUK__IN_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
79938 		case DUK_OP_IN_RC:
79939 			DUK__IN_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
79940 		case DUK_OP_IN_CC:
79941 			DUK__IN_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
79942 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
79943 
79944 		/* Pre/post inc/dec for register variables, important for loops. */
79945 #if defined(DUK_USE_EXEC_PREFER_SIZE)
79946 		case DUK_OP_PREINCR:
79947 		case DUK_OP_PREDECR:
79948 		case DUK_OP_POSTINCR:
79949 		case DUK_OP_POSTDECR: {
79950 			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), op);
79951 			break;
79952 		}
79953 		case DUK_OP_PREINCV:
79954 		case DUK_OP_PREDECV:
79955 		case DUK_OP_POSTINCV:
79956 		case DUK_OP_POSTDECV: {
79957 			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), op, DUK__STRICT());
79958 			break;
79959 		}
79960 #else  /* DUK_USE_EXEC_PREFER_SIZE */
79961 		case DUK_OP_PREINCR: {
79962 			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_PREINCR);
79963 			break;
79964 		}
79965 		case DUK_OP_PREDECR: {
79966 			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_PREDECR);
79967 			break;
79968 		}
79969 		case DUK_OP_POSTINCR: {
79970 			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_POSTINCR);
79971 			break;
79972 		}
79973 		case DUK_OP_POSTDECR: {
79974 			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_POSTDECR);
79975 			break;
79976 		}
79977 		case DUK_OP_PREINCV: {
79978 			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_PREINCV, DUK__STRICT());
79979 			break;
79980 		}
79981 		case DUK_OP_PREDECV: {
79982 			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_PREDECV, DUK__STRICT());
79983 			break;
79984 		}
79985 		case DUK_OP_POSTINCV: {
79986 			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_POSTINCV, DUK__STRICT());
79987 			break;
79988 		}
79989 		case DUK_OP_POSTDECV: {
79990 			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_POSTDECV, DUK__STRICT());
79991 			break;
79992 		}
79993 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
79994 
79995 		/* XXX: Move to separate helper, optimize for perf/size separately. */
79996 		/* Preinc/predec for object properties. */
79997 		case DUK_OP_PREINCP_RR:
79998 		case DUK_OP_PREINCP_CR:
79999 		case DUK_OP_PREINCP_RC:
80000 		case DUK_OP_PREINCP_CC:
80001 		case DUK_OP_PREDECP_RR:
80002 		case DUK_OP_PREDECP_CR:
80003 		case DUK_OP_PREDECP_RC:
80004 		case DUK_OP_PREDECP_CC:
80005 		case DUK_OP_POSTINCP_RR:
80006 		case DUK_OP_POSTINCP_CR:
80007 		case DUK_OP_POSTINCP_RC:
80008 		case DUK_OP_POSTINCP_CC:
80009 		case DUK_OP_POSTDECP_RR:
80010 		case DUK_OP_POSTDECP_CR:
80011 		case DUK_OP_POSTDECP_RC:
80012 		case DUK_OP_POSTDECP_CC: {
80013 			duk_tval *tv_obj;
80014 			duk_tval *tv_key;
80015 			duk_tval *tv_val;
80016 			duk_bool_t rc;
80017 			duk_double_t x, y, z;
80018 #if !defined(DUK_USE_EXEC_PREFER_SIZE)
80019 			duk_tval *tv_dst;
80020 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
80021 
80022 			/* A -> target reg
80023 			 * B -> object reg/const (may be const e.g. in "'foo'[1]")
80024 			 * C -> key reg/const
80025 			 */
80026 
80027 			/* Opcode bits 0-1 are used to distinguish reg/const variants.
80028 			 * Opcode bits 2-3 are used to distinguish inc/dec variants:
80029 			 * Bit 2 = inc(0)/dec(1), bit 3 = pre(0)/post(1).
80030 			 */
80031 			DUK_ASSERT((DUK_OP_PREINCP_RR & 0x0c) == 0x00);
80032 			DUK_ASSERT((DUK_OP_PREDECP_RR & 0x0c) == 0x04);
80033 			DUK_ASSERT((DUK_OP_POSTINCP_RR & 0x0c) == 0x08);
80034 			DUK_ASSERT((DUK_OP_POSTDECP_RR & 0x0c) == 0x0c);
80035 
80036 			tv_obj = DUK__REGCONSTP_B(ins);
80037 			tv_key = DUK__REGCONSTP_C(ins);
80038 			rc = duk_hobject_getprop(thr, tv_obj, tv_key);  /* -> [val] */
80039 			DUK_UNREF(rc);  /* ignore */
80040 			tv_obj = NULL;  /* invalidated */
80041 			tv_key = NULL;  /* invalidated */
80042 
80043 			/* XXX: Fastint fast path would be useful here.  Also fastints
80044 			 * now lose their fastint status in current handling which is
80045 			 * not intuitive.
80046 			 */
80047 
80048 			x = duk_to_number_m1(thr);
80049 			duk_pop_unsafe(thr);
80050 			if (ins & DUK_BC_INCDECP_FLAG_DEC) {
80051 				y = x - 1.0;
80052 			} else {
80053 				y = x + 1.0;
80054 			}
80055 
80056 			duk_push_number(thr, y);
80057 			tv_val = DUK_GET_TVAL_NEGIDX(thr, -1);
80058 			DUK_ASSERT(tv_val != NULL);
80059 			tv_obj = DUK__REGCONSTP_B(ins);
80060 			tv_key = DUK__REGCONSTP_C(ins);
80061 			rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, DUK__STRICT());
80062 			DUK_UNREF(rc);  /* ignore */
80063 			tv_obj = NULL;  /* invalidated */
80064 			tv_key = NULL;  /* invalidated */
80065 			duk_pop_unsafe(thr);
80066 
80067 			z = (ins & DUK_BC_INCDECP_FLAG_POST) ? x : y;
80068 #if defined(DUK_USE_EXEC_PREFER_SIZE)
80069 			duk_push_number(thr, z);
80070 			DUK__REPLACE_TOP_A_BREAK();
80071 #else
80072 			tv_dst = DUK__REGP_A(ins);
80073 			DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_dst, z);
80074 			break;
80075 #endif
80076 		}
80077 
80078 		/* XXX: GETPROP where object is 'this', GETPROPT?
80079 		 * Occurs relatively often in object oriented code.
80080 		 */
80081 
80082 #define DUK__GETPROP_BODY(barg,carg) { \
80083 		/* A -> target reg \
80084 		 * B -> object reg/const (may be const e.g. in "'foo'[1]") \
80085 		 * C -> key reg/const \
80086 		 */ \
80087 		(void) duk_hobject_getprop(thr, (barg), (carg)); \
80088 		DUK__REPLACE_TOP_A_BREAK(); \
80089 	}
80090 #define DUK__GETPROPC_BODY(barg,carg) { \
80091 		/* Same as GETPROP but callability check for property-based calls. */ \
80092 		duk_tval *tv__targ; \
80093 		(void) duk_hobject_getprop(thr, (barg), (carg)); \
80094 		DUK_GC_TORTURE(thr->heap); \
80095 		tv__targ = DUK_GET_TVAL_NEGIDX(thr, -1); \
80096 		if (DUK_UNLIKELY(!duk_is_callable_tval(thr, tv__targ))) { \
80097 			/* Here we intentionally re-evaluate the macro \
80098 			 * arguments to deal with potentially changed \
80099 			 * valstack base pointer! \
80100 			 */ \
80101 			duk_call_setup_propcall_error(thr, (barg), (carg)); \
80102 		} \
80103 		DUK__REPLACE_TOP_A_BREAK(); \
80104 	}
80105 #define DUK__PUTPROP_BODY(aarg,barg,carg) { \
80106 		/* A -> object reg \
80107 		 * B -> key reg/const \
80108 		 * C -> value reg/const \
80109 		 * \
80110 		 * Note: intentional difference to register arrangement \
80111 		 * of e.g. GETPROP; 'A' must contain a register-only value. \
80112 		 */ \
80113 		(void) duk_hobject_putprop(thr, (aarg), (barg), (carg), DUK__STRICT()); \
80114 		break; \
80115 	}
80116 #define DUK__DELPROP_BODY(barg,carg) { \
80117 		/* A -> result reg \
80118 		 * B -> object reg \
80119 		 * C -> key reg/const \
80120 		 */ \
80121 		duk_bool_t rc; \
80122 		rc = duk_hobject_delprop(thr, (barg), (carg), DUK__STRICT()); \
80123 		DUK_ASSERT(rc == 0 || rc == 1); \
80124 		DUK__REPLACE_BOOL_A_BREAK(rc); \
80125 	}
80126 #if defined(DUK_USE_EXEC_PREFER_SIZE)
80127 		case DUK_OP_GETPROP_RR:
80128 		case DUK_OP_GETPROP_CR:
80129 		case DUK_OP_GETPROP_RC:
80130 		case DUK_OP_GETPROP_CC:
80131 			DUK__GETPROP_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
80132 #if defined(DUK_USE_VERBOSE_ERRORS)
80133 		case DUK_OP_GETPROPC_RR:
80134 		case DUK_OP_GETPROPC_CR:
80135 		case DUK_OP_GETPROPC_RC:
80136 		case DUK_OP_GETPROPC_CC:
80137 			DUK__GETPROPC_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
80138 #endif
80139 		case DUK_OP_PUTPROP_RR:
80140 		case DUK_OP_PUTPROP_CR:
80141 		case DUK_OP_PUTPROP_RC:
80142 		case DUK_OP_PUTPROP_CC:
80143 			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
80144 		case DUK_OP_DELPROP_RR:
80145 		case DUK_OP_DELPROP_RC:  /* B is always reg */
80146 			DUK__DELPROP_BODY(DUK__REGP_B(ins), DUK__REGCONSTP_C(ins));
80147 #else  /* DUK_USE_EXEC_PREFER_SIZE */
80148 		case DUK_OP_GETPROP_RR:
80149 			DUK__GETPROP_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
80150 		case DUK_OP_GETPROP_CR:
80151 			DUK__GETPROP_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
80152 		case DUK_OP_GETPROP_RC:
80153 			DUK__GETPROP_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
80154 		case DUK_OP_GETPROP_CC:
80155 			DUK__GETPROP_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
80156 #if defined(DUK_USE_VERBOSE_ERRORS)
80157 		case DUK_OP_GETPROPC_RR:
80158 			DUK__GETPROPC_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
80159 		case DUK_OP_GETPROPC_CR:
80160 			DUK__GETPROPC_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
80161 		case DUK_OP_GETPROPC_RC:
80162 			DUK__GETPROPC_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
80163 		case DUK_OP_GETPROPC_CC:
80164 			DUK__GETPROPC_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
80165 #endif
80166 		case DUK_OP_PUTPROP_RR:
80167 			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__REGP_B(ins), DUK__REGP_C(ins));
80168 		case DUK_OP_PUTPROP_CR:
80169 			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__CONSTP_B(ins), DUK__REGP_C(ins));
80170 		case DUK_OP_PUTPROP_RC:
80171 			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__REGP_B(ins), DUK__CONSTP_C(ins));
80172 		case DUK_OP_PUTPROP_CC:
80173 			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
80174 		case DUK_OP_DELPROP_RR:  /* B is always reg */
80175 			DUK__DELPROP_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
80176 		case DUK_OP_DELPROP_RC:
80177 			DUK__DELPROP_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
80178 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
80179 
80180 		/* No fast path for DECLVAR now, it's quite a rare instruction. */
80181 		case DUK_OP_DECLVAR_RR:
80182 		case DUK_OP_DECLVAR_CR:
80183 		case DUK_OP_DECLVAR_RC:
80184 		case DUK_OP_DECLVAR_CC: {
80185 			duk_activation *act;
80186 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
80187 			duk_tval *tv1;
80188 			duk_hstring *name;
80189 			duk_small_uint_t prop_flags;
80190 			duk_bool_t is_func_decl;
80191 
80192 			tv1 = DUK__REGCONSTP_B(ins);
80193 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
80194 			name = DUK_TVAL_GET_STRING(tv1);
80195 			DUK_ASSERT(name != NULL);
80196 
80197 			is_func_decl = ((a & DUK_BC_DECLVAR_FLAG_FUNC_DECL) != 0);
80198 
80199 			/* XXX: declvar takes an duk_tval pointer, which is awkward and
80200 			 * should be reworked.
80201 			 */
80202 
80203 			/* Compiler is responsible for selecting property flags (configurability,
80204 			 * writability, etc).
80205 			 */
80206 			prop_flags = a & DUK_PROPDESC_FLAGS_MASK;
80207 
80208 			if (is_func_decl) {
80209 				duk_push_tval(thr, DUK__REGCONSTP_C(ins));
80210 			} else {
80211 				DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* valstack policy */
80212 				thr->valstack_top++;
80213 			}
80214 			tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
80215 
80216 			act = thr->callstack_curr;
80217 			if (duk_js_declvar_activation(thr, act, name, tv1, prop_flags, is_func_decl)) {
80218 				if (is_func_decl) {
80219 					/* Already declared, update value. */
80220 					tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
80221 					duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
80222 				} else {
80223 					/* Already declared but no initializer value
80224 					 * (e.g. 'var xyz;'), no-op.
80225 					 */
80226 				}
80227 			}
80228 
80229 			duk_pop_unsafe(thr);
80230 			break;
80231 		}
80232 
80233 #if defined(DUK_USE_REGEXP_SUPPORT)
80234 		/* The compiler should never emit DUK_OP_REGEXP if there is no
80235 		 * regexp support.
80236 		 */
80237 		case DUK_OP_REGEXP_RR:
80238 		case DUK_OP_REGEXP_CR:
80239 		case DUK_OP_REGEXP_RC:
80240 		case DUK_OP_REGEXP_CC: {
80241 			/* A -> target register
80242 			 * B -> bytecode (also contains flags)
80243 			 * C -> escaped source
80244 			 */
80245 
80246 			duk_push_tval(thr, DUK__REGCONSTP_C(ins));
80247 			duk_push_tval(thr, DUK__REGCONSTP_B(ins));  /* -> [ ... escaped_source bytecode ] */
80248 			duk_regexp_create_instance(thr);   /* -> [ ... regexp_instance ] */
80249 			DUK__REPLACE_TOP_A_BREAK();
80250 		}
80251 #endif  /* DUK_USE_REGEXP_SUPPORT */
80252 
80253 		/* XXX: 'c' is unused, use whole BC, etc. */
80254 		case DUK_OP_CSVAR_RR:
80255 		case DUK_OP_CSVAR_CR:
80256 		case DUK_OP_CSVAR_RC:
80257 		case DUK_OP_CSVAR_CC: {
80258 			/* The speciality of calling through a variable binding is that the
80259 			 * 'this' value may be provided by the variable lookup: E5 Section 6.b.i.
80260 			 *
80261 			 * The only (standard) case where the 'this' binding is non-null is when
80262 			 *   (1) the variable is found in an object environment record, and
80263 			 *   (2) that object environment record is a 'with' block.
80264 			 */
80265 
80266 			duk_activation *act;
80267 			duk_uint_fast_t idx;
80268 			duk_tval *tv1;
80269 			duk_hstring *name;
80270 
80271 			/* A -> target registers (A, A + 1) for call setup
80272 			 * B -> identifier name, usually constant but can be a register due to shuffling
80273 			 */
80274 
80275 			tv1 = DUK__REGCONSTP_B(ins);
80276 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
80277 			name = DUK_TVAL_GET_STRING(tv1);
80278 			DUK_ASSERT(name != NULL);
80279 			act = thr->callstack_curr;
80280 			(void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/);  /* -> [... val this] */
80281 
80282 			idx = (duk_uint_fast_t) DUK_DEC_A(ins);
80283 
80284 			/* Could add direct value stack handling. */
80285 			duk_replace(thr, (duk_idx_t) (idx + 1));  /* 'this' binding */
80286 			duk_replace(thr, (duk_idx_t) idx);        /* variable value (function, we hope, not checked here) */
80287 			break;
80288 		}
80289 
80290 		case DUK_OP_CLOSURE: {
80291 			duk_activation *act;
80292 			duk_hcompfunc *fun_act;
80293 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
80294 			duk_hobject *fun_temp;
80295 
80296 			/* A -> target reg
80297 			 * BC -> inner function index
80298 			 */
80299 
80300 			DUK_DDD(DUK_DDDPRINT("CLOSURE to target register %ld, fnum %ld (count %ld)",
80301 			                     (long) DUK_DEC_A(ins), (long) DUK_DEC_BC(ins), (long) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, DUK__FUN())));
80302 
80303 			DUK_ASSERT_DISABLE(bc >= 0); /* unsigned */
80304 			DUK_ASSERT((duk_uint_t) bc < (duk_uint_t) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, DUK__FUN()));
80305 
80306 			act = thr->callstack_curr;
80307 			fun_act = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
80308 			fun_temp = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, fun_act)[bc];
80309 			DUK_ASSERT(fun_temp != NULL);
80310 			DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(fun_temp));
80311 
80312 			DUK_DDD(DUK_DDDPRINT("CLOSURE: function template is: %p -> %!O",
80313 			                     (void *) fun_temp, (duk_heaphdr *) fun_temp));
80314 
80315 			if (act->lex_env == NULL) {
80316 				DUK_ASSERT(act->var_env == NULL);
80317 				duk_js_init_activation_environment_records_delayed(thr, act);
80318 				act = thr->callstack_curr;
80319 			}
80320 			DUK_ASSERT(act->lex_env != NULL);
80321 			DUK_ASSERT(act->var_env != NULL);
80322 
80323 			/* functions always have a NEWENV flag, i.e. they get a
80324 			 * new variable declaration environment, so only lex_env
80325 			 * matters here.
80326 			 */
80327 			duk_js_push_closure(thr,
80328 			                    (duk_hcompfunc *) fun_temp,
80329 			                    act->var_env,
80330 			                    act->lex_env,
80331 			                    1 /*add_auto_proto*/);
80332 			DUK__REPLACE_TOP_A_BREAK();
80333 		}
80334 
80335 		case DUK_OP_GETVAR: {
80336 			duk_activation *act;
80337 			duk_tval *tv1;
80338 			duk_hstring *name;
80339 
80340 			tv1 = DUK__CONSTP_BC(ins);
80341 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
80342 			name = DUK_TVAL_GET_STRING(tv1);
80343 			DUK_ASSERT(name != NULL);
80344 			act = thr->callstack_curr;
80345 			DUK_ASSERT(act != NULL);
80346 			(void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/);  /* -> [... val this] */
80347 			duk_pop_unsafe(thr);  /* 'this' binding is not needed here */
80348 			DUK__REPLACE_TOP_A_BREAK();
80349 		}
80350 
80351 		case DUK_OP_PUTVAR: {
80352 			duk_activation *act;
80353 			duk_tval *tv1;
80354 			duk_hstring *name;
80355 
80356 			tv1 = DUK__CONSTP_BC(ins);
80357 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
80358 			name = DUK_TVAL_GET_STRING(tv1);
80359 			DUK_ASSERT(name != NULL);
80360 
80361 			/* XXX: putvar takes a duk_tval pointer, which is awkward and
80362 			 * should be reworked.
80363 			 */
80364 
80365 			tv1 = DUK__REGP_A(ins);  /* val */
80366 			act = thr->callstack_curr;
80367 			duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
80368 			break;
80369 		}
80370 
80371 		case DUK_OP_DELVAR: {
80372 			duk_activation *act;
80373 			duk_tval *tv1;
80374 			duk_hstring *name;
80375 			duk_bool_t rc;
80376 
80377 			tv1 = DUK__CONSTP_BC(ins);
80378 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
80379 			name = DUK_TVAL_GET_STRING(tv1);
80380 			DUK_ASSERT(name != NULL);
80381 			act = thr->callstack_curr;
80382 			rc = duk_js_delvar_activation(thr, act, name);
80383 			DUK__REPLACE_BOOL_A_BREAK(rc);
80384 		}
80385 
80386 		case DUK_OP_JUMP: {
80387 			/* Note: without explicit cast to signed, MSVC will
80388 			 * apparently generate a large positive jump when the
80389 			 * bias-corrected value would normally be negative.
80390 			 */
80391 			curr_pc += (duk_int_fast_t) DUK_DEC_ABC(ins) - (duk_int_fast_t) DUK_BC_JUMP_BIAS;
80392 			break;
80393 		}
80394 
80395 #define DUK__RETURN_SHARED() do { \
80396 		duk_small_uint_t ret_result; \
80397 		/* duk__handle_return() is guaranteed never to throw, except \
80398 		 * for potential out-of-memory situations which will then \
80399 		 * propagate out of the executor longjmp handler. \
80400 		 */ \
80401 		DUK_ASSERT(thr->ptr_curr_pc == NULL); \
80402 		ret_result = duk__handle_return(thr, entry_act); \
80403 		if (ret_result == DUK__RETHAND_RESTART) { \
80404 			goto restart_execution; \
80405 		} \
80406 		DUK_ASSERT(ret_result == DUK__RETHAND_FINISHED); \
80407 		return; \
80408 	} while (0)
80409 #if defined(DUK_USE_EXEC_PREFER_SIZE)
80410 		case DUK_OP_RETREG:
80411 		case DUK_OP_RETCONST:
80412 		case DUK_OP_RETCONSTN:
80413 		case DUK_OP_RETUNDEF: {
80414 			 /* BC -> return value reg/const */
80415 
80416 			DUK__SYNC_AND_NULL_CURR_PC();
80417 
80418 			if (op == DUK_OP_RETREG) {
80419 				duk_push_tval(thr, DUK__REGP_BC(ins));
80420 			} else if (op == DUK_OP_RETUNDEF) {
80421 				DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* valstack policy */
80422 				thr->valstack_top++;
80423 			} else {
80424 				DUK_ASSERT(op == DUK_OP_RETCONST || op == DUK_OP_RETCONSTN);
80425 				duk_push_tval(thr, DUK__CONSTP_BC(ins));
80426 			}
80427 
80428 			DUK__RETURN_SHARED();
80429 		}
80430 #else  /* DUK_USE_EXEC_PREFER_SIZE */
80431 		case DUK_OP_RETREG: {
80432 			duk_tval *tv;
80433 
80434 			DUK__SYNC_AND_NULL_CURR_PC();
80435 			tv = DUK__REGP_BC(ins);
80436 			DUK_TVAL_SET_TVAL(thr->valstack_top, tv);
80437 			DUK_TVAL_INCREF(thr, tv);
80438 			thr->valstack_top++;
80439 			DUK__RETURN_SHARED();
80440 		}
80441 		/* This will be unused without refcounting. */
80442 		case DUK_OP_RETCONST: {
80443 			duk_tval *tv;
80444 
80445 			DUK__SYNC_AND_NULL_CURR_PC();
80446 			tv = DUK__CONSTP_BC(ins);
80447 			DUK_TVAL_SET_TVAL(thr->valstack_top, tv);
80448 			DUK_TVAL_INCREF(thr, tv);
80449 			thr->valstack_top++;
80450 			DUK__RETURN_SHARED();
80451 		}
80452 		case DUK_OP_RETCONSTN: {
80453 			duk_tval *tv;
80454 
80455 			DUK__SYNC_AND_NULL_CURR_PC();
80456 			tv = DUK__CONSTP_BC(ins);
80457 			DUK_TVAL_SET_TVAL(thr->valstack_top, tv);
80458 #if defined(DUK_USE_REFERENCE_COUNTING)
80459 			/* Without refcounting only RETCONSTN is used. */
80460 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv));  /* no INCREF for this constant */
80461 #endif
80462 			thr->valstack_top++;
80463 			DUK__RETURN_SHARED();
80464 		}
80465 		case DUK_OP_RETUNDEF: {
80466 			DUK__SYNC_AND_NULL_CURR_PC();
80467 			thr->valstack_top++;  /* value at valstack top is already undefined by valstack policy */
80468 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));
80469 			DUK__RETURN_SHARED();
80470 		}
80471 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
80472 
80473 		case DUK_OP_LABEL: {
80474 			duk_activation *act;
80475 			duk_catcher *cat;
80476 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
80477 
80478 			/* Allocate catcher and populate it (must be atomic). */
80479 
80480 			cat = duk_hthread_catcher_alloc(thr);
80481 			DUK_ASSERT(cat != NULL);
80482 
80483 			cat->flags = (duk_uint32_t) (DUK_CAT_TYPE_LABEL | (bc << DUK_CAT_LABEL_SHIFT));
80484 			cat->pc_base = (duk_instr_t *) curr_pc;  /* pre-incremented, points to first jump slot */
80485 			cat->idx_base = 0;  /* unused for label */
80486 			cat->h_varname = NULL;
80487 
80488 			act = thr->callstack_curr;
80489 			DUK_ASSERT(act != NULL);
80490 			cat->parent = act->cat;
80491 			act->cat = cat;
80492 
80493 			DUK_DDD(DUK_DDDPRINT("LABEL catcher: flags=0x%08lx, pc_base=%ld, "
80494 			                     "idx_base=%ld, h_varname=%!O, label_id=%ld",
80495 			                     (long) cat->flags, (long) cat->pc_base,
80496 			                     (long) cat->idx_base, (duk_heaphdr *) cat->h_varname, (long) DUK_CAT_GET_LABEL(cat)));
80497 
80498 			curr_pc += 2;  /* skip jump slots */
80499 			break;
80500 		}
80501 
80502 		case DUK_OP_ENDLABEL: {
80503 			duk_activation *act;
80504 #if (defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)) || defined(DUK_USE_ASSERTIONS)
80505 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
80506 #endif
80507 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
80508 			DUK_DDD(DUK_DDDPRINT("ENDLABEL %ld", (long) bc));
80509 #endif
80510 
80511 			act = thr->callstack_curr;
80512 			DUK_ASSERT(act->cat != NULL);
80513 			DUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_LABEL);
80514 			DUK_ASSERT((duk_uint_fast_t) DUK_CAT_GET_LABEL(act->cat) == bc);
80515 			duk_hthread_catcher_unwind_nolexenv_norz(thr, act);
80516 
80517 			/* no need to unwind callstack */
80518 			break;
80519 		}
80520 
80521 		case DUK_OP_BREAK: {
80522 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
80523 
80524 			DUK__SYNC_AND_NULL_CURR_PC();
80525 			duk__handle_break_or_continue(thr, (duk_uint_t) bc, DUK_LJ_TYPE_BREAK);
80526 			goto restart_execution;
80527 		}
80528 
80529 		case DUK_OP_CONTINUE: {
80530 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
80531 
80532 			DUK__SYNC_AND_NULL_CURR_PC();
80533 			duk__handle_break_or_continue(thr, (duk_uint_t) bc, DUK_LJ_TYPE_CONTINUE);
80534 			goto restart_execution;
80535 		}
80536 
80537 		/* XXX: move to helper, too large to be inline here */
80538 		case DUK_OP_TRYCATCH: {
80539 			duk__handle_op_trycatch(thr, ins, curr_pc);
80540 			curr_pc += 2;  /* skip jump slots */
80541 			break;
80542 		}
80543 
80544 		case DUK_OP_ENDTRY: {
80545 			curr_pc = duk__handle_op_endtry(thr, ins);
80546 			break;
80547 		}
80548 
80549 		case DUK_OP_ENDCATCH: {
80550 			duk__handle_op_endcatch(thr, ins);
80551 			break;
80552 		}
80553 
80554 		case DUK_OP_ENDFIN: {
80555 			/* Sync and NULL early. */
80556 			DUK__SYNC_AND_NULL_CURR_PC();
80557 
80558 			if (duk__handle_op_endfin(thr, ins, entry_act) != 0) {
80559 				return;
80560 			}
80561 
80562 			/* Must restart because we NULLed out curr_pc. */
80563 			goto restart_execution;
80564 		}
80565 
80566 		case DUK_OP_THROW: {
80567 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
80568 
80569 			/* Note: errors are augmented when they are created, not
80570 			 * when they are thrown.  So, don't augment here, it would
80571 			 * break re-throwing for instance.
80572 			 */
80573 
80574 			/* Sync so that augmentation sees up-to-date activations, NULL
80575 			 * thr->ptr_curr_pc so that it's not used if side effects occur
80576 			 * in augmentation or longjmp handling.
80577 			 */
80578 			DUK__SYNC_AND_NULL_CURR_PC();
80579 
80580 			duk_dup(thr, (duk_idx_t) bc);
80581 			DUK_DDD(DUK_DDDPRINT("THROW ERROR (BYTECODE): %!dT (before throw augment)",
80582 			                     (duk_tval *) duk_get_tval(thr, -1)));
80583 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
80584 			duk_err_augment_error_throw(thr);
80585 			DUK_DDD(DUK_DDDPRINT("THROW ERROR (BYTECODE): %!dT (after throw augment)",
80586 			                     (duk_tval *) duk_get_tval(thr, -1)));
80587 #endif
80588 
80589 			duk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, DUK_GET_TVAL_NEGIDX(thr, -1));
80590 #if defined(DUK_USE_DEBUGGER_SUPPORT)
80591 			duk_err_check_debugger_integration(thr);
80592 #endif
80593 
80594 			DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* always in executor */
80595 			duk_err_longjmp(thr);
80596 			DUK_UNREACHABLE();
80597 			break;
80598 		}
80599 
80600 		case DUK_OP_CSREG: {
80601 			/*
80602 			 *  Assuming a register binds to a variable declared within this
80603 			 *  function (a declarative binding), the 'this' for the call
80604 			 *  setup is always 'undefined'.  E5 Section 10.2.1.1.6.
80605 			 */
80606 
80607 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
80608 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
80609 
80610 			/* A -> register containing target function (not type checked here)
80611 			 * BC -> target registers (BC, BC + 1) for call setup
80612 			 */
80613 
80614 #if defined(DUK_USE_PREFER_SIZE)
80615 			duk_dup(thr, (duk_idx_t) a);
80616 			duk_replace(thr, (duk_idx_t) bc);
80617 			duk_to_undefined(thr, (duk_idx_t) (bc + 1));
80618 #else
80619 			duk_tval *tv1;
80620 			duk_tval *tv2;
80621 			duk_tval *tv3;
80622 			duk_tval tv_tmp1;
80623 			duk_tval tv_tmp2;
80624 
80625 			tv1 = DUK__REGP(bc);
80626 			tv2 = tv1 + 1;
80627 			DUK_TVAL_SET_TVAL(&tv_tmp1, tv1);
80628 			DUK_TVAL_SET_TVAL(&tv_tmp2, tv2);
80629 			tv3 = DUK__REGP(a);
80630 			DUK_TVAL_SET_TVAL(tv1, tv3);
80631 			DUK_TVAL_INCREF(thr, tv1);  /* no side effects */
80632 			DUK_TVAL_SET_UNDEFINED(tv2);  /* no need for incref */
80633 			DUK_TVAL_DECREF(thr, &tv_tmp1);
80634 			DUK_TVAL_DECREF(thr, &tv_tmp2);
80635 #endif
80636 			break;
80637 		}
80638 
80639 
80640 		/* XXX: in some cases it's faster NOT to reuse the value
80641 		 * stack but rather copy the arguments on top of the stack
80642 		 * (mainly when the calling value stack is large and the value
80643 		 * stack resize would be large).
80644 		 */
80645 
80646 		case DUK_OP_CALL0:
80647 		case DUK_OP_CALL1:
80648 		case DUK_OP_CALL2:
80649 		case DUK_OP_CALL3:
80650 		case DUK_OP_CALL4:
80651 		case DUK_OP_CALL5:
80652 		case DUK_OP_CALL6:
80653 		case DUK_OP_CALL7: {
80654 			/* Opcode packs 4 flag bits: 1 for indirect, 3 map
80655 			 * 1:1 to three lowest call handling flags.
80656 			 *
80657 			 * A -> nargs or register with nargs (indirect)
80658 			 * BC -> base register for call (base -> func, base+1 -> this, base+2 -> arg1 ... base+2+N-1 -> argN)
80659 			 */
80660 
80661 			duk_idx_t nargs;
80662 			duk_idx_t idx;
80663 			duk_small_uint_t call_flags;
80664 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
80665 			duk_hcompfunc *fun;
80666 #endif
80667 
80668 			DUK_ASSERT((DUK_OP_CALL0 & 0x0fU) == 0);
80669 			DUK_ASSERT((ins & DUK_BC_CALL_FLAG_INDIRECT) == 0);
80670 
80671 			nargs = (duk_idx_t) DUK_DEC_A(ins);
80672 			call_flags = (ins & 0x07U) | DUK_CALL_FLAG_ALLOW_ECMATOECMA;
80673 			idx = (duk_idx_t) DUK_DEC_BC(ins);
80674 
80675 			if (duk__executor_handle_call(thr, idx, nargs, call_flags)) {
80676 				/* curr_pc synced by duk_handle_call_unprotected() */
80677 				DUK_ASSERT(thr->ptr_curr_pc == NULL);
80678 				goto restart_execution;
80679 			}
80680 			DUK_ASSERT(thr->ptr_curr_pc != NULL);
80681 
80682 			/* duk_js_call.c is required to restore the stack reserve
80683 			 * so we only need to reset the top.
80684 			 */
80685 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
80686 			fun = DUK__FUN();
80687 #endif
80688 			duk_set_top_unsafe(thr, (duk_idx_t) fun->nregs);
80689 
80690 			/* No need to reinit setjmp() catchpoint, as call handling
80691 			 * will store and restore our state.
80692 			 *
80693 			 * When debugger is enabled, we need to recheck the activation
80694 			 * status after returning.  This is now handled by call handling
80695 			 * and heap->dbg_force_restart.
80696 			 */
80697 			break;
80698 		}
80699 
80700 		case DUK_OP_CALL8:
80701 		case DUK_OP_CALL9:
80702 		case DUK_OP_CALL10:
80703 		case DUK_OP_CALL11:
80704 		case DUK_OP_CALL12:
80705 		case DUK_OP_CALL13:
80706 		case DUK_OP_CALL14:
80707 		case DUK_OP_CALL15: {
80708 			/* Indirect variant. */
80709 			duk_uint_fast_t nargs;
80710 			duk_idx_t idx;
80711 			duk_small_uint_t call_flags;
80712 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
80713 			duk_hcompfunc *fun;
80714 #endif
80715 
80716 			DUK_ASSERT((DUK_OP_CALL0 & 0x0fU) == 0);
80717 			DUK_ASSERT((ins & DUK_BC_CALL_FLAG_INDIRECT) != 0);
80718 
80719 			nargs = (duk_uint_fast_t) DUK_DEC_A(ins);
80720 			DUK__LOOKUP_INDIRECT(nargs);
80721 			call_flags = (ins & 0x07U) | DUK_CALL_FLAG_ALLOW_ECMATOECMA;
80722 			idx = (duk_idx_t) DUK_DEC_BC(ins);
80723 
80724 			if (duk__executor_handle_call(thr, idx, (duk_idx_t) nargs, call_flags)) {
80725 				DUK_ASSERT(thr->ptr_curr_pc == NULL);
80726 				goto restart_execution;
80727 			}
80728 			DUK_ASSERT(thr->ptr_curr_pc != NULL);
80729 
80730 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
80731 			fun = DUK__FUN();
80732 #endif
80733 			duk_set_top_unsafe(thr, (duk_idx_t) fun->nregs);
80734 			break;
80735 		}
80736 
80737 		case DUK_OP_NEWOBJ: {
80738 			duk_push_object(thr);
80739 #if defined(DUK_USE_ASSERTIONS)
80740 			{
80741 				duk_hobject *h;
80742 				h = duk_require_hobject(thr, -1);
80743 				DUK_ASSERT(DUK_HOBJECT_GET_ESIZE(h) == 0);
80744 				DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(h) == 0);
80745 				DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(h) == 0);
80746 				DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(h) == 0);
80747 			}
80748 #endif
80749 #if !defined(DUK_USE_PREFER_SIZE)
80750 			/* XXX: could do a direct props realloc, but need hash size */
80751 			duk_hobject_resize_entrypart(thr, duk_known_hobject(thr, -1), DUK_DEC_A(ins));
80752 #endif
80753 			DUK__REPLACE_TOP_BC_BREAK();
80754 		}
80755 
80756 		case DUK_OP_NEWARR: {
80757 			duk_push_array(thr);
80758 #if defined(DUK_USE_ASSERTIONS)
80759 			{
80760 				duk_hobject *h;
80761 				h = duk_require_hobject(thr, -1);
80762 				DUK_ASSERT(DUK_HOBJECT_GET_ESIZE(h) == 0);
80763 				DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(h) == 0);
80764 				DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(h) == 0);
80765 				DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(h) == 0);
80766 				DUK_ASSERT(DUK_HOBJECT_HAS_ARRAY_PART(h));
80767 			}
80768 #endif
80769 #if !defined(DUK_USE_PREFER_SIZE)
80770 			duk_hobject_realloc_props(thr,
80771 			                          duk_known_hobject(thr, -1),
80772 			                          0 /*new_e_size*/,
80773 			                          DUK_DEC_A(ins) /*new_a_size*/,
80774 			                          0 /*new_h_size*/,
80775 			                          0 /*abandon_array*/);
80776 #if 0
80777 			duk_hobject_resize_arraypart(thr, duk_known_hobject(thr, -1), DUK_DEC_A(ins));
80778 #endif
80779 #endif
80780 			DUK__REPLACE_TOP_BC_BREAK();
80781 		}
80782 
80783 		case DUK_OP_MPUTOBJ:
80784 		case DUK_OP_MPUTOBJI: {
80785 			duk_idx_t obj_idx;
80786 			duk_uint_fast_t idx, idx_end;
80787 			duk_small_uint_fast_t count;
80788 
80789 			/* A -> register of target object
80790 			 * B -> first register of key/value pair list
80791 			 *      or register containing first register number if indirect
80792 			 * C -> number of key/value pairs * 2
80793 			 *      (= number of value stack indices used starting from 'B')
80794 			 */
80795 
80796 			obj_idx = DUK_DEC_A(ins);
80797 			DUK_ASSERT(duk_is_object(thr, obj_idx));
80798 
80799 			idx = (duk_uint_fast_t) DUK_DEC_B(ins);
80800 			if (DUK_DEC_OP(ins) == DUK_OP_MPUTOBJI) {
80801 				DUK__LOOKUP_INDIRECT(idx);
80802 			}
80803 
80804 			count = (duk_small_uint_fast_t) DUK_DEC_C(ins);
80805 			DUK_ASSERT(count > 0);  /* compiler guarantees */
80806 			idx_end = idx + count;
80807 
80808 #if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
80809 			if (DUK_UNLIKELY(idx_end > (duk_uint_fast_t) duk_get_top(thr))) {
80810 				/* XXX: use duk_is_valid_index() instead? */
80811 				/* XXX: improve check; check against nregs, not against top */
80812 				DUK__INTERNAL_ERROR("MPUTOBJ out of bounds");
80813 			}
80814 #endif
80815 
80816 			/* Use 'force' flag to duk_def_prop() to ensure that any
80817 			 * inherited properties don't prevent the operation.
80818 			 * With ES2015 duplicate properties are allowed, so that we
80819 			 * must overwrite any previous data or accessor property.
80820 			 *
80821 			 * With ES2015 computed property names the literal keys
80822 			 * may be arbitrary values and need to be ToPropertyKey()
80823 			 * coerced at runtime.
80824 			 */
80825 			do {
80826 				/* XXX: faster initialization (direct access or better primitives) */
80827 				duk_dup(thr, (duk_idx_t) idx);
80828 				duk_dup(thr, (duk_idx_t) (idx + 1));
80829 				duk_def_prop(thr, obj_idx, DUK_DEFPROP_HAVE_VALUE |
80830 				                           DUK_DEFPROP_FORCE |
80831 				                           DUK_DEFPROP_SET_WRITABLE |
80832 				                           DUK_DEFPROP_SET_ENUMERABLE |
80833 				                           DUK_DEFPROP_SET_CONFIGURABLE);
80834 				idx += 2;
80835 			} while (idx < idx_end);
80836 			break;
80837 		}
80838 
80839 		case DUK_OP_INITSET:
80840 		case DUK_OP_INITGET: {
80841 			duk__handle_op_initset_initget(thr, ins);
80842 			break;
80843 		}
80844 
80845 		case DUK_OP_MPUTARR:
80846 		case DUK_OP_MPUTARRI: {
80847 			duk_idx_t obj_idx;
80848 			duk_uint_fast_t idx, idx_end;
80849 			duk_small_uint_fast_t count;
80850 			duk_tval *tv1;
80851 			duk_uint32_t arr_idx;
80852 
80853 			/* A -> register of target object
80854 			 * B -> first register of value data (start_index, value1, value2, ..., valueN)
80855 			 *      or register containing first register number if indirect
80856 			 * C -> number of key/value pairs (N)
80857 			 */
80858 
80859 			obj_idx = DUK_DEC_A(ins);
80860 			DUK_ASSERT(duk_is_object(thr, obj_idx));
80861 
80862 			idx = (duk_uint_fast_t) DUK_DEC_B(ins);
80863 			if (DUK_DEC_OP(ins) == DUK_OP_MPUTARRI) {
80864 				DUK__LOOKUP_INDIRECT(idx);
80865 			}
80866 
80867 			count = (duk_small_uint_fast_t) DUK_DEC_C(ins);
80868 			DUK_ASSERT(count > 0 + 1);  /* compiler guarantees */
80869 			idx_end = idx + count;
80870 
80871 #if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
80872 			if (idx_end > (duk_uint_fast_t) duk_get_top(thr)) {
80873 				/* XXX: use duk_is_valid_index() instead? */
80874 				/* XXX: improve check; check against nregs, not against top */
80875 				DUK__INTERNAL_ERROR("MPUTARR out of bounds");
80876 			}
80877 #endif
80878 
80879 			tv1 = DUK__REGP(idx);
80880 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
80881 #if defined(DUK_USE_FASTINT)
80882 			DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
80883 			arr_idx = (duk_uint32_t) DUK_TVAL_GET_FASTINT_U32(tv1);
80884 #else
80885 			arr_idx = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv1);
80886 #endif
80887 			idx++;
80888 
80889 			do {
80890 				/* duk_xdef_prop() will define an own property without any array
80891 				 * special behaviors.  We'll need to set the array length explicitly
80892 				 * in the end.  For arrays with elisions, the compiler will emit an
80893 				 * explicit SETALEN which will update the length.
80894 				 */
80895 
80896 				/* XXX: because we're dealing with 'own' properties of a fresh array,
80897 				 * the array initializer should just ensure that the array has a large
80898 				 * enough array part and write the values directly into array part,
80899 				 * and finally set 'length' manually in the end (as already happens now).
80900 				 */
80901 
80902 				duk_dup(thr, (duk_idx_t) idx);
80903 				duk_xdef_prop_index_wec(thr, obj_idx, arr_idx);
80904 
80905 				idx++;
80906 				arr_idx++;
80907 			} while (idx < idx_end);
80908 
80909 			/* XXX: E5.1 Section 11.1.4 coerces the final length through
80910 			 * ToUint32() which is odd but happens now as a side effect of
80911 			 * 'arr_idx' type.
80912 			 */
80913 			duk_set_length(thr, obj_idx, (duk_size_t) (duk_uarridx_t) arr_idx);
80914 			break;
80915 		}
80916 
80917 		case DUK_OP_SETALEN: {
80918 			duk_tval *tv1;
80919 			duk_hobject *h;
80920 			duk_uint32_t len;
80921 
80922 			tv1 = DUK__REGP_A(ins);
80923 			DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv1));
80924 			h = DUK_TVAL_GET_OBJECT(tv1);
80925 			DUK_ASSERT(DUK_HOBJECT_IS_ARRAY(h));
80926 
80927 			tv1 = DUK__REGP_BC(ins);
80928 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
80929 #if defined(DUK_USE_FASTINT)
80930 			DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
80931 			len = (duk_uint32_t) DUK_TVAL_GET_FASTINT_U32(tv1);
80932 #else
80933 			len = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv1);
80934 #endif
80935 			((duk_harray *) h)->length = len;
80936 			break;
80937 		}
80938 
80939 		case DUK_OP_INITENUM: {
80940 			duk__handle_op_initenum(thr, ins);
80941 			break;
80942 		}
80943 
80944 		case DUK_OP_NEXTENUM: {
80945 			curr_pc += duk__handle_op_nextenum(thr, ins);
80946 			break;
80947 		}
80948 
80949 		case DUK_OP_INVLHS: {
80950 			DUK_ERROR_REFERENCE(thr, DUK_STR_INVALID_LVALUE);
80951 			DUK_WO_NORETURN(return;);
80952 			break;
80953 		}
80954 
80955 		case DUK_OP_DEBUGGER: {
80956 			/* Opcode only emitted by compiler when debugger
80957 			 * support is enabled.  Ignore it silently without
80958 			 * debugger support, in case it has been loaded
80959 			 * from precompiled bytecode.
80960 			 */
80961 #if defined(DUK_USE_DEBUGGER_SUPPORT)
80962 			if (duk_debug_is_attached(thr->heap)) {
80963 				DUK_D(DUK_DPRINT("DEBUGGER statement encountered, halt execution"));
80964 				DUK__SYNC_AND_NULL_CURR_PC();
80965 				duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
80966 				DUK_D(DUK_DPRINT("DEBUGGER statement finished, resume execution"));
80967 				goto restart_execution;
80968 			} else {
80969 				DUK_D(DUK_DPRINT("DEBUGGER statement ignored, debugger not attached"));
80970 			}
80971 #else
80972 			DUK_D(DUK_DPRINT("DEBUGGER statement ignored, no debugger support"));
80973 #endif
80974 			break;
80975 		}
80976 
80977 		case DUK_OP_NOP: {
80978 			/* Nop, ignored, but ABC fields may carry a value e.g.
80979 			 * for indirect opcode handling.
80980 			 */
80981 			break;
80982 		}
80983 
80984 		case DUK_OP_INVALID: {
80985 			DUK_ERROR_FMT1(thr, DUK_ERR_ERROR, "INVALID opcode (%ld)", (long) DUK_DEC_ABC(ins));
80986 			DUK_WO_NORETURN(return;);
80987 			break;
80988 		}
80989 
80990 #if defined(DUK_USE_ES6)
80991 		case DUK_OP_NEWTARGET: {
80992 			duk_push_new_target(thr);
80993 			DUK__REPLACE_TOP_BC_BREAK();
80994 		}
80995 #endif  /* DUK_USE_ES6 */
80996 
80997 #if !defined(DUK_USE_EXEC_PREFER_SIZE)
80998 #if !defined(DUK_USE_ES7_EXP_OPERATOR)
80999 		case DUK_OP_EXP_RR:
81000 		case DUK_OP_EXP_CR:
81001 		case DUK_OP_EXP_RC:
81002 		case DUK_OP_EXP_CC:
81003 #endif
81004 #if !defined(DUK_USE_ES6)
81005 		case DUK_OP_NEWTARGET:
81006 #endif
81007 #if !defined(DUK_USE_VERBOSE_ERRORS)
81008 		case DUK_OP_GETPROPC_RR:
81009 		case DUK_OP_GETPROPC_CR:
81010 		case DUK_OP_GETPROPC_RC:
81011 		case DUK_OP_GETPROPC_CC:
81012 #endif
81013 		case DUK_OP_UNUSED207:
81014 		case DUK_OP_UNUSED212:
81015 		case DUK_OP_UNUSED213:
81016 		case DUK_OP_UNUSED214:
81017 		case DUK_OP_UNUSED215:
81018 		case DUK_OP_UNUSED216:
81019 		case DUK_OP_UNUSED217:
81020 		case DUK_OP_UNUSED218:
81021 		case DUK_OP_UNUSED219:
81022 		case DUK_OP_UNUSED220:
81023 		case DUK_OP_UNUSED221:
81024 		case DUK_OP_UNUSED222:
81025 		case DUK_OP_UNUSED223:
81026 		case DUK_OP_UNUSED224:
81027 		case DUK_OP_UNUSED225:
81028 		case DUK_OP_UNUSED226:
81029 		case DUK_OP_UNUSED227:
81030 		case DUK_OP_UNUSED228:
81031 		case DUK_OP_UNUSED229:
81032 		case DUK_OP_UNUSED230:
81033 		case DUK_OP_UNUSED231:
81034 		case DUK_OP_UNUSED232:
81035 		case DUK_OP_UNUSED233:
81036 		case DUK_OP_UNUSED234:
81037 		case DUK_OP_UNUSED235:
81038 		case DUK_OP_UNUSED236:
81039 		case DUK_OP_UNUSED237:
81040 		case DUK_OP_UNUSED238:
81041 		case DUK_OP_UNUSED239:
81042 		case DUK_OP_UNUSED240:
81043 		case DUK_OP_UNUSED241:
81044 		case DUK_OP_UNUSED242:
81045 		case DUK_OP_UNUSED243:
81046 		case DUK_OP_UNUSED244:
81047 		case DUK_OP_UNUSED245:
81048 		case DUK_OP_UNUSED246:
81049 		case DUK_OP_UNUSED247:
81050 		case DUK_OP_UNUSED248:
81051 		case DUK_OP_UNUSED249:
81052 		case DUK_OP_UNUSED250:
81053 		case DUK_OP_UNUSED251:
81054 		case DUK_OP_UNUSED252:
81055 		case DUK_OP_UNUSED253:
81056 		case DUK_OP_UNUSED254:
81057 		case DUK_OP_UNUSED255:
81058 		/* Force all case clauses to map to an actual handler
81059 		 * so that the compiler can emit a jump without a bounds
81060 		 * check: the switch argument is a duk_uint8_t so that
81061 		 * the compiler may be able to figure it out.  This is
81062 		 * a small detail and obviously compiler dependent.
81063 		 */
81064 		/* default: clause omitted on purpose */
81065 #else  /* DUK_USE_EXEC_PREFER_SIZE */
81066 		default:
81067 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
81068 		{
81069 			/* Default case catches invalid/unsupported opcodes. */
81070 			DUK_D(DUK_DPRINT("invalid opcode: %ld - %!I", (long) op, ins));
81071 			DUK__INTERNAL_ERROR("invalid opcode");
81072 			break;
81073 		}
81074 
81075 		}  /* end switch */
81076 
81077 		continue;
81078 
81079 		/* Some shared exit paths for opcode handling below.  These
81080 		 * are mostly useful to reduce code footprint when multiple
81081 		 * opcodes have a similar epilogue (like replacing stack top
81082 		 * with index 'a').
81083 		 */
81084 
81085 #if defined(DUK_USE_EXEC_PREFER_SIZE)
81086 	 replace_top_a:
81087 		DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_A(ins));
81088 		continue;
81089 	 replace_top_bc:
81090 		DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_BC(ins));
81091 		continue;
81092 #endif
81093 	}
81094 	DUK_WO_NORETURN(return;);
81095 
81096 #if !defined(DUK_USE_VERBOSE_EXECUTOR_ERRORS)
81097  internal_error:
81098 	DUK_ERROR_INTERNAL(thr);
81099 	DUK_WO_NORETURN(return;);
81100 #endif
81101 }
81102 
81103 /* automatic undefs */
81104 #undef DUK__BYTEOFF_A
81105 #undef DUK__BYTEOFF_B
81106 #undef DUK__BYTEOFF_BC
81107 #undef DUK__BYTEOFF_C
81108 #undef DUK__COMPARE_BODY
81109 #undef DUK__CONST
81110 #undef DUK__CONSTP
81111 #undef DUK__CONSTP_A
81112 #undef DUK__CONSTP_B
81113 #undef DUK__CONSTP_BC
81114 #undef DUK__CONSTP_C
81115 #undef DUK__DELPROP_BODY
81116 #undef DUK__EQ_BODY
81117 #undef DUK__FUN
81118 #undef DUK__GETPROPC_BODY
81119 #undef DUK__GETPROP_BODY
81120 #undef DUK__GE_BODY
81121 #undef DUK__GT_BODY
81122 #undef DUK__INSTOF_BODY
81123 #undef DUK__INTERNAL_ERROR
81124 #undef DUK__INT_NOACTION
81125 #undef DUK__INT_RESTART
81126 #undef DUK__IN_BODY
81127 #undef DUK__LE_BODY
81128 #undef DUK__LONGJMP_RESTART
81129 #undef DUK__LONGJMP_RETHROW
81130 #undef DUK__LOOKUP_INDIRECT
81131 #undef DUK__LT_BODY
81132 #undef DUK__MASK_A
81133 #undef DUK__MASK_B
81134 #undef DUK__MASK_BC
81135 #undef DUK__MASK_C
81136 #undef DUK__NEQ_BODY
81137 #undef DUK__PUTPROP_BODY
81138 #undef DUK__RCBIT_B
81139 #undef DUK__RCBIT_C
81140 #undef DUK__REG
81141 #undef DUK__REGCONSTP_B
81142 #undef DUK__REGCONSTP_C
81143 #undef DUK__REGP
81144 #undef DUK__REGP_A
81145 #undef DUK__REGP_B
81146 #undef DUK__REGP_BC
81147 #undef DUK__REGP_C
81148 #undef DUK__REPLACE_BOOL_A_BREAK
81149 #undef DUK__REPLACE_TOP_A_BREAK
81150 #undef DUK__REPLACE_TOP_BC_BREAK
81151 #undef DUK__REPLACE_TO_TVPTR
81152 #undef DUK__RETHAND_FINISHED
81153 #undef DUK__RETHAND_RESTART
81154 #undef DUK__RETURN_SHARED
81155 #undef DUK__SEQ_BODY
81156 #undef DUK__SHIFT_A
81157 #undef DUK__SHIFT_B
81158 #undef DUK__SHIFT_BC
81159 #undef DUK__SHIFT_C
81160 #undef DUK__SNEQ_BODY
81161 #undef DUK__STRICT
81162 #undef DUK__SYNC_AND_NULL_CURR_PC
81163 #undef DUK__SYNC_CURR_PC
81164 #undef DUK__TVAL_SHIFT
81165 /*
81166  *  ECMAScript specification algorithm and conversion helpers.
81167  *
81168  *  These helpers encapsulate the primitive ECMAScript operation semantics,
81169  *  and are used by the bytecode executor and the API (among other places).
81170  *  Some primitives are only implemented as part of the API and have no
81171  *  "internal" helper.  This is the case when an internal helper would not
81172  *  really be useful; e.g. the operation is rare, uses value stack heavily,
81173  *  etc.
81174  *
81175  *  The operation arguments depend on what is required to implement
81176  *  the operation:
81177  *
81178  *    - If an operation is simple and stateless, and has no side
81179  *      effects, it won't take an duk_hthread argument and its
81180  *      arguments may be duk_tval pointers (which are safe as long
81181  *      as no side effects take place).
81182  *
81183  *    - If complex coercions are required (e.g. a "ToNumber" coercion)
81184  *      or errors may be thrown, the operation takes an duk_hthread
81185  *      argument.  This also implies that the operation may have
81186  *      arbitrary side effects, invalidating any duk_tval pointers.
81187  *
81188  *    - For operations with potential side effects, arguments can be
81189  *      taken in several ways:
81190  *
81191  *      a) as duk_tval pointers, which makes sense if the "common case"
81192  *         can be resolved without side effects (e.g. coercion); the
81193  *         arguments are pushed to the valstack for coercion if
81194  *         necessary
81195  *
81196  *      b) as duk_tval values
81197  *
81198  *      c) implicitly on value stack top
81199  *
81200  *      d) as indices to the value stack
81201  *
81202  *  Future work:
81203  *
81204  *     - Argument styles may not be the most sensible in every case now.
81205  *
81206  *     - In-place coercions might be useful for several operations, if
81207  *       in-place coercion is OK for the bytecode executor and the API.
81208  */
81209 
81210 /* #include duk_internal.h -> already included */
81211 
81212 /*
81213  *  ToPrimitive()  (E5 Section 9.1)
81214  *
81215  *  ==> implemented in the API.
81216  */
81217 
81218 /*
81219  *  ToBoolean()  (E5 Section 9.2)
81220  */
81221 
81222 DUK_INTERNAL duk_bool_t duk_js_toboolean(duk_tval *tv) {
81223 	switch (DUK_TVAL_GET_TAG(tv)) {
81224 	case DUK_TAG_UNDEFINED:
81225 	case DUK_TAG_NULL:
81226 		return 0;
81227 	case DUK_TAG_BOOLEAN:
81228 		DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv) == 0 || DUK_TVAL_GET_BOOLEAN(tv) == 1);
81229 		return DUK_TVAL_GET_BOOLEAN(tv);
81230 	case DUK_TAG_STRING: {
81231 		/* Symbols ToBoolean() coerce to true, regardless of their
81232 		 * description.  This happens with no explicit check because
81233 		 * of the symbol representation byte prefix.
81234 		 */
81235 		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
81236 		DUK_ASSERT(h != NULL);
81237 		return (DUK_HSTRING_GET_BYTELEN(h) > 0 ? 1 : 0);
81238 	}
81239 	case DUK_TAG_OBJECT: {
81240 		return 1;
81241 	}
81242 	case DUK_TAG_BUFFER: {
81243 		/* Mimic Uint8Array semantics: objects coerce true, regardless
81244 		 * of buffer length (zero or not) or context.
81245 		 */
81246 		return 1;
81247 	}
81248 	case DUK_TAG_POINTER: {
81249 		void *p = DUK_TVAL_GET_POINTER(tv);
81250 		return (p != NULL ? 1 : 0);
81251 	}
81252 	case DUK_TAG_LIGHTFUNC: {
81253 		return 1;
81254 	}
81255 #if defined(DUK_USE_FASTINT)
81256 	case DUK_TAG_FASTINT:
81257 		if (DUK_TVAL_GET_FASTINT(tv) != 0) {
81258 			return 1;
81259 		} else {
81260 			return 0;
81261 		}
81262 #endif
81263 	default: {
81264 		/* number */
81265 		duk_double_t d;
81266 #if defined(DUK_USE_PREFER_SIZE)
81267 		int c;
81268 #endif
81269 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
81270 		DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
81271 		d = DUK_TVAL_GET_DOUBLE(tv);
81272 #if defined(DUK_USE_PREFER_SIZE)
81273 		c = DUK_FPCLASSIFY((double) d);
81274 		if (c == DUK_FP_ZERO || c == DUK_FP_NAN) {
81275 			return 0;
81276 		} else {
81277 			return 1;
81278 		}
81279 #else
81280 		DUK_ASSERT(duk_double_is_nan_or_zero(d) == 0 || duk_double_is_nan_or_zero(d) == 1);
81281 		return duk_double_is_nan_or_zero(d) ^ 1;
81282 #endif
81283 	}
81284 	}
81285 	DUK_UNREACHABLE();
81286 	DUK_WO_UNREACHABLE(return 0;);
81287 }
81288 
81289 /*
81290  *  ToNumber()  (E5 Section 9.3)
81291  *
81292  *  Value to convert must be on stack top, and is popped before exit.
81293  *
81294  *  See: http://www.cs.indiana.edu/~burger/FP-Printing-PLDI96.pdf
81295  *       http://www.cs.indiana.edu/~burger/fp/index.html
81296  *
81297  *  Notes on the conversion:
81298  *
81299  *    - There are specific requirements on the accuracy of the conversion
81300  *      through a "Mathematical Value" (MV), so this conversion is not
81301  *      trivial.
81302  *
81303  *    - Quick rejects (e.g. based on first char) are difficult because
81304  *      the grammar allows leading and trailing white space.
81305  *
81306  *    - Quick reject based on string length is difficult even after
81307  *      accounting for white space; there may be arbitrarily many
81308  *      decimal digits.
81309  *
81310  *    - Standard grammar allows decimal values ("123"), hex values
81311  *      ("0x123") and infinities
81312  *
81313  *    - Unlike source code literals, ToNumber() coerces empty strings
81314  *      and strings with only whitespace to zero (not NaN).  However,
81315  *      while '' coerces to 0, '+' and '-' coerce to NaN.
81316  */
81317 
81318 /* E5 Section 9.3.1 */
81319 DUK_LOCAL duk_double_t duk__tonumber_string_raw(duk_hthread *thr) {
81320 	duk_small_uint_t s2n_flags;
81321 	duk_double_t d;
81322 
81323 	DUK_ASSERT(duk_is_string(thr, -1));
81324 
81325 	/* Quite lenient, e.g. allow empty as zero, but don't allow trailing
81326 	 * garbage.
81327 	 */
81328 	s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
81329 	            DUK_S2N_FLAG_ALLOW_EXP |
81330 	            DUK_S2N_FLAG_ALLOW_PLUS |
81331 	            DUK_S2N_FLAG_ALLOW_MINUS |
81332 	            DUK_S2N_FLAG_ALLOW_INF |
81333 	            DUK_S2N_FLAG_ALLOW_FRAC |
81334 	            DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
81335 	            DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
81336 	            DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO |
81337 	            DUK_S2N_FLAG_ALLOW_LEADING_ZERO |
81338 	            DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT |
81339 	            DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT |
81340 	            DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT;
81341 
81342 	duk_numconv_parse(thr, 10 /*radix*/, s2n_flags);
81343 
81344 #if defined(DUK_USE_PREFER_SIZE)
81345 	d = duk_get_number(thr, -1);
81346 	duk_pop_unsafe(thr);
81347 #else
81348 	thr->valstack_top--;
81349 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(thr->valstack_top));
81350 	DUK_ASSERT(DUK_TVAL_IS_DOUBLE(thr->valstack_top));  /* no fastint conversion in numconv now */
81351 	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(thr->valstack_top));
81352 	d = DUK_TVAL_GET_DOUBLE(thr->valstack_top);  /* assumes not a fastint */
81353 	DUK_TVAL_SET_UNDEFINED(thr->valstack_top);
81354 #endif
81355 
81356 	return d;
81357 }
81358 
81359 DUK_INTERNAL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv) {
81360 	DUK_ASSERT(thr != NULL);
81361 	DUK_ASSERT(tv != NULL);
81362 
81363 	switch (DUK_TVAL_GET_TAG(tv)) {
81364 	case DUK_TAG_UNDEFINED: {
81365 		/* return a specific NaN (although not strictly necessary) */
81366 		duk_double_union du;
81367 		DUK_DBLUNION_SET_NAN(&du);
81368 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
81369 		return du.d;
81370 	}
81371 	case DUK_TAG_NULL: {
81372 		/* +0.0 */
81373 		return 0.0;
81374 	}
81375 	case DUK_TAG_BOOLEAN: {
81376 		if (DUK_TVAL_IS_BOOLEAN_TRUE(tv)) {
81377 			return 1.0;
81378 		}
81379 		return 0.0;
81380 	}
81381 	case DUK_TAG_STRING: {
81382 		/* For Symbols ToNumber() is always a TypeError. */
81383 		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
81384 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
81385 			DUK_ERROR_TYPE(thr, DUK_STR_CANNOT_NUMBER_COERCE_SYMBOL);
81386 			DUK_WO_NORETURN(return 0.0;);
81387 		}
81388 		duk_push_hstring(thr, h);
81389 		return duk__tonumber_string_raw(thr);
81390 	}
81391 	case DUK_TAG_BUFFER:  /* plain buffer treated like object */
81392 	case DUK_TAG_OBJECT: {
81393 		duk_double_t d;
81394 		duk_push_tval(thr, tv);
81395 		duk_to_primitive(thr, -1, DUK_HINT_NUMBER);  /* 'tv' becomes invalid */
81396 
81397 		/* recursive call for a primitive value (guaranteed not to cause second
81398 		 * recursion).
81399 		 */
81400 		DUK_ASSERT(duk_get_tval(thr, -1) != NULL);
81401 		d = duk_js_tonumber(thr, duk_get_tval(thr, -1));
81402 
81403 		duk_pop_unsafe(thr);
81404 		return d;
81405 	}
81406 	case DUK_TAG_POINTER: {
81407 		/* Coerce like boolean */
81408 		void *p = DUK_TVAL_GET_POINTER(tv);
81409 		return (p != NULL ? 1.0 : 0.0);
81410 	}
81411 	case DUK_TAG_LIGHTFUNC: {
81412 		/* +(function(){}) -> NaN */
81413 		return DUK_DOUBLE_NAN;
81414 	}
81415 #if defined(DUK_USE_FASTINT)
81416 	case DUK_TAG_FASTINT:
81417 		return (duk_double_t) DUK_TVAL_GET_FASTINT(tv);
81418 #endif
81419 	default: {
81420 		/* number */
81421 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
81422 		DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
81423 		return DUK_TVAL_GET_DOUBLE(tv);
81424 	}
81425 	}
81426 
81427 	DUK_UNREACHABLE();
81428 	DUK_WO_UNREACHABLE(return 0.0;);
81429 }
81430 
81431 /*
81432  *  ToInteger()  (E5 Section 9.4)
81433  */
81434 
81435 /* exposed, used by e.g. duk_bi_date.c */
81436 DUK_INTERNAL duk_double_t duk_js_tointeger_number(duk_double_t x) {
81437 #if defined(DUK_USE_PREFER_SIZE)
81438 	duk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);
81439 
81440 	if (DUK_UNLIKELY(c == DUK_FP_NAN)) {
81441 		return 0.0;
81442 	} else if (DUK_UNLIKELY(c == DUK_FP_INFINITE)) {
81443 		return x;
81444 	} else {
81445 		/* Finite, including neg/pos zero.  Neg zero sign must be
81446 		 * preserved.
81447 		 */
81448 		return duk_double_trunc_towards_zero(x);
81449 	}
81450 #else  /* DUK_USE_PREFER_SIZE */
81451 	/* NaN and Infinity have the same exponent so it's a cheap
81452 	 * initial check for the rare path.
81453 	 */
81454 	if (DUK_UNLIKELY(duk_double_is_nan_or_inf(x) != 0U)) {
81455 		if (duk_double_is_nan(x)) {
81456 			return 0.0;
81457 		} else {
81458 			return x;
81459 		}
81460 	} else {
81461 		return duk_double_trunc_towards_zero(x);
81462 	}
81463 #endif  /* DUK_USE_PREFER_SIZE */
81464 }
81465 
81466 DUK_INTERNAL duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv) {
81467 	/* XXX: fastint */
81468 	duk_double_t d = duk_js_tonumber(thr, tv);  /* invalidates tv */
81469 	return duk_js_tointeger_number(d);
81470 }
81471 
81472 /*
81473  *  ToInt32(), ToUint32(), ToUint16()  (E5 Sections 9.5, 9.6, 9.7)
81474  */
81475 
81476 /* combined algorithm matching E5 Sections 9.5 and 9.6 */
81477 DUK_LOCAL duk_double_t duk__toint32_touint32_helper(duk_double_t x, duk_bool_t is_toint32) {
81478 #if defined (DUK_USE_PREFER_SIZE)
81479 	duk_small_int_t c;
81480 #endif
81481 
81482 #if defined (DUK_USE_PREFER_SIZE)
81483 	c = (duk_small_int_t) DUK_FPCLASSIFY(x);
81484 	if (c == DUK_FP_NAN || c == DUK_FP_ZERO || c == DUK_FP_INFINITE) {
81485 		return 0.0;
81486 	}
81487 #else
81488 	if (duk_double_is_nan_zero_inf(x)) {
81489 		return 0.0;
81490 	}
81491 #endif
81492 
81493 	/* x = sign(x) * floor(abs(x)), i.e. truncate towards zero, keep sign */
81494 	x = duk_double_trunc_towards_zero(x);
81495 
81496 	/* NOTE: fmod(x) result sign is same as sign of x, which
81497 	 * differs from what Javascript wants (see Section 9.6).
81498 	 */
81499 
81500 	x = DUK_FMOD(x, DUK_DOUBLE_2TO32);    /* -> x in ]-2**32, 2**32[ */
81501 
81502 	if (x < 0.0) {
81503 		x += DUK_DOUBLE_2TO32;
81504 	}
81505 	DUK_ASSERT(x >= 0 && x < DUK_DOUBLE_2TO32);  /* -> x in [0, 2**32[ */
81506 
81507 	if (is_toint32) {
81508 		if (x >= DUK_DOUBLE_2TO31) {
81509 			/* x in [2**31, 2**32[ */
81510 
81511 			x -= DUK_DOUBLE_2TO32;  /* -> x in [-2**31,2**31[ */
81512 		}
81513 	}
81514 
81515 	return x;
81516 }
81517 
81518 DUK_INTERNAL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv) {
81519 	duk_double_t d;
81520 
81521 #if defined(DUK_USE_FASTINT)
81522 	if (DUK_TVAL_IS_FASTINT(tv)) {
81523 		return DUK_TVAL_GET_FASTINT_I32(tv);
81524 	}
81525 #endif
81526 
81527 	d = duk_js_tonumber(thr, tv);  /* invalidates tv */
81528 	d = duk__toint32_touint32_helper(d, 1);
81529 	DUK_ASSERT(DUK_FPCLASSIFY(d) == DUK_FP_ZERO || DUK_FPCLASSIFY(d) == DUK_FP_NORMAL);
81530 	DUK_ASSERT(d >= -2147483648.0 && d <= 2147483647.0);  /* [-0x80000000,0x7fffffff] */
81531 	DUK_ASSERT(duk_double_equals(d, (duk_double_t) ((duk_int32_t) d)));  /* whole, won't clip */
81532 	return (duk_int32_t) d;
81533 }
81534 
81535 
81536 DUK_INTERNAL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv) {
81537 	duk_double_t d;
81538 
81539 #if defined(DUK_USE_FASTINT)
81540 	if (DUK_TVAL_IS_FASTINT(tv)) {
81541 		return DUK_TVAL_GET_FASTINT_U32(tv);
81542 	}
81543 #endif
81544 
81545 	d = duk_js_tonumber(thr, tv);  /* invalidates tv */
81546 	d = duk__toint32_touint32_helper(d, 0);
81547 	DUK_ASSERT(DUK_FPCLASSIFY(d) == DUK_FP_ZERO || DUK_FPCLASSIFY(d) == DUK_FP_NORMAL);
81548 	DUK_ASSERT(d >= 0.0 && d <= 4294967295.0);  /* [0x00000000, 0xffffffff] */
81549 	DUK_ASSERT(duk_double_equals(d, (duk_double_t) ((duk_uint32_t) d)));  /* whole, won't clip */
81550 	return (duk_uint32_t) d;
81551 
81552 }
81553 
81554 DUK_INTERNAL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv) {
81555 	/* should be a safe way to compute this */
81556 	return (duk_uint16_t) (duk_js_touint32(thr, tv) & 0x0000ffffU);
81557 }
81558 
81559 /*
81560  *  ToString()  (E5 Section 9.8)
81561  *  ToObject()  (E5 Section 9.9)
81562  *  CheckObjectCoercible()  (E5 Section 9.10)
81563  *  IsCallable()  (E5 Section 9.11)
81564  *
81565  *  ==> implemented in the API.
81566  */
81567 
81568 /*
81569  *  Loose equality, strict equality, and SameValue (E5 Sections 11.9.1, 11.9.4,
81570  *  9.12).  These have much in common so they can share some helpers.
81571  *
81572  *  Future work notes:
81573  *
81574  *    - Current implementation (and spec definition) has recursion; this should
81575  *      be fixed if possible.
81576  *
81577  *    - String-to-number coercion should be possible without going through the
81578  *      value stack (and be more compact) if a shared helper is invoked.
81579  */
81580 
81581 /* Note that this is the same operation for strict and loose equality:
81582  *  - E5 Section 11.9.3, step 1.c (loose)
81583  *  - E5 Section 11.9.6, step 4 (strict)
81584  */
81585 
81586 DUK_LOCAL duk_bool_t duk__js_equals_number(duk_double_t x, duk_double_t y) {
81587 #if defined(DUK_USE_PARANOID_MATH)
81588 	/* Straightforward algorithm, makes fewer compiler assumptions. */
81589 	duk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
81590 	duk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
81591 	if (cx == DUK_FP_NAN || cy == DUK_FP_NAN) {
81592 		return 0;
81593 	}
81594 	if (cx == DUK_FP_ZERO && cy == DUK_FP_ZERO) {
81595 		return 1;
81596 	}
81597 	if (x == y) {
81598 		return 1;
81599 	}
81600 	return 0;
81601 #else  /* DUK_USE_PARANOID_MATH */
81602 	/* Better equivalent algorithm.  If the compiler is compliant, C and
81603 	 * ECMAScript semantics are identical for this particular comparison.
81604 	 * In particular, NaNs must never compare equal and zeroes must compare
81605 	 * equal regardless of sign.  Could also use a macro, but this inlines
81606 	 * already nicely (no difference on gcc, for instance).
81607 	 */
81608 	if (duk_double_equals(x, y)) {
81609 		/* IEEE requires that NaNs compare false */
81610 		DUK_ASSERT(DUK_FPCLASSIFY(x) != DUK_FP_NAN);
81611 		DUK_ASSERT(DUK_FPCLASSIFY(y) != DUK_FP_NAN);
81612 		return 1;
81613 	} else {
81614 		/* IEEE requires that zeros compare the same regardless
81615 		 * of their signed, so if both x and y are zeroes, they
81616 		 * are caught above.
81617 		 */
81618 		DUK_ASSERT(!(DUK_FPCLASSIFY(x) == DUK_FP_ZERO && DUK_FPCLASSIFY(y) == DUK_FP_ZERO));
81619 		return 0;
81620 	}
81621 #endif  /* DUK_USE_PARANOID_MATH */
81622 }
81623 
81624 DUK_LOCAL duk_bool_t duk__js_samevalue_number(duk_double_t x, duk_double_t y) {
81625 #if defined(DUK_USE_PARANOID_MATH)
81626 	duk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
81627 	duk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
81628 
81629 	if (cx == DUK_FP_NAN && cy == DUK_FP_NAN) {
81630 		/* SameValue(NaN, NaN) = true, regardless of NaN sign or extra bits */
81631 		return 1;
81632 	}
81633 	if (cx == DUK_FP_ZERO && cy == DUK_FP_ZERO) {
81634 		/* Note: cannot assume that a non-zero return value of signbit() would
81635 		 * always be the same -- hence cannot (portably) use something like:
81636 		 *
81637 		 *     signbit(x) == signbit(y)
81638 		 */
81639 		duk_small_int_t sx = DUK_SIGNBIT(x) ? 1 : 0;
81640 		duk_small_int_t sy = DUK_SIGNBIT(y) ? 1 : 0;
81641 		return (sx == sy);
81642 	}
81643 
81644 	/* normal comparison; known:
81645 	 *   - both x and y are not NaNs (but one of them can be)
81646 	 *   - both x and y are not zero (but one of them can be)
81647 	 *   - x and y may be denormal or infinite
81648 	 */
81649 
81650 	return (x == y);
81651 #else  /* DUK_USE_PARANOID_MATH */
81652 	duk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
81653 	duk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
81654 
81655 	if (duk_double_equals(x, y)) {
81656 		/* IEEE requires that NaNs compare false */
81657 		DUK_ASSERT(DUK_FPCLASSIFY(x) != DUK_FP_NAN);
81658 		DUK_ASSERT(DUK_FPCLASSIFY(y) != DUK_FP_NAN);
81659 
81660 		/* Using classification has smaller footprint than direct comparison. */
81661 		if (DUK_UNLIKELY(cx == DUK_FP_ZERO && cy == DUK_FP_ZERO)) {
81662 			/* Note: cannot assume that a non-zero return value of signbit() would
81663 			 * always be the same -- hence cannot (portably) use something like:
81664 			 *
81665 			 *     signbit(x) == signbit(y)
81666 			 */
81667 			return duk_double_same_sign(x, y);
81668 		}
81669 		return 1;
81670 	} else {
81671 		/* IEEE requires that zeros compare the same regardless
81672 		 * of their sign, so if both x and y are zeroes, they
81673 		 * are caught above.
81674 		 */
81675 		DUK_ASSERT(!(DUK_FPCLASSIFY(x) == DUK_FP_ZERO && DUK_FPCLASSIFY(y) == DUK_FP_ZERO));
81676 
81677 		/* Difference to non-strict/strict comparison is that NaNs compare
81678 		 * equal and signed zero signs matter.
81679 		 */
81680 		if (DUK_UNLIKELY(cx == DUK_FP_NAN && cy == DUK_FP_NAN)) {
81681 			/* SameValue(NaN, NaN) = true, regardless of NaN sign or extra bits */
81682 			return 1;
81683 		}
81684 		return 0;
81685 	}
81686 #endif  /* DUK_USE_PARANOID_MATH */
81687 }
81688 
81689 DUK_INTERNAL duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_t flags) {
81690 	duk_uint_t type_mask_x;
81691 	duk_uint_t type_mask_y;
81692 
81693 	/* If flags != 0 (strict or SameValue), thr can be NULL.  For loose
81694 	 * equals comparison it must be != NULL.
81695 	 */
81696 	DUK_ASSERT(flags != 0 || thr != NULL);
81697 
81698 	/*
81699 	 *  Same type?
81700 	 *
81701 	 *  Note: since number values have no explicit tag in the 8-byte
81702 	 *  representation, need the awkward if + switch.
81703 	 */
81704 
81705 #if defined(DUK_USE_FASTINT)
81706 	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
81707 		if (DUK_TVAL_GET_FASTINT(tv_x) == DUK_TVAL_GET_FASTINT(tv_y)) {
81708 			return 1;
81709 		} else {
81710 			return 0;
81711 		}
81712 	}
81713 	else
81714 #endif
81715 	if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
81716 		duk_double_t d1, d2;
81717 
81718 		/* Catches both doubles and cases where only one argument is
81719 		 * a fastint so can't assume a double.
81720 		 */
81721 		d1 = DUK_TVAL_GET_NUMBER(tv_x);
81722 		d2 = DUK_TVAL_GET_NUMBER(tv_y);
81723 		if (DUK_UNLIKELY((flags & DUK_EQUALS_FLAG_SAMEVALUE) != 0)) {
81724 			/* SameValue */
81725 			return duk__js_samevalue_number(d1, d2);
81726 		} else {
81727 			/* equals and strict equals */
81728 			return duk__js_equals_number(d1, d2);
81729 		}
81730 	} else if (DUK_TVAL_GET_TAG(tv_x) == DUK_TVAL_GET_TAG(tv_y)) {
81731 		switch (DUK_TVAL_GET_TAG(tv_x)) {
81732 		case DUK_TAG_UNDEFINED:
81733 		case DUK_TAG_NULL: {
81734 			return 1;
81735 		}
81736 		case DUK_TAG_BOOLEAN: {
81737 			return DUK_TVAL_GET_BOOLEAN(tv_x) == DUK_TVAL_GET_BOOLEAN(tv_y);
81738 		}
81739 		case DUK_TAG_POINTER: {
81740 			return DUK_TVAL_GET_POINTER(tv_x) == DUK_TVAL_GET_POINTER(tv_y);
81741 		}
81742 		case DUK_TAG_STRING:
81743 		case DUK_TAG_OBJECT: {
81744 			/* Heap pointer comparison suffices for strings and objects.
81745 			 * Symbols compare equal if they have the same internal
81746 			 * representation; again heap pointer comparison suffices.
81747 			 */
81748 			return DUK_TVAL_GET_HEAPHDR(tv_x) == DUK_TVAL_GET_HEAPHDR(tv_y);
81749 		}
81750 		case DUK_TAG_BUFFER: {
81751 			/* In Duktape 2.x plain buffers mimic Uint8Array objects
81752 			 * so always compare by heap pointer.  In Duktape 1.x
81753 			 * strict comparison would compare heap pointers and
81754 			 * non-strict would compare contents.
81755 			 */
81756 			return DUK_TVAL_GET_HEAPHDR(tv_x) == DUK_TVAL_GET_HEAPHDR(tv_y);
81757 		}
81758 		case DUK_TAG_LIGHTFUNC: {
81759 			/* At least 'magic' has a significant impact on function
81760 			 * identity.
81761 			 */
81762 			duk_small_uint_t lf_flags_x;
81763 			duk_small_uint_t lf_flags_y;
81764 			duk_c_function func_x;
81765 			duk_c_function func_y;
81766 
81767 			DUK_TVAL_GET_LIGHTFUNC(tv_x, func_x, lf_flags_x);
81768 			DUK_TVAL_GET_LIGHTFUNC(tv_y, func_y, lf_flags_y);
81769 			return ((func_x == func_y) && (lf_flags_x == lf_flags_y)) ? 1 : 0;
81770 		}
81771 #if defined(DUK_USE_FASTINT)
81772 		case DUK_TAG_FASTINT:
81773 #endif
81774 		default: {
81775 			DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_x));
81776 			DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_y));
81777 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_x));
81778 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_y));
81779 			DUK_UNREACHABLE();
81780 			DUK_WO_UNREACHABLE(return 0;);
81781 		}
81782 		}
81783 	}
81784 
81785 	if ((flags & (DUK_EQUALS_FLAG_STRICT | DUK_EQUALS_FLAG_SAMEVALUE)) != 0) {
81786 		return 0;
81787 	}
81788 
81789 	DUK_ASSERT(flags == 0);  /* non-strict equality from here on */
81790 
81791 	/*
81792 	 *  Types are different; various cases for non-strict comparison
81793 	 *
81794 	 *  Since comparison is symmetric, we use a "swap trick" to reduce
81795 	 *  code size.
81796 	 */
81797 
81798 	type_mask_x = duk_get_type_mask_tval(tv_x);
81799 	type_mask_y = duk_get_type_mask_tval(tv_y);
81800 
81801 	/* Undefined/null are considered equal (e.g. "null == undefined" -> true). */
81802 	if ((type_mask_x & (DUK_TYPE_MASK_UNDEFINED | DUK_TYPE_MASK_NULL)) &&
81803 	    (type_mask_y & (DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_UNDEFINED))) {
81804 		return 1;
81805 	}
81806 
81807 	/* Number/string -> coerce string to number (e.g. "'1.5' == 1.5" -> true). */
81808 	if ((type_mask_x & DUK_TYPE_MASK_NUMBER) && (type_mask_y & DUK_TYPE_MASK_STRING)) {
81809 		if (!DUK_TVAL_STRING_IS_SYMBOL(tv_y)) {
81810 			duk_double_t d1, d2;
81811 			d1 = DUK_TVAL_GET_NUMBER(tv_x);
81812 			d2 = duk_to_number_tval(thr, tv_y);
81813 			return duk__js_equals_number(d1, d2);
81814 		}
81815 	}
81816 	if ((type_mask_x & DUK_TYPE_MASK_STRING) && (type_mask_y & DUK_TYPE_MASK_NUMBER)) {
81817 		if (!DUK_TVAL_STRING_IS_SYMBOL(tv_x)) {
81818 			duk_double_t d1, d2;
81819 			d1 = DUK_TVAL_GET_NUMBER(tv_y);
81820 			d2 = duk_to_number_tval(thr, tv_x);
81821 			return duk__js_equals_number(d1, d2);
81822 		}
81823 	}
81824 
81825 	/* Boolean/any -> coerce boolean to number and try again.  If boolean is
81826 	 * compared to a pointer, the final comparison after coercion now always
81827 	 * yields false (as pointer vs. number compares to false), but this is
81828 	 * not special cased.
81829 	 *
81830 	 * ToNumber(bool) is +1.0 or 0.0.  Tagged boolean value is always 0 or 1.
81831 	 */
81832 	if (type_mask_x & DUK_TYPE_MASK_BOOLEAN) {
81833 		DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv_x) == 0 || DUK_TVAL_GET_BOOLEAN(tv_x) == 1);
81834 		duk_push_uint(thr, DUK_TVAL_GET_BOOLEAN(tv_x));
81835 		duk_push_tval(thr, tv_y);
81836 		goto recursive_call;
81837 	}
81838 	if (type_mask_y & DUK_TYPE_MASK_BOOLEAN) {
81839 		DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv_y) == 0 || DUK_TVAL_GET_BOOLEAN(tv_y) == 1);
81840 		duk_push_tval(thr, tv_x);
81841 		duk_push_uint(thr, DUK_TVAL_GET_BOOLEAN(tv_y));
81842 		goto recursive_call;
81843 	}
81844 
81845 	/* String-number-symbol/object -> coerce object to primitive (apparently without hint), then try again. */
81846 	if ((type_mask_x & (DUK_TYPE_MASK_STRING | DUK_TYPE_MASK_NUMBER)) &&
81847 	    (type_mask_y & DUK_TYPE_MASK_OBJECT)) {
81848 		/* No symbol check needed because symbols and strings are accepted. */
81849 		duk_push_tval(thr, tv_x);
81850 		duk_push_tval(thr, tv_y);
81851 		duk_to_primitive(thr, -1, DUK_HINT_NONE);  /* apparently no hint? */
81852 		goto recursive_call;
81853 	}
81854 	if ((type_mask_x & DUK_TYPE_MASK_OBJECT) &&
81855 	    (type_mask_y & (DUK_TYPE_MASK_STRING | DUK_TYPE_MASK_NUMBER))) {
81856 		/* No symbol check needed because symbols and strings are accepted. */
81857 		duk_push_tval(thr, tv_x);
81858 		duk_push_tval(thr, tv_y);
81859 		duk_to_primitive(thr, -2, DUK_HINT_NONE);  /* apparently no hint? */
81860 		goto recursive_call;
81861 	}
81862 
81863 	/* Nothing worked -> not equal. */
81864 	return 0;
81865 
81866  recursive_call:
81867 	/* Shared code path to call the helper again with arguments on stack top. */
81868 	{
81869 		duk_bool_t rc;
81870 		rc = duk_js_equals_helper(thr,
81871 		                          DUK_GET_TVAL_NEGIDX(thr, -2),
81872 		                          DUK_GET_TVAL_NEGIDX(thr, -1),
81873 		                          0 /*flags:nonstrict*/);
81874 		duk_pop_2_unsafe(thr);
81875 		return rc;
81876 	}
81877 }
81878 
81879 /*
81880  *  Comparisons (x >= y, x > y, x <= y, x < y)
81881  *
81882  *  E5 Section 11.8.5: implement 'x < y' and then use negate and eval_left_first
81883  *  flags to get the rest.
81884  */
81885 
81886 /* XXX: this should probably just operate on the stack top, because it
81887  * needs to push stuff on the stack anyway...
81888  */
81889 
81890 DUK_INTERNAL duk_small_int_t duk_js_data_compare(const duk_uint8_t *buf1, const duk_uint8_t *buf2, duk_size_t len1, duk_size_t len2) {
81891 	duk_size_t prefix_len;
81892 	duk_small_int_t rc;
81893 
81894 	prefix_len = (len1 <= len2 ? len1 : len2);
81895 
81896 	/* duk_memcmp() is guaranteed to return zero (equal) for zero length
81897 	 * inputs.
81898 	 */
81899 	rc = duk_memcmp_unsafe((const void *) buf1,
81900 	                       (const void *) buf2,
81901 	                       (size_t) prefix_len);
81902 
81903 	if (rc < 0) {
81904 		return -1;
81905 	} else if (rc > 0) {
81906 		return 1;
81907 	}
81908 
81909 	/* prefix matches, lengths matter now */
81910 	if (len1 < len2) {
81911 		/* e.g. "x" < "xx" */
81912 		return -1;
81913 	} else if (len1 > len2) {
81914 		return 1;
81915 	}
81916 
81917 	return 0;
81918 }
81919 
81920 DUK_INTERNAL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2) {
81921 	/*
81922 	 *  String comparison (E5 Section 11.8.5, step 4), which
81923 	 *  needs to compare codepoint by codepoint.
81924 	 *
81925 	 *  However, UTF-8 allows us to use strcmp directly: the shared
81926 	 *  prefix will be encoded identically (UTF-8 has unique encoding)
81927 	 *  and the first differing character can be compared with a simple
81928 	 *  unsigned byte comparison (which strcmp does).
81929 	 *
81930 	 *  This will not work properly for non-xutf-8 strings, but this
81931 	 *  is not an issue for compliance.
81932 	 */
81933 
81934 	DUK_ASSERT(h1 != NULL);
81935 	DUK_ASSERT(h2 != NULL);
81936 
81937 	return duk_js_data_compare((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h1),
81938 	                           (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h2),
81939 	                           (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1),
81940 	                           (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2));
81941 }
81942 
81943 #if 0  /* unused */
81944 DUK_INTERNAL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2) {
81945 	/* Similar to String comparison. */
81946 
81947 	DUK_ASSERT(h1 != NULL);
81948 	DUK_ASSERT(h2 != NULL);
81949 	DUK_UNREF(heap);
81950 
81951 	return duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h1),
81952 	                           (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h2),
81953 	                           (duk_size_t) DUK_HBUFFER_GET_SIZE(h1),
81954 	                           (duk_size_t) DUK_HBUFFER_GET_SIZE(h2));
81955 }
81956 #endif
81957 
81958 #if defined(DUK_USE_FASTINT)
81959 DUK_LOCAL duk_bool_t duk__compare_fastint(duk_bool_t retval, duk_int64_t v1, duk_int64_t v2) {
81960 	DUK_ASSERT(retval == 0 || retval == 1);
81961 	if (v1 < v2) {
81962 		return retval ^ 1;
81963 	} else {
81964 		return retval;
81965 	}
81966 }
81967 #endif
81968 
81969 #if defined(DUK_USE_PARANOID_MATH)
81970 DUK_LOCAL duk_bool_t duk__compare_number(duk_bool_t retval, duk_double_t d1, duk_double_t d2) {
81971 	duk_small_int_t c1, s1, c2, s2;
81972 
81973 	DUK_ASSERT(retval == 0 || retval == 1);
81974 	c1 = (duk_small_int_t) DUK_FPCLASSIFY(d1);
81975 	s1 = (duk_small_int_t) DUK_SIGNBIT(d1);
81976 	c2 = (duk_small_int_t) DUK_FPCLASSIFY(d2);
81977 	s2 = (duk_small_int_t) DUK_SIGNBIT(d2);
81978 
81979 	if (c1 == DUK_FP_NAN || c2 == DUK_FP_NAN) {
81980 		return 0;  /* Always false, regardless of negation. */
81981 	}
81982 
81983 	if (c1 == DUK_FP_ZERO && c2 == DUK_FP_ZERO) {
81984 		/* For all combinations: +0 < +0, +0 < -0, -0 < +0, -0 < -0,
81985 		 * steps e, f, and g.
81986 		 */
81987 		return retval;  /* false */
81988 	}
81989 
81990 	if (d1 == d2) {
81991 		return retval;  /* false */
81992 	}
81993 
81994 	if (c1 == DUK_FP_INFINITE && s1 == 0) {
81995 		/* x == +Infinity */
81996 		return retval;  /* false */
81997 	}
81998 
81999 	if (c2 == DUK_FP_INFINITE && s2 == 0) {
82000 		/* y == +Infinity */
82001 		return retval ^ 1;  /* true */
82002 	}
82003 
82004 	if (c2 == DUK_FP_INFINITE && s2 != 0) {
82005 		/* y == -Infinity */
82006 		return retval;  /* false */
82007 	}
82008 
82009 	if (c1 == DUK_FP_INFINITE && s1 != 0) {
82010 		/* x == -Infinity */
82011 		return retval ^ 1;  /* true */
82012 	}
82013 
82014 	if (d1 < d2) {
82015 		return retval ^ 1;  /* true */
82016 	}
82017 
82018 	return retval;  /* false */
82019 }
82020 #else  /* DUK_USE_PARANOID_MATH */
82021 DUK_LOCAL duk_bool_t duk__compare_number(duk_bool_t retval, duk_double_t d1, duk_double_t d2) {
82022 	/* This comparison tree relies doesn't match the exact steps in
82023 	 * E5 Section 11.8.5 but should produce the same results.  The
82024 	 * steps rely on exact IEEE semantics for NaNs, etc.
82025 	 */
82026 
82027 	DUK_ASSERT(retval == 0 || retval == 1);
82028 	if (d1 < d2) {
82029 		/* In no case should both (d1 < d2) and (d2 < d1) be true.
82030 		 * It's possible that neither is true though, and that's
82031 		 * handled below.
82032 		 */
82033 		DUK_ASSERT(!(d2 < d1));
82034 
82035 		/* - d1 < d2, both d1/d2 are normals (not Infinity, not NaN)
82036 		 * - d2 is +Infinity, d1 != +Infinity and NaN
82037 		 * - d1 is -Infinity, d2 != -Infinity and NaN
82038 		 */
82039 		return retval ^ 1;
82040 	} else {
82041 		if (d2 < d1) {
82042 			/* - !(d1 < d2), both d1/d2 are normals (not Infinity, not NaN)
82043 			 * - d1 is +Infinity, d2 != +Infinity and NaN
82044 			 * - d2 is -Infinity, d1 != -Infinity and NaN
82045 			 */
82046 			return retval;
82047 		} else {
82048 			/* - d1 and/or d2 is NaN
82049 			 * - d1 and d2 are both +/- 0
82050 			 * - d1 == d2 (including infinities)
82051 			 */
82052 			if (duk_double_is_nan(d1) || duk_double_is_nan(d2)) {
82053 				/* Note: undefined from Section 11.8.5 always
82054 				 * results in false return (see e.g. Section
82055 				 * 11.8.3) - hence special treatment here.
82056 				 */
82057 				return 0;  /* zero regardless of negation */
82058 			} else {
82059 				return retval;
82060 			}
82061 		}
82062 	}
82063 }
82064 #endif  /* DUK_USE_PARANOID_MATH */
82065 
82066 DUK_INTERNAL duk_bool_t duk_js_compare_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_t flags) {
82067 	duk_double_t d1, d2;
82068 	duk_small_int_t rc;
82069 	duk_bool_t retval;
82070 
82071 	DUK_ASSERT(DUK_COMPARE_FLAG_NEGATE == 1);  /* Rely on this flag being lowest. */
82072 	retval = flags & DUK_COMPARE_FLAG_NEGATE;
82073 	DUK_ASSERT(retval == 0 || retval == 1);
82074 
82075 	/* Fast path for fastints */
82076 #if defined(DUK_USE_FASTINT)
82077 	if (DUK_LIKELY(DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y))) {
82078 		return duk__compare_fastint(retval,
82079 		                            DUK_TVAL_GET_FASTINT(tv_x),
82080 		                            DUK_TVAL_GET_FASTINT(tv_y));
82081 	}
82082 #endif  /* DUK_USE_FASTINT */
82083 
82084 	/* Fast path for numbers (one of which may be a fastint) */
82085 #if !defined(DUK_USE_PREFER_SIZE)
82086 	if (DUK_LIKELY(DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y))) {
82087 		return duk__compare_number(retval,
82088 		                           DUK_TVAL_GET_NUMBER(tv_x),
82089 		                           DUK_TVAL_GET_NUMBER(tv_y));
82090 	}
82091 #endif
82092 
82093 	/* Slow path */
82094 
82095 	duk_push_tval(thr, tv_x);
82096 	duk_push_tval(thr, tv_y);
82097 
82098 	if (flags & DUK_COMPARE_FLAG_EVAL_LEFT_FIRST) {
82099 		duk_to_primitive(thr, -2, DUK_HINT_NUMBER);
82100 		duk_to_primitive(thr, -1, DUK_HINT_NUMBER);
82101 	} else {
82102 		duk_to_primitive(thr, -1, DUK_HINT_NUMBER);
82103 		duk_to_primitive(thr, -2, DUK_HINT_NUMBER);
82104 	}
82105 
82106 	/* Note: reuse variables */
82107 	tv_x = DUK_GET_TVAL_NEGIDX(thr, -2);
82108 	tv_y = DUK_GET_TVAL_NEGIDX(thr, -1);
82109 
82110 	if (DUK_TVAL_IS_STRING(tv_x) && DUK_TVAL_IS_STRING(tv_y)) {
82111 		duk_hstring *h1 = DUK_TVAL_GET_STRING(tv_x);
82112 		duk_hstring *h2 = DUK_TVAL_GET_STRING(tv_y);
82113 		DUK_ASSERT(h1 != NULL);
82114 		DUK_ASSERT(h2 != NULL);
82115 
82116 		if (DUK_LIKELY(!DUK_HSTRING_HAS_SYMBOL(h1) && !DUK_HSTRING_HAS_SYMBOL(h2))) {
82117 			rc = duk_js_string_compare(h1, h2);
82118 			duk_pop_2_unsafe(thr);
82119 			if (rc < 0) {
82120 				return retval ^ 1;
82121 			} else {
82122 				return retval;
82123 			}
82124 		}
82125 
82126 		/* One or both are Symbols: fall through to handle in the
82127 		 * generic path.  Concretely, ToNumber() will fail.
82128 		 */
82129 	}
82130 
82131 	/* Ordering should not matter (E5 Section 11.8.5, step 3.a). */
82132 #if 0
82133 	if (flags & DUK_COMPARE_FLAG_EVAL_LEFT_FIRST) {
82134 		d1 = duk_to_number_m2(thr);
82135 		d2 = duk_to_number_m1(thr);
82136 	} else {
82137 		d2 = duk_to_number_m1(thr);
82138 		d1 = duk_to_number_m2(thr);
82139 	}
82140 #endif
82141 	d1 = duk_to_number_m2(thr);
82142 	d2 = duk_to_number_m1(thr);
82143 
82144 	/* We want to duk_pop_2_unsafe(thr); because the values are numbers
82145 	 * no decref check is needed.
82146 	 */
82147 #if defined(DUK_USE_PREFER_SIZE)
82148 	duk_pop_2_nodecref_unsafe(thr);
82149 #else
82150 	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk_get_tval(thr, -2)));
82151 	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk_get_tval(thr, -1)));
82152 	DUK_ASSERT(duk_get_top(thr) >= 2);
82153 	thr->valstack_top -= 2;
82154 	tv_x = thr->valstack_top;
82155 	tv_y = tv_x + 1;
82156 	DUK_TVAL_SET_UNDEFINED(tv_x);  /* Value stack policy */
82157 	DUK_TVAL_SET_UNDEFINED(tv_y);
82158 #endif
82159 
82160 	return duk__compare_number(retval, d1, d2);
82161 }
82162 
82163 /*
82164  *  instanceof
82165  */
82166 
82167 /*
82168  *  ES2015 Section 7.3.19 describes the OrdinaryHasInstance() algorithm
82169  *  which covers both bound and non-bound functions; in effect the algorithm
82170  *  includes E5 Sections 11.8.6, 15.3.5.3, and 15.3.4.5.3.
82171  *
82172  *  ES2015 Section 12.9.4 describes the instanceof operator which first
82173  *  checks @@hasInstance well-known symbol and falls back to
82174  *  OrdinaryHasInstance().
82175  *
82176  *  Limited Proxy support: don't support 'getPrototypeOf' trap but
82177  *  continue lookup in Proxy target if the value is a Proxy.
82178  */
82179 
82180 DUK_LOCAL duk_bool_t duk__js_instanceof_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_bool_t skip_sym_check) {
82181 	duk_hobject *func;
82182 	duk_hobject *val;
82183 	duk_hobject *proto;
82184 	duk_tval *tv;
82185 	duk_bool_t skip_first;
82186 	duk_uint_t sanity;
82187 
82188 	/*
82189 	 *  Get the values onto the stack first.  It would be possible to cover
82190 	 *  some normal cases without resorting to the value stack.
82191 	 *
82192 	 *  The right hand side could be a light function (as they generally
82193 	 *  behave like objects).  Light functions never have a 'prototype'
82194 	 *  property so E5.1 Section 15.3.5.3 step 3 always throws a TypeError.
82195 	 *  Using duk_require_hobject() is thus correct (except for error msg).
82196 	 */
82197 
82198 	duk_push_tval(thr, tv_x);
82199 	duk_push_tval(thr, tv_y);
82200 	func = duk_require_hobject(thr, -1);
82201 	DUK_ASSERT(func != NULL);
82202 
82203 #if defined(DUK_USE_SYMBOL_BUILTIN)
82204 	/*
82205 	 *  @@hasInstance check, ES2015 Section 12.9.4, Steps 2-4.
82206 	 */
82207 	if (!skip_sym_check) {
82208 		if (duk_get_method_stridx(thr, -1, DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE)) {
82209 			/* [ ... lhs rhs func ] */
82210 			duk_insert(thr, -3);    /* -> [ ... func lhs rhs ] */
82211 			duk_swap_top(thr, -2);  /* -> [ ... func rhs(this) lhs ] */
82212 			duk_call_method(thr, 1);
82213 			return duk_to_boolean_top_pop(thr);
82214 		}
82215 	}
82216 #else
82217 	DUK_UNREF(skip_sym_check);
82218 #endif
82219 
82220 	/*
82221 	 *  For bound objects, [[HasInstance]] just calls the target function
82222 	 *  [[HasInstance]].  If that is again a bound object, repeat until
82223 	 *  we find a non-bound Function object.
82224 	 *
82225 	 *  The bound function chain is now "collapsed" so there can be only
82226 	 *  one bound function in the chain.
82227 	 */
82228 
82229 	if (!DUK_HOBJECT_IS_CALLABLE(func)) {
82230 		/*
82231 		 *  Note: of native ECMAScript objects, only Function instances
82232 		 *  have a [[HasInstance]] internal property.  Custom objects might
82233 		 *  also have it, but not in current implementation.
82234 		 *
82235 		 *  XXX: add a separate flag, DUK_HOBJECT_FLAG_ALLOW_INSTANCEOF?
82236 		 */
82237 		goto error_invalid_rval;
82238 	}
82239 
82240 	if (DUK_HOBJECT_HAS_BOUNDFUNC(func)) {
82241 		duk_push_tval(thr, &((duk_hboundfunc *) (void *) func)->target);
82242 		duk_replace(thr, -2);
82243 		func = duk_require_hobject(thr, -1);  /* lightfunc throws */
82244 
82245 		/* Rely on Function.prototype.bind() never creating bound
82246 		 * functions whose target is not proper.
82247 		 */
82248 		DUK_ASSERT(func != NULL);
82249 		DUK_ASSERT(DUK_HOBJECT_IS_CALLABLE(func));
82250 	}
82251 
82252 	/*
82253 	 *  'func' is now a non-bound object which supports [[HasInstance]]
82254 	 *  (which here just means DUK_HOBJECT_FLAG_CALLABLE).  Move on
82255 	 *  to execute E5 Section 15.3.5.3.
82256 	 */
82257 
82258 	DUK_ASSERT(func != NULL);
82259 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));
82260 	DUK_ASSERT(DUK_HOBJECT_IS_CALLABLE(func));
82261 
82262 	/* [ ... lval rval(func) ] */
82263 
82264 	/* For lightfuncs, buffers, and pointers start the comparison directly
82265 	 * from the virtual prototype object.
82266 	 */
82267 	skip_first = 0;
82268 	tv = DUK_GET_TVAL_NEGIDX(thr, -2);
82269 	switch (DUK_TVAL_GET_TAG(tv)) {
82270 	case DUK_TAG_LIGHTFUNC:
82271 		val = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
82272 		DUK_ASSERT(val != NULL);
82273 		break;
82274 	case DUK_TAG_BUFFER:
82275 		val = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
82276 		DUK_ASSERT(val != NULL);
82277 		break;
82278 	case DUK_TAG_POINTER:
82279 		val = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];
82280 		DUK_ASSERT(val != NULL);
82281 		break;
82282 	case DUK_TAG_OBJECT:
82283 		skip_first = 1;  /* Ignore object itself on first round. */
82284 		val = DUK_TVAL_GET_OBJECT(tv);
82285 		DUK_ASSERT(val != NULL);
82286 		break;
82287 	default:
82288 		goto pop2_and_false;
82289 	}
82290 	DUK_ASSERT(val != NULL);  /* Loop doesn't actually rely on this. */
82291 
82292 	/* Look up .prototype of rval.  Leave it on the value stack in case it
82293 	 * has been virtualized (e.g. getter, Proxy trap).
82294 	 */
82295 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_PROTOTYPE);  /* -> [ ... lval rval rval.prototype ] */
82296 #if defined(DUK_USE_VERBOSE_ERRORS)
82297 	proto = duk_get_hobject(thr, -1);
82298 	if (proto == NULL) {
82299 		goto error_invalid_rval_noproto;
82300 	}
82301 #else
82302 	proto = duk_require_hobject(thr, -1);
82303 #endif
82304 
82305 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
82306 	do {
82307 		/*
82308 		 *  Note: prototype chain is followed BEFORE first comparison.  This
82309 		 *  means that the instanceof lval is never itself compared to the
82310 		 *  rval.prototype property.  This is apparently intentional, see E5
82311 		 *  Section 15.3.5.3, step 4.a.
82312 		 *
82313 		 *  Also note:
82314 		 *
82315 		 *      js> (function() {}) instanceof Function
82316 		 *      true
82317 		 *      js> Function instanceof Function
82318 		 *      true
82319 		 *
82320 		 *  For the latter, h_proto will be Function.prototype, which is the
82321 		 *  built-in Function prototype.  Because Function.[[Prototype]] is
82322 		 *  also the built-in Function prototype, the result is true.
82323 		 */
82324 
82325 		if (!val) {
82326 			goto pop3_and_false;
82327 		}
82328 
82329 		DUK_ASSERT(val != NULL);
82330 #if defined(DUK_USE_ES6_PROXY)
82331 		val = duk_hobject_resolve_proxy_target(val);
82332 #endif
82333 
82334 		if (skip_first) {
82335 			skip_first = 0;
82336 		} else if (val == proto) {
82337 			goto pop3_and_true;
82338 		}
82339 
82340 		DUK_ASSERT(val != NULL);
82341 		val = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, val);
82342 	} while (--sanity > 0);
82343 
82344 	DUK_ASSERT(sanity == 0);
82345 	DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
82346 	DUK_WO_NORETURN(return 0;);
82347 
82348  pop2_and_false:
82349 	duk_pop_2_unsafe(thr);
82350 	return 0;
82351 
82352  pop3_and_false:
82353 	duk_pop_3_unsafe(thr);
82354 	return 0;
82355 
82356  pop3_and_true:
82357 	duk_pop_3_unsafe(thr);
82358 	return 1;
82359 
82360  error_invalid_rval:
82361 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_INSTANCEOF_RVAL);
82362 	DUK_WO_NORETURN(return 0;);
82363 
82364 #if defined(DUK_USE_VERBOSE_ERRORS)
82365  error_invalid_rval_noproto:
82366 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_INSTANCEOF_RVAL_NOPROTO);
82367 	DUK_WO_NORETURN(return 0;);
82368 #endif
82369 }
82370 
82371 #if defined(DUK_USE_SYMBOL_BUILTIN)
82372 DUK_INTERNAL duk_bool_t duk_js_instanceof_ordinary(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
82373 	return duk__js_instanceof_helper(thr, tv_x, tv_y, 1 /*skip_sym_check*/);
82374 }
82375 #endif
82376 
82377 DUK_INTERNAL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
82378 	return duk__js_instanceof_helper(thr, tv_x, tv_y, 0 /*skip_sym_check*/);
82379 }
82380 
82381 /*
82382  *  in
82383  */
82384 
82385 /*
82386  *  E5 Sections 11.8.7, 8.12.6.
82387  *
82388  *  Basically just a property existence check using [[HasProperty]].
82389  */
82390 
82391 DUK_INTERNAL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
82392 	duk_bool_t retval;
82393 
82394 	/*
82395 	 *  Get the values onto the stack first.  It would be possible to cover
82396 	 *  some normal cases without resorting to the value stack (e.g. if
82397 	 *  lval is already a string).
82398 	 */
82399 
82400 	/* XXX: The ES5/5.1/6 specifications require that the key in 'key in obj'
82401 	 * must be string coerced before the internal HasProperty() algorithm is
82402 	 * invoked.  A fast path skipping coercion could be safely implemented for
82403 	 * numbers (as number-to-string coercion has no side effects).  For ES2015
82404 	 * proxy behavior, the trap 'key' argument must be in a string coerced
82405 	 * form (which is a shame).
82406 	 */
82407 
82408 	/* TypeError if rval is not an object or object like (e.g. lightfunc
82409 	 * or plain buffer).
82410 	 */
82411 	duk_push_tval(thr, tv_x);
82412 	duk_push_tval(thr, tv_y);
82413 	duk_require_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT | DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
82414 
82415 	(void) duk_to_property_key_hstring(thr, -2);
82416 
82417 	retval = duk_hobject_hasprop(thr,
82418 	                             DUK_GET_TVAL_NEGIDX(thr, -1),
82419 	                             DUK_GET_TVAL_NEGIDX(thr, -2));
82420 
82421 	duk_pop_2_unsafe(thr);
82422 	return retval;
82423 }
82424 
82425 /*
82426  *  typeof
82427  *
82428  *  E5 Section 11.4.3.
82429  *
82430  *  Very straightforward.  The only question is what to return for our
82431  *  non-standard tag / object types.
82432  *
82433  *  There is an unfortunate string constant define naming problem with
82434  *  typeof return values for e.g. "Object" and "object"; careful with
82435  *  the built-in string defines.  The LC_XXX defines are used for the
82436  *  lowercase variants now.
82437  */
82438 
82439 DUK_INTERNAL duk_small_uint_t duk_js_typeof_stridx(duk_tval *tv_x) {
82440 	duk_small_uint_t stridx = 0;
82441 
82442 	switch (DUK_TVAL_GET_TAG(tv_x)) {
82443 	case DUK_TAG_UNDEFINED: {
82444 		stridx = DUK_STRIDX_LC_UNDEFINED;
82445 		break;
82446 	}
82447 	case DUK_TAG_NULL: {
82448 		/* Note: not a typo, "object" is returned for a null value. */
82449 		stridx = DUK_STRIDX_LC_OBJECT;
82450 		break;
82451 	}
82452 	case DUK_TAG_BOOLEAN: {
82453 		stridx = DUK_STRIDX_LC_BOOLEAN;
82454 		break;
82455 	}
82456 	case DUK_TAG_POINTER: {
82457 		/* Implementation specific. */
82458 		stridx = DUK_STRIDX_LC_POINTER;
82459 		break;
82460 	}
82461 	case DUK_TAG_STRING: {
82462 		duk_hstring *str;
82463 
82464 		/* All internal keys are identified as Symbols. */
82465 		str = DUK_TVAL_GET_STRING(tv_x);
82466 		DUK_ASSERT(str != NULL);
82467 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(str))) {
82468 			stridx = DUK_STRIDX_LC_SYMBOL;
82469 		} else {
82470 			stridx = DUK_STRIDX_LC_STRING;
82471 		}
82472 		break;
82473 	}
82474 	case DUK_TAG_OBJECT: {
82475 		duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv_x);
82476 		DUK_ASSERT(obj != NULL);
82477 		if (DUK_HOBJECT_IS_CALLABLE(obj)) {
82478 			stridx = DUK_STRIDX_LC_FUNCTION;
82479 		} else {
82480 			stridx = DUK_STRIDX_LC_OBJECT;
82481 		}
82482 		break;
82483 	}
82484 	case DUK_TAG_BUFFER: {
82485 		/* Implementation specific.  In Duktape 1.x this would be
82486 		 * 'buffer', in Duktape 2.x changed to 'object' because plain
82487 		 * buffers now mimic Uint8Array objects.
82488 		 */
82489 		stridx = DUK_STRIDX_LC_OBJECT;
82490 		break;
82491 	}
82492 	case DUK_TAG_LIGHTFUNC: {
82493 		stridx = DUK_STRIDX_LC_FUNCTION;
82494 		break;
82495 	}
82496 #if defined(DUK_USE_FASTINT)
82497 	case DUK_TAG_FASTINT:
82498 #endif
82499 	default: {
82500 		/* number */
82501 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_x));
82502 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_x));
82503 		stridx = DUK_STRIDX_LC_NUMBER;
82504 		break;
82505 	}
82506 	}
82507 
82508 	DUK_ASSERT_STRIDX_VALID(stridx);
82509 	return stridx;
82510 }
82511 
82512 /*
82513  *  IsArray()
82514  */
82515 
82516 DUK_INTERNAL duk_bool_t duk_js_isarray_hobject(duk_hobject *h) {
82517 	DUK_ASSERT(h != NULL);
82518 #if defined(DUK_USE_ES6_PROXY)
82519 	h = duk_hobject_resolve_proxy_target(h);
82520 #endif
82521 	return (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY ? 1 : 0);
82522 }
82523 
82524 DUK_INTERNAL duk_bool_t duk_js_isarray(duk_tval *tv) {
82525 	DUK_ASSERT(tv != NULL);
82526 	if (DUK_TVAL_IS_OBJECT(tv)) {
82527 		return duk_js_isarray_hobject(DUK_TVAL_GET_OBJECT(tv));
82528 	}
82529 	return 0;
82530 }
82531 
82532 /*
82533  *  Array index and length
82534  *
82535  *  Array index: E5 Section 15.4
82536  *  Array length: E5 Section 15.4.5.1 steps 3.c - 3.d (array length write)
82537  */
82538 
82539 /* Compure array index from string context, or return a "not array index"
82540  * indicator.
82541  */
82542 DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_string(const duk_uint8_t *str, duk_uint32_t blen) {
82543 	duk_uarridx_t res;
82544 
82545 	/* Only strings with byte length 1-10 can be 32-bit array indices.
82546 	 * Leading zeroes (except '0' alone), plus/minus signs are not allowed.
82547 	 * We could do a lot of prechecks here, but since most strings won't
82548 	 * start with any digits, it's simpler to just parse the number and
82549 	 * fail quickly.
82550 	 */
82551 
82552 	res = 0;
82553 	if (blen == 0) {
82554 		goto parse_fail;
82555 	}
82556 	do {
82557 		duk_uarridx_t dig;
82558 		dig = (duk_uarridx_t) (*str++) - DUK_ASC_0;
82559 
82560 		if (dig <= 9U) {
82561 			/* Careful overflow handling.  When multiplying by 10:
82562 			 * - 0x19999998 x 10 = 0xfffffff0: no overflow, and adding
82563 			 *   0...9 is safe.
82564 			 * - 0x19999999 x 10 = 0xfffffffa: no overflow, adding
82565 			 *   0...5 is safe, 6...9 overflows.
82566 			 * - 0x1999999a x 10 = 0x100000004: always overflow.
82567 			 */
82568 			if (DUK_UNLIKELY(res >= 0x19999999UL)) {
82569 				if (res >= 0x1999999aUL) {
82570 					/* Always overflow. */
82571 					goto parse_fail;
82572 				}
82573 				DUK_ASSERT(res == 0x19999999UL);
82574 				if (dig >= 6U) {
82575 					goto parse_fail;
82576 				}
82577 				res = 0xfffffffaUL + dig;
82578 				DUK_ASSERT(res >= 0xfffffffaUL);
82579 				DUK_ASSERT_DISABLE(res <= 0xffffffffUL);  /* range */
82580 			} else {
82581 				res = res * 10U + dig;
82582 				if (DUK_UNLIKELY(res == 0)) {
82583 					/* If 'res' is 0, previous 'res' must
82584 					 * have been 0 and we scanned in a zero.
82585 					 * This is only allowed if blen == 1,
82586 					 * i.e. the exact string '0'.
82587 					 */
82588 					if (blen == (duk_uint32_t) 1) {
82589 						return 0;
82590 					}
82591 					goto parse_fail;
82592 				}
82593 			}
82594 		} else {
82595 			/* Because 'dig' is unsigned, catches both values
82596 			 * above '9' and below '0'.
82597 			 */
82598 			goto parse_fail;
82599 		}
82600 	} while (--blen > 0);
82601 
82602 	return res;
82603 
82604  parse_fail:
82605 	return DUK_HSTRING_NO_ARRAY_INDEX;
82606 }
82607 
82608 #if !defined(DUK_USE_HSTRING_ARRIDX)
82609 /* Get array index for a string which is known to be an array index.  This helper
82610  * is needed when duk_hstring doesn't concretely store the array index, but strings
82611  * are flagged as array indices at intern time.
82612  */
82613 DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_hstring_fast_known(duk_hstring *h) {
82614 	const duk_uint8_t *p;
82615 	duk_uarridx_t res;
82616 	duk_uint8_t t;
82617 
82618 	DUK_ASSERT(h != NULL);
82619 	DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(h));
82620 
82621 	p = DUK_HSTRING_GET_DATA(h);
82622 	res = 0;
82623 	for (;;) {
82624 		t = *p++;
82625 		if (DUK_UNLIKELY(t == 0)) {
82626 			/* Scanning to NUL is always safe for interned strings. */
82627 			break;
82628 		}
82629 		DUK_ASSERT(t >= (duk_uint8_t) DUK_ASC_0 && t <= (duk_uint8_t) DUK_ASC_9);
82630 		res = res * 10U + (duk_uarridx_t) t - (duk_uarridx_t) DUK_ASC_0;
82631 	}
82632 	return res;
82633 }
82634 
82635 DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_hstring_fast(duk_hstring *h) {
82636 	DUK_ASSERT(h != NULL);
82637 	if (!DUK_HSTRING_HAS_ARRIDX(h)) {
82638 		return DUK_HSTRING_NO_ARRAY_INDEX;
82639 	}
82640 	return duk_js_to_arrayindex_hstring_fast_known(h);
82641 }
82642 #endif  /* DUK_USE_HSTRING_ARRIDX */
82643 /*
82644  *  Identifier access and function closure handling.
82645  *
82646  *  Provides the primitives for slow path identifier accesses: GETVAR,
82647  *  PUTVAR, DELVAR, etc.  The fast path, direct register accesses, should
82648  *  be used for most identifier accesses.  Consequently, these slow path
82649  *  primitives should be optimized for maximum compactness.
82650  *
82651  *  ECMAScript environment records (declarative and object) are represented
82652  *  as internal objects with control keys.  Environment records have a
82653  *  parent record ("outer environment reference") which is represented by
82654  *  the implicit prototype for technical reasons (in other words, it is a
82655  *  convenient field).  The prototype chain is not followed in the ordinary
82656  *  sense for variable lookups.
82657  *
82658  *  See identifier-handling.rst for more details on the identifier algorithms
82659  *  and the internal representation.  See function-objects.rst for details on
82660  *  what function templates and instances are expected to look like.
82661  *
82662  *  Care must be taken to avoid duk_tval pointer invalidation caused by
82663  *  e.g. value stack or object resizing.
82664  *
82665  *  TODO: properties for function instances could be initialized much more
82666  *  efficiently by creating a property allocation for a certain size and
82667  *  filling in keys and values directly (and INCREFing both with "bulk incref"
82668  *  primitives.
82669  *
82670  *  XXX: duk_hobject_getprop() and duk_hobject_putprop() calls are a bit
82671  *  awkward (especially because they follow the prototype chain); rework
82672  *  if "raw" own property helpers are added.
82673  */
82674 
82675 /* #include duk_internal.h -> already included */
82676 
82677 /*
82678  *  Local result type for duk__get_identifier_reference() lookup.
82679  */
82680 
82681 typedef struct {
82682 	duk_hobject *env;
82683 	duk_hobject *holder;      /* for object-bound identifiers */
82684 	duk_tval *value;          /* for register-bound and declarative env identifiers */
82685 	duk_uint_t attrs;         /* property attributes for identifier (relevant if value != NULL) */
82686 	duk_bool_t has_this;      /* for object-bound identifiers: provide 'this' binding */
82687 } duk__id_lookup_result;
82688 
82689 /*
82690  *  Create a new function object based on a "template function" which contains
82691  *  compiled bytecode, constants, etc, but lacks a lexical environment.
82692  *
82693  *  ECMAScript requires that each created closure is a separate object, with
82694  *  its own set of editable properties.  However, structured property values
82695  *  (such as the formal arguments list and the variable map) are shared.
82696  *  Also the bytecode, constants, and inner functions are shared.
82697  *
82698  *  See E5 Section 13.2 for detailed requirements on the function objects;
82699  *  there are no similar requirements for function "templates" which are an
82700  *  implementation dependent internal feature.  Also see function-objects.rst
82701  *  for a discussion on the function instance properties provided by this
82702  *  implementation.
82703  *
82704  *  Notes:
82705  *
82706  *   * Order of internal properties should match frequency of use, since the
82707  *     properties will be linearly scanned on lookup (functions usually don't
82708  *     have enough properties to warrant a hash part).
82709  *
82710  *   * The created closure is independent of its template; they do share the
82711  *     same 'data' buffer object, but the template object itself can be freed
82712  *     even if the closure object remains reachable.
82713  */
82714 
82715 DUK_LOCAL void duk__inc_data_inner_refcounts(duk_hthread *thr, duk_hcompfunc *f) {
82716 	duk_tval *tv, *tv_end;
82717 	duk_hobject **funcs, **funcs_end;
82718 
82719 	DUK_UNREF(thr);
82720 
82721 	/* If function creation fails due to out-of-memory, the data buffer
82722 	 * pointer may be NULL in some cases.  That's actually possible for
82723 	 * GC code, but shouldn't be possible here because the incomplete
82724 	 * function will be unwound from the value stack and never instantiated.
82725 	 */
82726 	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, f) != NULL);
82727 
82728 	tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, f);
82729 	tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, f);
82730 	while (tv < tv_end) {
82731 		DUK_TVAL_INCREF(thr, tv);
82732 		tv++;
82733 	}
82734 
82735 	funcs = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, f);
82736 	funcs_end = DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, f);
82737 	while (funcs < funcs_end) {
82738 		DUK_HEAPHDR_INCREF(thr, (duk_heaphdr *) *funcs);
82739 		funcs++;
82740 	}
82741 }
82742 
82743 /* Push a new closure on the stack.
82744  *
82745  * Note: if fun_temp has NEWENV, i.e. a new lexical and variable declaration
82746  * is created when the function is called, only outer_lex_env matters
82747  * (outer_var_env is ignored and may or may not be same as outer_lex_env).
82748  */
82749 
82750 DUK_LOCAL const duk_uint16_t duk__closure_copy_proplist[] = {
82751 	/* order: most frequent to least frequent */
82752 	DUK_STRIDX_INT_VARMAP,
82753 	DUK_STRIDX_INT_FORMALS,
82754 #if defined(DUK_USE_PC2LINE)
82755 	DUK_STRIDX_INT_PC2LINE,
82756 #endif
82757 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
82758 	DUK_STRIDX_FILE_NAME,
82759 #endif
82760 #if defined(DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY)
82761 	DUK_STRIDX_INT_SOURCE
82762 #endif
82763 };
82764 
82765 DUK_INTERNAL
82766 void duk_js_push_closure(duk_hthread *thr,
82767                          duk_hcompfunc *fun_temp,
82768                          duk_hobject *outer_var_env,
82769                          duk_hobject *outer_lex_env,
82770                          duk_bool_t add_auto_proto) {
82771 	duk_hcompfunc *fun_clos;
82772 	duk_harray *formals;
82773 	duk_small_uint_t i;
82774 	duk_uint_t len_value;
82775 
82776 	DUK_ASSERT(fun_temp != NULL);
82777 	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_temp) != NULL);
82778 	DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_temp) != NULL);
82779 	DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_temp) != NULL);
82780 	DUK_ASSERT(outer_var_env != NULL);
82781 	DUK_ASSERT(outer_lex_env != NULL);
82782 	DUK_UNREF(len_value);
82783 
82784 	DUK_STATS_INC(thr->heap, stats_envrec_pushclosure);
82785 
82786 	fun_clos = duk_push_hcompfunc(thr);
82787 	DUK_ASSERT(fun_clos != NULL);
82788 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) fun_clos) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
82789 
82790 	duk_push_hobject(thr, &fun_temp->obj);  /* -> [ ... closure template ] */
82791 
82792 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun_clos));
82793 	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos) == NULL);
82794 	DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_clos) == NULL);
82795 	DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_clos) == NULL);
82796 
82797 	DUK_HCOMPFUNC_SET_DATA(thr->heap, fun_clos, DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_temp));
82798 	DUK_HCOMPFUNC_SET_FUNCS(thr->heap, fun_clos, DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_temp));
82799 	DUK_HCOMPFUNC_SET_BYTECODE(thr->heap, fun_clos, DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_temp));
82800 
82801 	/* Note: all references inside 'data' need to get their refcounts
82802 	 * upped too.  This is the case because refcounts are decreased
82803 	 * through every function referencing 'data' independently.
82804 	 */
82805 
82806 	DUK_HBUFFER_INCREF(thr, DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos));
82807 	duk__inc_data_inner_refcounts(thr, fun_temp);
82808 
82809 	fun_clos->nregs = fun_temp->nregs;
82810 	fun_clos->nargs = fun_temp->nargs;
82811 #if defined(DUK_USE_DEBUGGER_SUPPORT)
82812 	fun_clos->start_line = fun_temp->start_line;
82813 	fun_clos->end_line = fun_temp->end_line;
82814 #endif
82815 
82816 	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos) != NULL);
82817 	DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_clos) != NULL);
82818 	DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_clos) != NULL);
82819 
82820 	/* XXX: Could also copy from template, but there's no way to have any
82821 	 * other value here now (used code has no access to the template).
82822 	 * Prototype is set by duk_push_hcompfunc().
82823 	 */
82824 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, &fun_clos->obj) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
82825 #if 0
82826 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, &fun_clos->obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
82827 #endif
82828 
82829 	/* Copy duk_hobject flags as is from the template using a mask.
82830 	 * Leave out duk_heaphdr owned flags just in case (e.g. if there's
82831 	 * some GC flag or similar).  Some flags can then be adjusted
82832 	 * separately if necessary.
82833 	 */
82834 
82835 	/* DUK_HEAPHDR_SET_FLAGS() masks changes to non-duk_heaphdr flags only. */
82836 	DUK_HEAPHDR_SET_FLAGS((duk_heaphdr *) fun_clos, DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) fun_temp));
82837 	DUK_DD(DUK_DDPRINT("fun_temp heaphdr flags: 0x%08lx, fun_clos heaphdr flags: 0x%08lx",
82838 	                   (unsigned long) DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) fun_temp),
82839 	                   (unsigned long) DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) fun_clos)));
82840 
82841 	DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(&fun_clos->obj));
82842 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(&fun_clos->obj));
82843 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(&fun_clos->obj));
82844 	DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(&fun_clos->obj));
82845 	DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(&fun_clos->obj));
82846 	/* DUK_HOBJECT_FLAG_ARRAY_PART: don't care */
82847 	/* DUK_HOBJECT_FLAG_NEWENV: handled below */
82848 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(&fun_clos->obj));
82849 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(&fun_clos->obj));
82850 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(&fun_clos->obj));
82851 
82852 	if (!DUK_HOBJECT_HAS_CONSTRUCTABLE(&fun_clos->obj)) {
82853 		/* If the template is not constructable don't add an automatic
82854 		 * .prototype property.  This is the case for e.g. ES2015 object
82855 		 * literal getters/setters and method definitions.
82856 		 */
82857 		add_auto_proto = 0;
82858 	}
82859 
82860 	/*
82861 	 *  Setup environment record properties based on the template and
82862 	 *  its flags.
82863 	 *
82864 	 *  If DUK_HOBJECT_HAS_NEWENV(fun_temp) is true, the environment
82865 	 *  records represent identifiers "outside" the function; the
82866 	 *  "inner" environment records are created on demand.  Otherwise,
82867 	 *  the environment records are those that will be directly used
82868 	 *  (e.g. for declarations).
82869 	 *
82870 	 *  _Lexenv is always set; _Varenv defaults to _Lexenv if missing,
82871 	 *  so _Varenv is only set if _Lexenv != _Varenv.
82872 	 *
82873 	 *  This is relatively complex, see doc/identifier-handling.rst.
82874 	 */
82875 
82876 	if (DUK_HOBJECT_HAS_NEWENV(&fun_clos->obj)) {
82877 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
82878 		if (DUK_HOBJECT_HAS_NAMEBINDING(&fun_clos->obj)) {
82879 			duk_hobject *proto;
82880 			duk_hdecenv *new_env;
82881 
82882 			/*
82883 			 *  Named function expression, name needs to be bound
82884 			 *  in an intermediate environment record.  The "outer"
82885 			 *  lexical/variable environment will thus be:
82886 			 *
82887 			 *  a) { funcname: <func>, __prototype: outer_lex_env }
82888 			 *  b) { funcname: <func>, __prototype:  <globalenv> }  (if outer_lex_env missing)
82889 			 */
82890 
82891 			if (outer_lex_env) {
82892 				proto = outer_lex_env;
82893 			} else {
82894 				proto = thr->builtins[DUK_BIDX_GLOBAL_ENV];
82895 			}
82896 
82897 			/* -> [ ... closure template env ] */
82898 			new_env = duk_hdecenv_alloc(thr,
82899 			                            DUK_HOBJECT_FLAG_EXTENSIBLE |
82900 			                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
82901 			DUK_ASSERT(new_env != NULL);
82902 			duk_push_hobject(thr, (duk_hobject *) new_env);
82903 
82904 			DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
82905 			DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, proto);
82906 			DUK_HOBJECT_INCREF_ALLOWNULL(thr, proto);
82907 
82908 			DUK_ASSERT(new_env->thread == NULL);  /* Closed. */
82909 			DUK_ASSERT(new_env->varmap == NULL);
82910 
82911 			/* It's important that duk_xdef_prop() is a 'raw define' so that any
82912 			 * properties in an ancestor are never an issue (they should never be
82913 			 * e.g. non-writable, but just in case).
82914 			 *
82915 			 * Because template objects are not visible to user code, the case
82916 			 * where .name is missing shouldn't happen in practice.  It it does,
82917 			 * the name 'undefined' gets bound and maps to the closure (which is
82918 			 * a bit odd, but safe).
82919 			 */
82920 			(void) duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_NAME);
82921 			/* -> [ ... closure template env funcname ] */
82922 			duk_dup_m4(thr);                                           /* -> [ ... closure template env funcname closure ] */
82923 			duk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_NONE);           /* -> [ ... closure template env ] */
82924 			/* env[funcname] = closure */
82925 
82926 			/* [ ... closure template env ] */
82927 
82928 			DUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, (duk_hobject *) new_env);
82929 			DUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, (duk_hobject *) new_env);
82930 			DUK_HOBJECT_INCREF(thr, (duk_hobject *) new_env);
82931 			DUK_HOBJECT_INCREF(thr, (duk_hobject *) new_env);
82932 			duk_pop_unsafe(thr);
82933 
82934 			/* [ ... closure template ] */
82935 		}
82936 		else
82937 #endif  /* DUK_USE_FUNC_NAME_PROPERTY */
82938 		{
82939 			/*
82940 			 *  Other cases (function declaration, anonymous function expression,
82941 			 *  strict direct eval code).  The "outer" environment will be whatever
82942 			 *  the caller gave us.
82943 			 */
82944 
82945 			DUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, outer_lex_env);
82946 			DUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, outer_lex_env);
82947 			DUK_HOBJECT_INCREF(thr, outer_lex_env);
82948 			DUK_HOBJECT_INCREF(thr, outer_lex_env);
82949 
82950 			/* [ ... closure template ] */
82951 		}
82952 	} else {
82953 		/*
82954 		 *  Function gets no new environment when called.  This is the
82955 		 *  case for global code, indirect eval code, and non-strict
82956 		 *  direct eval code.  There is no direct correspondence to the
82957 		 *  E5 specification, as global/eval code is not exposed as a
82958 		 *  function.
82959 		 */
82960 
82961 		DUK_ASSERT(!DUK_HOBJECT_HAS_NAMEBINDING(&fun_temp->obj));
82962 
82963 		DUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, outer_lex_env);
82964 		DUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, outer_var_env);
82965 		DUK_HOBJECT_INCREF(thr, outer_lex_env);  /* NULLs not allowed; asserted on entry */
82966 		DUK_HOBJECT_INCREF(thr, outer_var_env);
82967 	}
82968 	DUK_DDD(DUK_DDDPRINT("closure varenv -> %!ipO, lexenv -> %!ipO",
82969 	                     (duk_heaphdr *) fun_clos->var_env,
82970 	                     (duk_heaphdr *) fun_clos->lex_env));
82971 
82972 	/* Call handling assumes this for all callable closures. */
82973 	DUK_ASSERT(DUK_HCOMPFUNC_GET_LEXENV(thr->heap, fun_clos) != NULL);
82974 	DUK_ASSERT(DUK_HCOMPFUNC_GET_VARENV(thr->heap, fun_clos) != NULL);
82975 
82976 	/*
82977 	 *  Copy some internal properties directly
82978 	 *
82979 	 *  The properties will be non-writable and non-enumerable, but
82980 	 *  configurable.
82981 	 *
82982 	 *  Function templates are bare objects, so inheritance of internal
82983 	 *  Symbols is not an issue here even when using ordinary property
82984 	 *  reads.  The function instance created is not bare, so internal
82985 	 *  Symbols must be defined without inheritance checks.
82986 	 */
82987 
82988 	/* [ ... closure template ] */
82989 
82990 	DUK_DDD(DUK_DDDPRINT("copying properties: closure=%!iT, template=%!iT",
82991 	                     (duk_tval *) duk_get_tval(thr, -2),
82992 	                     (duk_tval *) duk_get_tval(thr, -1)));
82993 
82994 	for (i = 0; i < (duk_small_uint_t) (sizeof(duk__closure_copy_proplist) / sizeof(duk_uint16_t)); i++) {
82995 		duk_small_int_t stridx = (duk_small_int_t) duk__closure_copy_proplist[i];
82996 		if (duk_xget_owndataprop_stridx_short(thr, -1, stridx)) {
82997 			/* [ ... closure template val ] */
82998 			DUK_DDD(DUK_DDDPRINT("copying property, stridx=%ld -> found", (long) stridx));
82999 			duk_xdef_prop_stridx_short(thr, -3, stridx, DUK_PROPDESC_FLAGS_C);
83000 		} else {
83001 			DUK_DDD(DUK_DDDPRINT("copying property, stridx=%ld -> not found", (long) stridx));
83002 			duk_pop_unsafe(thr);
83003 		}
83004 	}
83005 
83006 	/*
83007 	 *  "length" maps to number of formals (E5 Section 13.2) for function
83008 	 *  declarations/expressions (non-bound functions).  Note that 'nargs'
83009 	 *  is NOT necessarily equal to the number of arguments.  Use length
83010 	 *  of _Formals; if missing, assume nargs matches .length.
83011 	 */
83012 
83013 	/* [ ... closure template ] */
83014 
83015 	formals = duk_hobject_get_formals(thr, (duk_hobject *) fun_temp);
83016 	if (formals) {
83017 		len_value = (duk_uint_t) formals->length;
83018 		DUK_DD(DUK_DDPRINT("closure length from _Formals -> %ld", (long) len_value));
83019 	} else {
83020 		len_value = fun_temp->nargs;
83021 		DUK_DD(DUK_DDPRINT("closure length defaulted from nargs -> %ld", (long) len_value));
83022 	}
83023 
83024 	duk_push_uint(thr, len_value);  /* [ ... closure template len_value ] */
83025 	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);
83026 
83027 	/*
83028 	 *  "prototype" is, by default, a fresh object with the "constructor"
83029 	 *  property.
83030 	 *
83031 	 *  Note that this creates a circular reference for every function
83032 	 *  instance (closure) which prevents refcount-based collection of
83033 	 *  function instances.
83034 	 *
83035 	 *  XXX: Try to avoid creating the default prototype object, because
83036 	 *  many functions are not used as constructors and the default
83037 	 *  prototype is unnecessary.  Perhaps it could be created on-demand
83038 	 *  when it is first accessed?
83039 	 */
83040 
83041 	/* [ ... closure template ] */
83042 
83043 	if (add_auto_proto) {
83044 		duk_push_object(thr);  /* -> [ ... closure template newobj ] */
83045 		duk_dup_m3(thr);       /* -> [ ... closure template newobj closure ] */
83046 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC);  /* -> [ ... closure template newobj ] */
83047 		duk_compact(thr, -1);  /* compact the prototype */
83048 		duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W);     /* -> [ ... closure template ] */
83049 	}
83050 
83051 	/*
83052 	 *  "arguments" and "caller" must be mapped to throwers for strict
83053 	 *  mode and bound functions (E5 Section 15.3.5).
83054 	 *
83055 	 *  XXX: This is expensive to have for every strict function instance.
83056 	 *  Try to implement as virtual properties or on-demand created properties.
83057 	 */
83058 
83059 	/* [ ... closure template ] */
83060 
83061 	if (DUK_HOBJECT_HAS_STRICT(&fun_clos->obj)) {
83062 		duk_xdef_prop_stridx_thrower(thr, -2, DUK_STRIDX_CALLER);
83063 		duk_xdef_prop_stridx_thrower(thr, -2, DUK_STRIDX_LC_ARGUMENTS);
83064 	} else {
83065 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
83066 		DUK_DDD(DUK_DDDPRINT("function is non-strict and non-standard 'caller' property in use, add initial 'null' value"));
83067 		duk_push_null(thr);
83068 		duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_CALLER, DUK_PROPDESC_FLAGS_NONE);
83069 #else
83070 		DUK_DDD(DUK_DDDPRINT("function is non-strict and non-standard 'caller' property not used"));
83071 #endif
83072 	}
83073 
83074 	/*
83075 	 *  "name" used to be non-standard but is now defined by ES2015.
83076 	 *  In ES2015/ES2016 the .name property is configurable.
83077 	 */
83078 
83079 	/* [ ... closure template ] */
83080 
83081 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
83082 	/* XXX: Look for own property only; doesn't matter much because
83083 	 * templates are bare objects.
83084 	 */
83085 	if (duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_NAME)) {
83086 		/* [ ... closure template name ] */
83087 		DUK_ASSERT(duk_is_string(thr, -1));
83088 		DUK_DD(DUK_DDPRINT("setting function instance name to %!T", duk_get_tval(thr, -1)));
83089 		duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);  /* -> [ ... closure template ] */
83090 	} else {
83091 		/* Anonymous functions don't have a .name in ES2015, so don't set
83092 		 * it on the instance either.  The instance will then inherit
83093 		 * it from Function.prototype.name.
83094 		 */
83095 		DUK_DD(DUK_DDPRINT("not setting function instance .name"));
83096 		duk_pop_unsafe(thr);
83097 	}
83098 #endif
83099 
83100 	/*
83101 	 *  Compact the closure, in most cases no properties will be added later.
83102 	 *  Also, without this the closures end up having unused property slots
83103 	 *  (e.g. in Duktape 0.9.0, 8 slots would be allocated and only 7 used).
83104 	 *  A better future solution would be to allocate the closure directly
83105 	 *  to correct size (and setup the properties directly without going
83106 	 *  through the API).
83107 	 */
83108 
83109 	duk_compact(thr, -2);
83110 
83111 	/*
83112 	 *  Some assertions (E5 Section 13.2).
83113 	 */
83114 
83115 	DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(&fun_clos->obj) == DUK_HOBJECT_CLASS_FUNCTION);
83116 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, &fun_clos->obj) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
83117 	DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(&fun_clos->obj));
83118 	DUK_ASSERT(duk_has_prop_stridx(thr, -2, DUK_STRIDX_LENGTH) != 0);
83119 	DUK_ASSERT(add_auto_proto == 0 || duk_has_prop_stridx(thr, -2, DUK_STRIDX_PROTOTYPE) != 0);
83120 	/* May be missing .name */
83121 	DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(&fun_clos->obj) ||
83122 	           duk_has_prop_stridx(thr, -2, DUK_STRIDX_CALLER) != 0);
83123 	DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(&fun_clos->obj) ||
83124 	           duk_has_prop_stridx(thr, -2, DUK_STRIDX_LC_ARGUMENTS) != 0);
83125 
83126 	/*
83127 	 *  Finish
83128 	 */
83129 
83130 	/* [ ... closure template ] */
83131 
83132 	DUK_DDD(DUK_DDDPRINT("created function instance: template=%!iT -> closure=%!iT",
83133 	                     (duk_tval *) duk_get_tval(thr, -1),
83134 	                     (duk_tval *) duk_get_tval(thr, -2)));
83135 
83136 	duk_pop_unsafe(thr);
83137 
83138 	/* [ ... closure ] */
83139 }
83140 
83141 /*
83142  *  Delayed activation environment record initialization (for functions
83143  *  with NEWENV).
83144  *
83145  *  The non-delayed initialization is handled by duk_handle_call().
83146  */
83147 
83148 DUK_LOCAL void duk__preallocate_env_entries(duk_hthread *thr, duk_hobject *varmap, duk_hobject *env) {
83149 	duk_uint_fast32_t i;
83150 
83151 	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(varmap); i++) {
83152 		duk_hstring *key;
83153 
83154 		key = DUK_HOBJECT_E_GET_KEY(thr->heap, varmap, i);
83155 		DUK_ASSERT(key != NULL);   /* assume keys are compact in _Varmap */
83156 		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, varmap, i));  /* assume plain values */
83157 
83158 		/* Predefine as 'undefined' to reserve a property slot.
83159 		 * This makes the unwind process (where register values
83160 		 * are copied to the env object) safe against throwing.
83161 		 *
83162 		 * XXX: This could be made much faster by creating the
83163 		 * property table directly.
83164 		 */
83165 		duk_push_undefined(thr);
83166 		DUK_DDD(DUK_DDDPRINT("preallocate env entry for key %!O", key));
83167 		duk_hobject_define_property_internal(thr, env, key, DUK_PROPDESC_FLAGS_WE);
83168 	}
83169 }
83170 
83171 /* shared helper */
83172 DUK_INTERNAL
83173 duk_hobject *duk_create_activation_environment_record(duk_hthread *thr,
83174                                                       duk_hobject *func,
83175                                                       duk_size_t bottom_byteoff) {
83176 	duk_hdecenv *env;
83177 	duk_hobject *parent;
83178 	duk_hcompfunc *f;
83179 
83180 	DUK_ASSERT(thr != NULL);
83181 	DUK_ASSERT(func != NULL);
83182 
83183 	DUK_STATS_INC(thr->heap, stats_envrec_create);
83184 
83185 	f = (duk_hcompfunc *) func;
83186 	parent = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);
83187 	if (!parent) {
83188 		parent = thr->builtins[DUK_BIDX_GLOBAL_ENV];
83189 	}
83190 
83191 	env = duk_hdecenv_alloc(thr,
83192 	                        DUK_HOBJECT_FLAG_EXTENSIBLE |
83193 	                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
83194 	DUK_ASSERT(env != NULL);
83195 	duk_push_hobject(thr, (duk_hobject *) env);
83196 
83197 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) env) == NULL);
83198 	DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) env, parent);
83199 	DUK_HOBJECT_INCREF_ALLOWNULL(thr, parent);  /* parent env is the prototype */
83200 
83201 	/* open scope information, for compiled functions only */
83202 
83203 	DUK_ASSERT(env->thread == NULL);
83204 	DUK_ASSERT(env->varmap == NULL);
83205 	DUK_ASSERT(env->regbase_byteoff == 0);
83206 	if (DUK_HOBJECT_IS_COMPFUNC(func)) {
83207 		duk_hobject *varmap;
83208 
83209 		varmap = duk_hobject_get_varmap(thr, func);
83210 		if (varmap != NULL) {
83211 			env->varmap = varmap;
83212 			DUK_HOBJECT_INCREF(thr, varmap);
83213 			env->thread = thr;
83214 			DUK_HTHREAD_INCREF(thr, thr);
83215 			env->regbase_byteoff = bottom_byteoff;
83216 
83217 			/* Preallocate env property table to avoid potential
83218 			 * for out-of-memory on unwind when the env is closed.
83219 			 */
83220 			duk__preallocate_env_entries(thr, varmap, (duk_hobject *) env);
83221 		} else {
83222 			/* If function has no _Varmap, leave the environment closed. */
83223 			DUK_ASSERT(env->thread == NULL);
83224 			DUK_ASSERT(env->varmap == NULL);
83225 			DUK_ASSERT(env->regbase_byteoff == 0);
83226 		}
83227 	}
83228 
83229 	return (duk_hobject *) env;
83230 }
83231 
83232 DUK_INTERNAL
83233 void duk_js_init_activation_environment_records_delayed(duk_hthread *thr,
83234                                                         duk_activation *act) {
83235 	duk_hobject *func;
83236 	duk_hobject *env;
83237 
83238 	DUK_ASSERT(thr != NULL);
83239 	func = DUK_ACT_GET_FUNC(act);
83240 	DUK_ASSERT(func != NULL);
83241 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));  /* bound functions are never in act 'func' */
83242 
83243 	/*
83244 	 *  Delayed initialization only occurs for 'NEWENV' functions.
83245 	 */
83246 
83247 	DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
83248 	DUK_ASSERT(act->lex_env == NULL);
83249 	DUK_ASSERT(act->var_env == NULL);
83250 
83251 	DUK_STATS_INC(thr->heap, stats_envrec_delayedcreate);
83252 
83253 	env = duk_create_activation_environment_record(thr, func, act->bottom_byteoff);
83254 	DUK_ASSERT(env != NULL);
83255 	/* 'act' is a stable pointer, so still OK. */
83256 
83257 	DUK_DDD(DUK_DDDPRINT("created delayed fresh env: %!ipO", (duk_heaphdr *) env));
83258 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
83259 	{
83260 		duk_hobject *p = env;
83261 		while (p) {
83262 			DUK_DDD(DUK_DDDPRINT("  -> %!ipO", (duk_heaphdr *) p));
83263 			p = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, p);
83264 		}
83265 	}
83266 #endif
83267 
83268 	act->lex_env = env;
83269 	act->var_env = env;
83270 	DUK_HOBJECT_INCREF(thr, env);  /* XXX: incref by count (here 2 times) */
83271 	DUK_HOBJECT_INCREF(thr, env);
83272 
83273 	duk_pop_unsafe(thr);
83274 }
83275 
83276 /*
83277  *  Closing environment records.
83278  *
83279  *  The environment record MUST be closed with the thread where its activation
83280  *  is; i.e. if 'env' is open, 'thr' must match env->thread, and the regbase
83281  *  and varmap must still be valid.  On entry, 'env' must be reachable.
83282  */
83283 
83284 DUK_INTERNAL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env) {
83285 	duk_uint_fast32_t i;
83286 	duk_hobject *varmap;
83287 	duk_hstring *key;
83288 	duk_tval *tv;
83289 	duk_uint_t regnum;
83290 
83291 	DUK_ASSERT(thr != NULL);
83292 	DUK_ASSERT(env != NULL);
83293 
83294 	if (DUK_UNLIKELY(!DUK_HOBJECT_IS_DECENV(env))) {
83295 		DUK_DDD(DUK_DDDPRINT("env not a declarative record: %!iO", (duk_heaphdr *) env));
83296 		return;
83297 	}
83298 
83299 	varmap = ((duk_hdecenv *) env)->varmap;
83300 	if (varmap == NULL) {
83301 		DUK_DDD(DUK_DDDPRINT("env already closed: %!iO", (duk_heaphdr *) env));
83302 
83303 		return;
83304 	}
83305 	DUK_ASSERT(((duk_hdecenv *) env)->thread != NULL);
83306 	DUK_HDECENV_ASSERT_VALID((duk_hdecenv *) env);
83307 
83308 	DUK_DDD(DUK_DDDPRINT("closing env: %!iO", (duk_heaphdr *) env));
83309 	DUK_DDD(DUK_DDDPRINT("varmap: %!O", (duk_heaphdr *) varmap));
83310 
83311 	/* Env must be closed in the same thread as where it runs. */
83312 	DUK_ASSERT(((duk_hdecenv *) env)->thread == thr);
83313 
83314 	/* XXX: additional conditions when to close variables? we don't want to do it
83315 	 * unless the environment may have "escaped" (referenced in a function closure).
83316 	 * With delayed environments, the existence is probably good enough of a check.
83317 	 */
83318 
83319 	/* Note: we rely on the _Varmap having a bunch of nice properties, like:
83320 	 *  - being compacted and unmodified during this process
83321 	 *  - not containing an array part
83322 	 *  - having correct value types
83323 	 */
83324 
83325 	DUK_DDD(DUK_DDDPRINT("copying bound register values, %ld bound regs", (long) DUK_HOBJECT_GET_ENEXT(varmap)));
83326 
83327 	/* Copy over current variable values from value stack to the
83328 	 * environment record.  The scope object is empty but may
83329 	 * inherit from another scope which has conflicting names.
83330 	 */
83331 
83332 	/* XXX: Do this using a once allocated entry area, no side effects.
83333 	 * Hash part would need special treatment however (maybe copy, and
83334 	 * then realloc with hash part if large enough).
83335 	 */
83336 	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(varmap); i++) {
83337 		duk_size_t regbase_byteoff;
83338 
83339 		key = DUK_HOBJECT_E_GET_KEY(thr->heap, varmap, i);
83340 		DUK_ASSERT(key != NULL);   /* assume keys are compact in _Varmap */
83341 		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, varmap, i));  /* assume plain values */
83342 
83343 		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, varmap, i);
83344 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
83345 		DUK_ASSERT(DUK_TVAL_GET_NUMBER(tv) <= (duk_double_t) DUK_UINT32_MAX);  /* limits */
83346 #if defined(DUK_USE_FASTINT)
83347 		DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
83348 		regnum = (duk_uint_t) DUK_TVAL_GET_FASTINT_U32(tv);
83349 #else
83350 		regnum = (duk_uint_t) DUK_TVAL_GET_NUMBER(tv);
83351 #endif
83352 
83353 		regbase_byteoff = ((duk_hdecenv *) env)->regbase_byteoff;
83354 		DUK_ASSERT((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum >= (duk_uint8_t *) thr->valstack);
83355 		DUK_ASSERT((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum < (duk_uint8_t *) thr->valstack_top);
83356 
83357 		/* Write register value into env as named properties.
83358 		 * If property already exists, overwrites silently.
83359 		 * Property is writable, but not deletable (not configurable
83360 		 * in terms of property attributes).
83361 		 *
83362 		 * This property write must not throw because we're unwinding
83363 		 * and unwind code is not allowed to throw at present.  The
83364 		 * call itself has no such guarantees, but we've preallocated
83365 		 * entries for each property when the env was created, so no
83366 		 * out-of-memory error should be possible.  If this guarantee
83367 		 * is not provided, problems like GH-476 may happen.
83368 		 */
83369 		duk_push_tval(thr, (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum));
83370 		DUK_DDD(DUK_DDDPRINT("closing identifier %!O -> reg %ld, value %!T",
83371 		                     (duk_heaphdr *) key,
83372 		                     (long) regnum,
83373 		                     (duk_tval *) duk_get_tval(thr, -1)));
83374 		duk_hobject_define_property_internal(thr, env, key, DUK_PROPDESC_FLAGS_WE);
83375 	}
83376 
83377 	/* NULL atomically to avoid inconsistent state + side effects. */
83378 	DUK_HOBJECT_DECREF_NORZ(thr, ((duk_hdecenv *) env)->thread);
83379 	DUK_HOBJECT_DECREF_NORZ(thr, ((duk_hdecenv *) env)->varmap);
83380 	((duk_hdecenv *) env)->thread = NULL;
83381 	((duk_hdecenv *) env)->varmap = NULL;
83382 
83383 	DUK_DDD(DUK_DDDPRINT("env after closing: %!O", (duk_heaphdr *) env));
83384 }
83385 
83386 /*
83387  *  GETIDREF: a GetIdentifierReference-like helper.
83388  *
83389  *  Provides a parent traversing lookup and a single level lookup
83390  *  (for HasBinding).
83391  *
83392  *  Instead of returning the value, returns a bunch of values allowing
83393  *  the caller to read, write, or delete the binding.  Value pointers
83394  *  are duk_tval pointers which can be mutated directly as long as
83395  *  refcounts are properly updated.  Note that any operation which may
83396  *  reallocate valstacks or compact objects may invalidate the returned
83397  *  duk_tval (but not object) pointers, so caller must be very careful.
83398  *
83399  *  If starting environment record 'env' is given, 'act' is ignored.
83400  *  However, if 'env' is NULL, the caller may identify, in 'act', an
83401  *  activation which hasn't had its declarative environment initialized
83402  *  yet.  The activation registers are then looked up, and its parent
83403  *  traversed normally.
83404  *
83405  *  The 'out' structure values are only valid if the function returns
83406  *  success (non-zero).
83407  */
83408 
83409 /* lookup name from an open declarative record's registers */
83410 DUK_LOCAL
83411 duk_bool_t duk__getid_open_decl_env_regs(duk_hthread *thr,
83412                                          duk_hstring *name,
83413                                          duk_hdecenv *env,
83414                                          duk__id_lookup_result *out) {
83415 	duk_tval *tv;
83416 	duk_size_t reg_rel;
83417 
83418 	DUK_ASSERT(thr != NULL);
83419 	DUK_ASSERT(name != NULL);
83420 	DUK_ASSERT(env != NULL);
83421 	DUK_ASSERT(out != NULL);
83422 
83423 	DUK_ASSERT(DUK_HOBJECT_IS_DECENV((duk_hobject *) env));
83424 	DUK_HDECENV_ASSERT_VALID(env);
83425 
83426 	if (env->thread == NULL) {
83427 		/* already closed */
83428 		return 0;
83429 	}
83430 	DUK_ASSERT(env->varmap != NULL);
83431 
83432 	tv = duk_hobject_find_entry_tval_ptr(thr->heap, env->varmap, name);
83433 	if (DUK_UNLIKELY(tv == NULL)) {
83434 		return 0;
83435 	}
83436 
83437 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
83438 	DUK_ASSERT(DUK_TVAL_GET_NUMBER(tv) <= (duk_double_t) DUK_UINT32_MAX);  /* limits */
83439 #if defined(DUK_USE_FASTINT)
83440 	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
83441 	reg_rel = (duk_size_t) DUK_TVAL_GET_FASTINT_U32(tv);
83442 #else
83443 	reg_rel = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
83444 #endif
83445 	DUK_ASSERT_DISABLE(reg_rel >= 0);  /* unsigned */
83446 
83447 	tv = (duk_tval *) (void *) ((duk_uint8_t *) env->thread->valstack + env->regbase_byteoff + sizeof(duk_tval) * reg_rel);
83448 	DUK_ASSERT(tv >= env->thread->valstack && tv < env->thread->valstack_end);  /* XXX: more accurate? */
83449 
83450 	out->value = tv;
83451 	out->attrs = DUK_PROPDESC_FLAGS_W;  /* registers are mutable, non-deletable */
83452 	out->env = (duk_hobject *) env;
83453 	out->holder = NULL;
83454 	out->has_this = 0;
83455 	return 1;
83456 }
83457 
83458 /* lookup name from current activation record's functions' registers */
83459 DUK_LOCAL
83460 duk_bool_t duk__getid_activation_regs(duk_hthread *thr,
83461                                       duk_hstring *name,
83462                                       duk_activation *act,
83463                                       duk__id_lookup_result *out) {
83464 	duk_tval *tv;
83465 	duk_hobject *func;
83466 	duk_hobject *varmap;
83467 	duk_size_t reg_rel;
83468 
83469 	DUK_ASSERT(thr != NULL);
83470 	DUK_ASSERT(name != NULL);
83471 	DUK_ASSERT(act != NULL);
83472 	DUK_ASSERT(out != NULL);
83473 
83474 	func = DUK_ACT_GET_FUNC(act);
83475 	DUK_ASSERT(func != NULL);
83476 	DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
83477 
83478 	if (!DUK_HOBJECT_IS_COMPFUNC(func)) {
83479 		return 0;
83480 	}
83481 
83482 	/* XXX: move varmap to duk_hcompfunc struct field? */
83483 	varmap = duk_hobject_get_varmap(thr, func);
83484 	if (!varmap) {
83485 		return 0;
83486 	}
83487 
83488 	tv = duk_hobject_find_entry_tval_ptr(thr->heap, varmap, name);
83489 	if (!tv) {
83490 		return 0;
83491 	}
83492 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
83493 	reg_rel = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
83494 	DUK_ASSERT_DISABLE(reg_rel >= 0);
83495 	DUK_ASSERT(reg_rel < ((duk_hcompfunc *) func)->nregs);
83496 
83497 	tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->bottom_byteoff);
83498 	tv += reg_rel;
83499 
83500 	out->value = tv;
83501 	out->attrs = DUK_PROPDESC_FLAGS_W;  /* registers are mutable, non-deletable */
83502 	out->env = NULL;
83503 	out->holder = NULL;
83504 	out->has_this = 0;
83505 	return 1;
83506 }
83507 
83508 DUK_LOCAL
83509 duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
83510                                          duk_hobject *env,
83511                                          duk_hstring *name,
83512                                          duk_activation *act,
83513                                          duk_bool_t parents,
83514                                          duk__id_lookup_result *out) {
83515 	duk_tval *tv;
83516 	duk_uint_t sanity;
83517 
83518 	DUK_ASSERT(thr != NULL);
83519 	DUK_ASSERT(env != NULL || act != NULL);
83520 	DUK_ASSERT(name != NULL);
83521 	DUK_ASSERT(out != NULL);
83522 
83523 	DUK_ASSERT(!env || DUK_HOBJECT_IS_ENV(env));
83524 	DUK_ASSERT(!env || !DUK_HOBJECT_HAS_ARRAY_PART(env));
83525 
83526 	/*
83527 	 *  Conceptually, we look for the identifier binding by starting from
83528 	 *  'env' and following to chain of environment records (represented
83529 	 *  by the prototype chain).
83530 	 *
83531 	 *  If 'env' is NULL, the current activation does not yet have an
83532 	 *  allocated declarative environment record; this should be treated
83533 	 *  exactly as if the environment record existed but had no bindings
83534 	 *  other than register bindings.
83535 	 *
83536 	 *  Note: we assume that with the DUK_HOBJECT_FLAG_NEWENV cleared
83537 	 *  the environment will always be initialized immediately; hence
83538 	 *  a NULL 'env' should only happen with the flag set.  This is the
83539 	 *  case for: (1) function calls, and (2) strict, direct eval calls.
83540 	 */
83541 
83542 	if (env == NULL && act != NULL) {
83543 		duk_hobject *func;
83544 		duk_hcompfunc *f;
83545 
83546 		DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference: env is NULL, activation is non-NULL -> "
83547 		                     "delayed env case, look up activation regs first"));
83548 
83549 		/*
83550 		 *  Try registers
83551 		 */
83552 
83553 		if (duk__getid_activation_regs(thr, name, act, out)) {
83554 			DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
83555 			                     "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
83556 			                     "(found from register bindings when env=NULL)",
83557 			                     (duk_heaphdr *) name, (duk_tval *) out->value,
83558 			                     (long) out->attrs, (long) out->has_this,
83559 			                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
83560 			return 1;
83561 		}
83562 
83563 		DUK_DDD(DUK_DDDPRINT("not found in current activation regs"));
83564 
83565 		/*
83566 		 *  Not found in registers, proceed to the parent record.
83567 		 *  Here we need to determine what the parent would be,
83568 		 *  if 'env' was not NULL (i.e. same logic as when initializing
83569 		 *  the record).
83570 		 *
83571 		 *  Note that environment initialization is only deferred when
83572 		 *  DUK_HOBJECT_HAS_NEWENV is set, and this only happens for:
83573 		 *    - Function code
83574 		 *    - Strict eval code
83575 		 *
83576 		 *  We only need to check _Lexenv here; _Varenv exists only if it
83577 		 *  differs from _Lexenv (and thus _Lexenv will also be present).
83578 		 */
83579 
83580 		if (!parents) {
83581 			DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference failed, no parent traversal "
83582 			                     "(not found from register bindings when env=NULL)"));
83583 			goto fail_not_found;
83584 		}
83585 
83586 		func = DUK_ACT_GET_FUNC(act);
83587 		DUK_ASSERT(func != NULL);
83588 		DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
83589 		f = (duk_hcompfunc *) func;
83590 
83591 		env = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);
83592 		if (!env) {
83593 			env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
83594 		}
83595 
83596 		DUK_DDD(DUK_DDDPRINT("continue lookup from env: %!iO",
83597 		                     (duk_heaphdr *) env));
83598 	}
83599 
83600 	/*
83601 	 *  Prototype walking starting from 'env'.
83602 	 *
83603 	 *  ('act' is not needed anywhere here.)
83604 	 */
83605 
83606 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
83607 	while (env != NULL) {
83608 		duk_small_uint_t cl;
83609 		duk_uint_t attrs;
83610 
83611 		DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference, name=%!O, considering env=%p -> %!iO",
83612 		                     (duk_heaphdr *) name,
83613 		                     (void *) env,
83614 		                     (duk_heaphdr *) env));
83615 
83616 		DUK_ASSERT(env != NULL);
83617 		DUK_ASSERT(DUK_HOBJECT_IS_ENV(env));
83618 		DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(env));
83619 
83620 		cl = DUK_HOBJECT_GET_CLASS_NUMBER(env);
83621 		DUK_ASSERT(cl == DUK_HOBJECT_CLASS_OBJENV || cl == DUK_HOBJECT_CLASS_DECENV);
83622 		if (cl == DUK_HOBJECT_CLASS_DECENV) {
83623 			/*
83624 			 *  Declarative environment record.
83625 			 *
83626 			 *  Identifiers can never be stored in ancestors and are
83627 			 *  always plain values, so we can use an internal helper
83628 			 *  and access the value directly with an duk_tval ptr.
83629 			 *
83630 			 *  A closed environment is only indicated by it missing
83631 			 *  the "book-keeping" properties required for accessing
83632 			 *  register-bound variables.
83633 			 */
83634 
83635 			DUK_HDECENV_ASSERT_VALID((duk_hdecenv *) env);
83636 			if (duk__getid_open_decl_env_regs(thr, name, (duk_hdecenv *) env, out)) {
83637 				DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
83638 				                     "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
83639 				                     "(declarative environment record, scope open, found in regs)",
83640 				                     (duk_heaphdr *) name, (duk_tval *) out->value,
83641 				                     (long) out->attrs, (long) out->has_this,
83642 				                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
83643 				return 1;
83644 			}
83645 
83646 			tv = duk_hobject_find_entry_tval_ptr_and_attrs(thr->heap, env, name, &attrs);
83647 			if (tv) {
83648 				out->value = tv;
83649 				out->attrs = attrs;
83650 				out->env = env;
83651 				out->holder = env;
83652 				out->has_this = 0;
83653 
83654 				DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
83655 				                     "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
83656 				                     "(declarative environment record, found in properties)",
83657 				                     (duk_heaphdr *) name, (duk_tval *) out->value,
83658 				                     (long) out->attrs, (long) out->has_this,
83659 				                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
83660 				return 1;
83661 			}
83662 		} else {
83663 			/*
83664 			 *  Object environment record.
83665 			 *
83666 			 *  Binding (target) object is an external, uncontrolled object.
83667 			 *  Identifier may be bound in an ancestor property, and may be
83668 			 *  an accessor.  Target can also be a Proxy which we must support
83669 			 *  here.
83670 			 */
83671 
83672 			/* XXX: we could save space by using _Target OR _This.  If _Target, assume
83673 			 * this binding is undefined.  If _This, assumes this binding is _This, and
83674 			 * target is also _This.  One property would then be enough.
83675 			 */
83676 
83677 			duk_hobject *target;
83678 			duk_bool_t found;
83679 
83680 			DUK_ASSERT(cl == DUK_HOBJECT_CLASS_OBJENV);
83681 			DUK_HOBJENV_ASSERT_VALID((duk_hobjenv *) env);
83682 
83683 			target = ((duk_hobjenv *) env)->target;
83684 			DUK_ASSERT(target != NULL);
83685 
83686 			/* Target may be a Proxy or property may be an accessor, so we must
83687 			 * use an actual, Proxy-aware hasprop check here.
83688 			 *
83689 			 * out->holder is NOT set to the actual duk_hobject where the
83690 			 * property is found, but rather the object binding target object.
83691 			 */
83692 
83693 #if defined(DUK_USE_ES6_PROXY)
83694 			if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(target))) {
83695 				duk_tval tv_name;
83696 				duk_tval tv_target_tmp;
83697 
83698 				DUK_ASSERT(name != NULL);
83699 				DUK_TVAL_SET_STRING(&tv_name, name);
83700 				DUK_TVAL_SET_OBJECT(&tv_target_tmp, target);
83701 
83702 				found = duk_hobject_hasprop(thr, &tv_target_tmp, &tv_name);
83703 			} else
83704 #endif  /* DUK_USE_ES6_PROXY */
83705 			{
83706 				/* XXX: duk_hobject_hasprop() would be correct for
83707 				 * non-Proxy objects too, but it is about ~20-25%
83708 				 * slower at present so separate code paths for
83709 				 * Proxy and non-Proxy now.
83710 				 */
83711 				found = duk_hobject_hasprop_raw(thr, target, name);
83712 			}
83713 
83714 			if (found) {
83715 				out->value = NULL;  /* can't get value, may be accessor */
83716 				out->attrs = 0;     /* irrelevant when out->value == NULL */
83717 				out->env = env;
83718 				out->holder = target;
83719 				out->has_this = ((duk_hobjenv *) env)->has_this;
83720 
83721 				DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
83722 				                     "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
83723 				                     "(object environment record)",
83724 				                     (duk_heaphdr *) name, (duk_tval *) out->value,
83725 				                     (long) out->attrs, (long) out->has_this,
83726 				                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
83727 				return 1;
83728 			}
83729 		}
83730 
83731 		if (!parents) {
83732 			DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference failed, no parent traversal "
83733 			                     "(not found from first traversed env)"));
83734 			goto fail_not_found;
83735 		}
83736 
83737                 if (DUK_UNLIKELY(sanity-- == 0)) {
83738                         DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
83739 			DUK_WO_NORETURN(return 0;);
83740                 }
83741 		env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env);
83742 	}
83743 
83744 	/*
83745 	 *  Not found (even in global object)
83746 	 */
83747 
83748  fail_not_found:
83749 	return 0;
83750 }
83751 
83752 /*
83753  *  HASVAR: check identifier binding from a given environment record
83754  *  without traversing its parents.
83755  *
83756  *  This primitive is not exposed to user code as such, but is used
83757  *  internally for e.g. declaration binding instantiation.
83758  *
83759  *  See E5 Sections:
83760  *    10.2.1.1.1 HasBinding(N)
83761  *    10.2.1.2.1 HasBinding(N)
83762  *
83763  *  Note: strictness has no bearing on this check.  Hence we don't take
83764  *  a 'strict' parameter.
83765  */
83766 
83767 #if 0  /*unused*/
83768 DUK_INTERNAL
83769 duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr,
83770                                 duk_hobject *env,
83771                                 duk_hstring *name) {
83772 	duk__id_lookup_result ref;
83773 	duk_bool_t parents;
83774 
83775 	DUK_DDD(DUK_DDDPRINT("hasvar: thr=%p, env=%p, name=%!O "
83776 	                     "(env -> %!dO)",
83777 	                     (void *) thr, (void *) env, (duk_heaphdr *) name,
83778 	                     (duk_heaphdr *) env));
83779 
83780 	DUK_ASSERT(thr != NULL);
83781 	DUK_ASSERT(env != NULL);
83782 	DUK_ASSERT(name != NULL);
83783 
83784         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
83785         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
83786 
83787 	DUK_ASSERT(DUK_HOBJECT_IS_ENV(env));
83788 	DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(env));
83789 
83790 	/* lookup results is ignored */
83791 	parents = 0;
83792 	return duk__get_identifier_reference(thr, env, name, NULL, parents, &ref);
83793 }
83794 #endif
83795 
83796 /*
83797  *  GETVAR
83798  *
83799  *  See E5 Sections:
83800  *    11.1.2 Identifier Reference
83801  *    10.3.1 Identifier Resolution
83802  *    11.13.1 Simple Assignment  [example of where the Reference is GetValue'd]
83803  *    8.7.1 GetValue (V)
83804  *    8.12.1 [[GetOwnProperty]] (P)
83805  *    8.12.2 [[GetProperty]] (P)
83806  *    8.12.3 [[Get]] (P)
83807  *
83808  *  If 'throw' is true, always leaves two values on top of stack: [val this].
83809  *
83810  *  If 'throw' is false, returns 0 if identifier cannot be resolved, and the
83811  *  stack will be unaffected in this case.  If identifier is resolved, returns
83812  *  1 and leaves [val this] on top of stack.
83813  *
83814  *  Note: the 'strict' flag of a reference returned by GetIdentifierReference
83815  *  is ignored by GetValue.  Hence we don't take a 'strict' parameter.
83816  *
83817  *  The 'throw' flag is needed for implementing 'typeof' for an unreferenced
83818  *  identifier.  An unreference identifier in other contexts generates a
83819  *  ReferenceError.
83820  */
83821 
83822 DUK_LOCAL
83823 duk_bool_t duk__getvar_helper(duk_hthread *thr,
83824                               duk_hobject *env,
83825                               duk_activation *act,
83826                               duk_hstring *name,
83827                               duk_bool_t throw_flag) {
83828 	duk__id_lookup_result ref;
83829 	duk_tval tv_tmp_obj;
83830 	duk_tval tv_tmp_key;
83831 	duk_bool_t parents;
83832 
83833 	DUK_DDD(DUK_DDDPRINT("getvar: thr=%p, env=%p, act=%p, name=%!O "
83834 	                     "(env -> %!dO)",
83835 	                     (void *) thr, (void *) env, (void *) act,
83836 	                     (duk_heaphdr *) name, (duk_heaphdr *) env));
83837 
83838 	DUK_ASSERT(thr != NULL);
83839 	DUK_ASSERT(name != NULL);
83840 	/* env and act may be NULL */
83841 
83842 	DUK_STATS_INC(thr->heap, stats_getvar_all);
83843 
83844         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
83845         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
83846 
83847 	parents = 1;     /* follow parent chain */
83848 	if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
83849 		if (ref.value) {
83850 			duk_push_tval(thr, ref.value);
83851 			duk_push_undefined(thr);
83852 		} else {
83853 			DUK_ASSERT(ref.holder != NULL);
83854 
83855 			/* ref.holder is safe across the getprop call (even
83856 			 * with side effects) because 'env' is reachable and
83857 			 * ref.holder is a direct heap pointer.
83858 			 */
83859 
83860 			DUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);
83861 			DUK_TVAL_SET_STRING(&tv_tmp_key, name);
83862 			(void) duk_hobject_getprop(thr, &tv_tmp_obj, &tv_tmp_key);  /* [value] */
83863 
83864 			if (ref.has_this) {
83865 				duk_push_hobject(thr, ref.holder);
83866 			} else {
83867 				duk_push_undefined(thr);
83868 			}
83869 
83870 			/* [value this] */
83871 		}
83872 
83873 		return 1;
83874 	} else {
83875 		if (throw_flag) {
83876 			DUK_ERROR_FMT1(thr, DUK_ERR_REFERENCE_ERROR,
83877 			               "identifier '%s' undefined",
83878 			               (const char *) DUK_HSTRING_GET_DATA(name));
83879 			DUK_WO_NORETURN(return 0;);
83880 		}
83881 
83882 		return 0;
83883 	}
83884 }
83885 
83886 DUK_INTERNAL
83887 duk_bool_t duk_js_getvar_envrec(duk_hthread *thr,
83888                                 duk_hobject *env,
83889                                 duk_hstring *name,
83890                                 duk_bool_t throw_flag) {
83891 	return duk__getvar_helper(thr, env, NULL, name, throw_flag);
83892 }
83893 
83894 DUK_INTERNAL
83895 duk_bool_t duk_js_getvar_activation(duk_hthread *thr,
83896                                     duk_activation *act,
83897                                     duk_hstring *name,
83898                                     duk_bool_t throw_flag) {
83899 	DUK_ASSERT(act != NULL);
83900 	return duk__getvar_helper(thr, act->lex_env, act, name, throw_flag);
83901 }
83902 
83903 /*
83904  *  PUTVAR
83905  *
83906  *  See E5 Sections:
83907  *    11.1.2 Identifier Reference
83908  *    10.3.1 Identifier Resolution
83909  *    11.13.1 Simple Assignment  [example of where the Reference is PutValue'd]
83910  *    8.7.2 PutValue (V,W)  [see especially step 3.b, undefined -> automatic global in non-strict mode]
83911  *    8.12.4 [[CanPut]] (P)
83912  *    8.12.5 [[Put]] (P)
83913  *
83914  *  Note: may invalidate any valstack (or object) duk_tval pointers because
83915  *  putting a value may reallocate any object or any valstack.  Caller beware.
83916  */
83917 
83918 DUK_LOCAL
83919 void duk__putvar_helper(duk_hthread *thr,
83920                         duk_hobject *env,
83921                         duk_activation *act,
83922                         duk_hstring *name,
83923                         duk_tval *val,
83924                         duk_bool_t strict) {
83925 	duk__id_lookup_result ref;
83926 	duk_tval tv_tmp_val;
83927 	duk_tval tv_tmp_obj;
83928 	duk_tval tv_tmp_key;
83929 	duk_bool_t parents;
83930 
83931 	DUK_STATS_INC(thr->heap, stats_putvar_all);
83932 
83933 	DUK_DDD(DUK_DDDPRINT("putvar: thr=%p, env=%p, act=%p, name=%!O, val=%p, strict=%ld "
83934 	                     "(env -> %!dO, val -> %!T)",
83935 	                     (void *) thr, (void *) env, (void *) act,
83936 	                     (duk_heaphdr *) name, (void *) val, (long) strict,
83937 	                     (duk_heaphdr *) env, (duk_tval *) val));
83938 
83939 	DUK_ASSERT(thr != NULL);
83940 	DUK_ASSERT(name != NULL);
83941 	DUK_ASSERT(val != NULL);
83942 	/* env and act may be NULL */
83943 
83944 	DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
83945 	DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
83946 	DUK_ASSERT_REFCOUNT_NONZERO_TVAL(val);
83947 
83948 	DUK_TVAL_SET_TVAL(&tv_tmp_val, val);  /* Stabilize. */
83949 	val = NULL;
83950 
83951 	/*
83952 	 *  In strict mode E5 protects 'eval' and 'arguments' from being
83953 	 *  assigned to (or even declared anywhere).  Attempt to do so
83954 	 *  should result in a compile time SyntaxError.  See the internal
83955 	 *  design documentation for details.
83956 	 *
83957 	 *  Thus, we should never come here, run-time, for strict code,
83958 	 *  and name 'eval' or 'arguments'.
83959 	 */
83960 
83961 	DUK_ASSERT(!strict ||
83962 	           (name != DUK_HTHREAD_STRING_EVAL(thr) &&
83963 	            name != DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)));
83964 
83965 	/*
83966 	 *  Lookup variable and update in-place if found.
83967 	 */
83968 
83969 	parents = 1;     /* follow parent chain */
83970 
83971 	if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
83972 		if (ref.value && (ref.attrs & DUK_PROPDESC_FLAG_WRITABLE)) {
83973 			/* Update duk_tval in-place if pointer provided and the
83974 			 * property is writable.  If the property is not writable
83975 			 * (immutable binding), use duk_hobject_putprop() which
83976 			 * will respect mutability.
83977 			 */
83978 			duk_tval *tv_val;
83979 
83980 			tv_val = ref.value;
83981 			DUK_ASSERT(tv_val != NULL);
83982 			DUK_TVAL_SET_TVAL_UPDREF(thr, tv_val, &tv_tmp_val);  /* side effects */
83983 
83984 			/* ref.value invalidated here */
83985 		} else {
83986 			DUK_ASSERT(ref.holder != NULL);
83987 
83988 			DUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);
83989 			DUK_TVAL_SET_STRING(&tv_tmp_key, name);
83990 			(void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, &tv_tmp_val, strict);
83991 
83992 			/* ref.value invalidated here */
83993 		}
83994 
83995 		return;
83996 	}
83997 
83998 	/*
83999 	 *  Not found: write to global object (non-strict) or ReferenceError
84000 	 *  (strict); see E5 Section 8.7.2, step 3.
84001 	 */
84002 
84003 	if (strict) {
84004 		DUK_DDD(DUK_DDDPRINT("identifier binding not found, strict => reference error"));
84005 		DUK_ERROR_FMT1(thr, DUK_ERR_REFERENCE_ERROR,
84006 		               "identifier '%s' undefined",
84007 		               (const char *) DUK_HSTRING_GET_DATA(name));
84008 		DUK_WO_NORETURN(return;);
84009 	}
84010 
84011 	DUK_DDD(DUK_DDDPRINT("identifier binding not found, not strict => set to global"));
84012 
84013 	DUK_TVAL_SET_OBJECT(&tv_tmp_obj, thr->builtins[DUK_BIDX_GLOBAL]);
84014 	DUK_TVAL_SET_STRING(&tv_tmp_key, name);
84015 	(void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, &tv_tmp_val, 0);  /* 0 = no throw */
84016 
84017 	/* NB: 'val' may be invalidated here because put_value may realloc valstack,
84018 	 * caller beware.
84019 	 */
84020 }
84021 
84022 DUK_INTERNAL
84023 void duk_js_putvar_envrec(duk_hthread *thr,
84024                           duk_hobject *env,
84025                           duk_hstring *name,
84026                           duk_tval *val,
84027                           duk_bool_t strict) {
84028 	duk__putvar_helper(thr, env, NULL, name, val, strict);
84029 }
84030 
84031 DUK_INTERNAL
84032 void duk_js_putvar_activation(duk_hthread *thr,
84033                               duk_activation *act,
84034                               duk_hstring *name,
84035                               duk_tval *val,
84036                               duk_bool_t strict) {
84037 	DUK_ASSERT(act != NULL);
84038 	duk__putvar_helper(thr, act->lex_env, act, name, val, strict);
84039 }
84040 
84041 /*
84042  *  DELVAR
84043  *
84044  *  See E5 Sections:
84045  *    11.4.1 The delete operator
84046  *    10.2.1.1.5 DeleteBinding (N)  [declarative environment record]
84047  *    10.2.1.2.5 DeleteBinding (N)  [object environment record]
84048  *
84049  *  Variable bindings established inside eval() are deletable (configurable),
84050  *  other bindings are not, including variables declared in global level.
84051  *  Registers are always non-deletable, and the deletion of other bindings
84052  *  is controlled by the configurable flag.
84053  *
84054  *  For strict mode code, the 'delete' operator should fail with a compile
84055  *  time SyntaxError if applied to identifiers.  Hence, no strict mode
84056  *  run-time deletion of identifiers should ever happen.  This function
84057  *  should never be called from strict mode code!
84058  */
84059 
84060 DUK_LOCAL
84061 duk_bool_t duk__delvar_helper(duk_hthread *thr,
84062                               duk_hobject *env,
84063                               duk_activation *act,
84064                               duk_hstring *name) {
84065 	duk__id_lookup_result ref;
84066 	duk_bool_t parents;
84067 
84068 	DUK_DDD(DUK_DDDPRINT("delvar: thr=%p, env=%p, act=%p, name=%!O "
84069 	                     "(env -> %!dO)",
84070 	                     (void *) thr, (void *) env, (void *) act,
84071 	                     (duk_heaphdr *) name, (duk_heaphdr *) env));
84072 
84073 	DUK_ASSERT(thr != NULL);
84074 	DUK_ASSERT(name != NULL);
84075 	/* env and act may be NULL */
84076 
84077         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
84078 
84079 	parents = 1;     /* follow parent chain */
84080 
84081 	if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
84082 		if (ref.value && !(ref.attrs & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
84083 			/* Identifier found in registers (always non-deletable)
84084 			 * or declarative environment record and non-configurable.
84085 			 */
84086 			return 0;
84087 		}
84088 		DUK_ASSERT(ref.holder != NULL);
84089 
84090 		return duk_hobject_delprop_raw(thr, ref.holder, name, 0);
84091 	}
84092 
84093 	/*
84094 	 *  Not found (even in global object).
84095 	 *
84096 	 *  In non-strict mode this is a silent SUCCESS (!), see E5 Section 11.4.1,
84097 	 *  step 3.b.  In strict mode this case is a compile time SyntaxError so
84098 	 *  we should not come here.
84099 	 */
84100 
84101 	DUK_DDD(DUK_DDDPRINT("identifier to be deleted not found: name=%!O "
84102 	                     "(treated as silent success)",
84103 	                     (duk_heaphdr *) name));
84104 	return 1;
84105 }
84106 
84107 #if 0  /*unused*/
84108 DUK_INTERNAL
84109 duk_bool_t duk_js_delvar_envrec(duk_hthread *thr,
84110                                 duk_hobject *env,
84111                                 duk_hstring *name) {
84112 	return duk__delvar_helper(thr, env, NULL, name);
84113 }
84114 #endif
84115 
84116 DUK_INTERNAL
84117 duk_bool_t duk_js_delvar_activation(duk_hthread *thr,
84118                                     duk_activation *act,
84119                                     duk_hstring *name) {
84120 	DUK_ASSERT(act != NULL);
84121 	return duk__delvar_helper(thr, act->lex_env, act, name);
84122 }
84123 
84124 /*
84125  *  DECLVAR
84126  *
84127  *  See E5 Sections:
84128  *    10.4.3 Entering Function Code
84129  *    10.5 Declaration Binding Instantion
84130  *    12.2 Variable Statement
84131  *    11.1.2 Identifier Reference
84132  *    10.3.1 Identifier Resolution
84133  *
84134  *  Variable declaration behavior is mainly discussed in Section 10.5,
84135  *  and is not discussed in the execution semantics (Sections 11-13).
84136  *
84137  *  Conceptually declarations happen when code (global, eval, function)
84138  *  is entered, before any user code is executed.  In practice, register-
84139  *  bound identifiers are 'declared' automatically (by virtue of being
84140  *  allocated to registers with the initial value 'undefined').  Other
84141  *  identifiers are declared in the function prologue with this primitive.
84142  *
84143  *  Since non-register bindings eventually back to an internal object's
84144  *  properties, the 'prop_flags' argument is used to specify binding
84145  *  type:
84146  *
84147  *    - Immutable binding: set DUK_PROPDESC_FLAG_WRITABLE to false
84148  *    - Non-deletable binding: set DUK_PROPDESC_FLAG_CONFIGURABLE to false
84149  *    - The flag DUK_PROPDESC_FLAG_ENUMERABLE should be set, although it
84150  *      doesn't really matter for internal objects
84151  *
84152  *  All bindings are non-deletable mutable bindings except:
84153  *
84154  *    - Declarations in eval code (mutable, deletable)
84155  *    - 'arguments' binding in strict function code (immutable)
84156  *    - Function name binding of a function expression (immutable)
84157  *
84158  *  Declarations may go to declarative environment records (always
84159  *  so for functions), but may also go to object environment records
84160  *  (e.g. global code).  The global object environment has special
84161  *  behavior when re-declaring a function (but not a variable); see
84162  *  E5.1 specification, Section 10.5, step 5.e.
84163  *
84164  *  Declarations always go to the 'top-most' environment record, i.e.
84165  *  we never check the record chain.  It's not an error even if a
84166  *  property (even an immutable or non-deletable one) of the same name
84167  *  already exists.
84168  *
84169  *  If a declared variable already exists, its value needs to be updated
84170  *  (if possible).  Returns 1 if a PUTVAR needs to be done by the caller;
84171  *  otherwise returns 0.
84172  */
84173 
84174 DUK_LOCAL
84175 duk_bool_t duk__declvar_helper(duk_hthread *thr,
84176                                duk_hobject *env,
84177                                duk_hstring *name,
84178                                duk_tval *val,
84179                                duk_small_uint_t prop_flags,
84180                                duk_bool_t is_func_decl) {
84181 	duk_hobject *holder;
84182 	duk_bool_t parents;
84183 	duk__id_lookup_result ref;
84184 	duk_tval *tv;
84185 
84186 	DUK_DDD(DUK_DDDPRINT("declvar: thr=%p, env=%p, name=%!O, val=%!T, prop_flags=0x%08lx, is_func_decl=%ld "
84187 	                     "(env -> %!iO)",
84188 	                     (void *) thr, (void *) env, (duk_heaphdr *) name,
84189 	                     (duk_tval *) val, (unsigned long) prop_flags,
84190 	                     (unsigned int) is_func_decl, (duk_heaphdr *) env));
84191 
84192 	DUK_ASSERT(thr != NULL);
84193 	DUK_ASSERT(env != NULL);
84194 	DUK_ASSERT(name != NULL);
84195 	DUK_ASSERT(val != NULL);
84196 
84197 	/* Note: in strict mode the compiler should reject explicit
84198 	 * declaration of 'eval' or 'arguments'.  However, internal
84199 	 * bytecode may declare 'arguments' in the function prologue.
84200 	 * We don't bother checking (or asserting) for these now.
84201 	 */
84202 
84203 	/* Note: val is a stable duk_tval pointer.  The caller makes
84204 	 * a value copy into its stack frame, so 'tv_val' is not subject
84205 	 * to side effects here.
84206 	 */
84207 
84208 	/*
84209 	 *  Check whether already declared.
84210 	 *
84211 	 *  We need to check whether the binding exists in the environment
84212 	 *  without walking its parents.  However, we still need to check
84213 	 *  register-bound identifiers and the prototype chain of an object
84214 	 *  environment target object.
84215 	 */
84216 
84217 	parents = 0;  /* just check 'env' */
84218 	if (duk__get_identifier_reference(thr, env, name, NULL, parents, &ref)) {
84219 		duk_int_t e_idx;
84220 		duk_int_t h_idx;
84221 		duk_small_uint_t flags;
84222 
84223 		/*
84224 		 *  Variable already declared, ignore re-declaration.
84225 		 *  The only exception is the updated behavior of E5.1 for
84226 		 *  global function declarations, E5.1 Section 10.5, step 5.e.
84227 		 *  This behavior does not apply to global variable declarations.
84228 		 */
84229 
84230 		if (!(is_func_decl && env == thr->builtins[DUK_BIDX_GLOBAL_ENV])) {
84231 			DUK_DDD(DUK_DDDPRINT("re-declare a binding, ignoring"));
84232 			return 1;  /* 1 -> needs a PUTVAR */
84233 		}
84234 
84235 		/*
84236 		 *  Special behavior in E5.1.
84237 		 *
84238 		 *  Note that even though parents == 0, the conflicting property
84239 		 *  may be an inherited property (currently our global object's
84240 		 *  prototype is Object.prototype).  Step 5.e first operates on
84241 		 *  the existing property (which is potentially in an ancestor)
84242 		 *  and then defines a new property in the global object (and
84243 		 *  never modifies the ancestor).
84244 		 *
84245 		 *  Also note that this logic would become even more complicated
84246 		 *  if the conflicting property might be a virtual one.  Object
84247 		 *  prototype has no virtual properties, though.
84248 		 *
84249 		 *  XXX: this is now very awkward, rework.
84250 		 */
84251 
84252 		DUK_DDD(DUK_DDDPRINT("re-declare a function binding in global object, "
84253 		                     "updated E5.1 processing"));
84254 
84255 		DUK_ASSERT(ref.holder != NULL);
84256 		holder = ref.holder;
84257 
84258 		/* holder will be set to the target object, not the actual object
84259 		 * where the property was found (see duk__get_identifier_reference()).
84260 		 */
84261 		DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(holder) == DUK_HOBJECT_CLASS_GLOBAL);
84262 		DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(holder));  /* global object doesn't have array part */
84263 
84264 		/* XXX: use a helper for prototype traversal; no loop check here */
84265 		/* must be found: was found earlier, and cannot be inherited */
84266 		for (;;) {
84267 			DUK_ASSERT(holder != NULL);
84268 			if (duk_hobject_find_entry(thr->heap, holder, name, &e_idx, &h_idx)) {
84269 				DUK_ASSERT(e_idx >= 0);
84270 				break;
84271 			}
84272 			/* SCANBUILD: NULL pointer dereference, doesn't actually trigger,
84273 			 * asserted above.
84274 			 */
84275 			holder = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, holder);
84276 		}
84277 		DUK_ASSERT(holder != NULL);
84278 		DUK_ASSERT(e_idx >= 0);
84279 		/* SCANBUILD: scan-build produces a NULL pointer dereference warning
84280 		 * below; it never actually triggers because holder is actually never
84281 		 * NULL.
84282 		 */
84283 
84284 		/* ref.holder is global object, holder is the object with the
84285 		 * conflicting property.
84286 		 */
84287 
84288 		flags = DUK_HOBJECT_E_GET_FLAGS(thr->heap, holder, e_idx);
84289 		if (!(flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
84290 			if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
84291 				DUK_DDD(DUK_DDDPRINT("existing property is a non-configurable "
84292 				                     "accessor -> reject"));
84293 				goto fail_existing_attributes;
84294 			}
84295 			if (!((flags & DUK_PROPDESC_FLAG_WRITABLE) &&
84296 			      (flags & DUK_PROPDESC_FLAG_ENUMERABLE))) {
84297 				DUK_DDD(DUK_DDDPRINT("existing property is a non-configurable "
84298 				                     "plain property which is not writable and "
84299 				                     "enumerable -> reject"));
84300 				goto fail_existing_attributes;
84301 			}
84302 
84303 			DUK_DDD(DUK_DDDPRINT("existing property is not configurable but "
84304 			                     "is plain, enumerable, and writable -> "
84305 			                     "allow redeclaration"));
84306 		}
84307 
84308 		if (holder == ref.holder) {
84309 			/* XXX: if duk_hobject_define_property_internal() was updated
84310 			 * to handle a pre-existing accessor property, this would be
84311 			 * a simple call (like for the ancestor case).
84312 			 */
84313 			DUK_DDD(DUK_DDDPRINT("redefine, offending property in global object itself"));
84314 
84315 			if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
84316 				duk_hobject *tmp;
84317 
84318 				tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, holder, e_idx);
84319 				DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, holder, e_idx, NULL);
84320 				DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
84321 				DUK_UNREF(tmp);
84322 				tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, holder, e_idx);
84323 				DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, holder, e_idx, NULL);
84324 				DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
84325 				DUK_UNREF(tmp);
84326 			} else {
84327 				tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx);
84328 				DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);
84329 			}
84330 
84331 			/* Here val would be potentially invalid if we didn't make
84332 			 * a value copy at the caller.
84333 			 */
84334 
84335 			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx);
84336 			DUK_TVAL_SET_TVAL(tv, val);
84337 			DUK_TVAL_INCREF(thr, tv);
84338 			DUK_HOBJECT_E_SET_FLAGS(thr->heap, holder, e_idx, prop_flags);
84339 
84340 			DUK_DDD(DUK_DDDPRINT("updated global binding, final result: "
84341 			                     "value -> %!T, prop_flags=0x%08lx",
84342 			                     (duk_tval *) DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx),
84343 			                     (unsigned long) prop_flags));
84344 		} else {
84345 			DUK_DDD(DUK_DDDPRINT("redefine, offending property in ancestor"));
84346 
84347 			DUK_ASSERT(ref.holder == thr->builtins[DUK_BIDX_GLOBAL]);
84348 			duk_push_tval(thr, val);
84349 			duk_hobject_define_property_internal(thr, ref.holder, name, prop_flags);
84350 		}
84351 
84352 		return 0;
84353 	}
84354 
84355 	/*
84356 	 *  Not found (in registers or record objects).  Declare
84357 	 *  to current variable environment.
84358 	 */
84359 
84360 	/*
84361 	 *  Get holder object
84362 	 */
84363 
84364 	if (DUK_HOBJECT_IS_DECENV(env)) {
84365 		DUK_HDECENV_ASSERT_VALID((duk_hdecenv *) env);
84366 		holder = env;
84367 	} else {
84368 		DUK_HOBJENV_ASSERT_VALID((duk_hobjenv *) env);
84369 		holder = ((duk_hobjenv *) env)->target;
84370 		DUK_ASSERT(holder != NULL);
84371 	}
84372 
84373 	/*
84374 	 *  Define new property
84375 	 *
84376 	 *  Note: this may fail if the holder is not extensible.
84377 	 */
84378 
84379 	/* XXX: this is awkward as we use an internal method which doesn't handle
84380 	 * extensibility etc correctly.  Basically we'd want to do a [[DefineOwnProperty]]
84381 	 * or Object.defineProperty() here.
84382 	 */
84383 
84384 	if (!DUK_HOBJECT_HAS_EXTENSIBLE(holder)) {
84385 		goto fail_not_extensible;
84386 	}
84387 
84388 	duk_push_hobject(thr, holder);
84389 	duk_push_hstring(thr, name);
84390 	duk_push_tval(thr, val);
84391 	duk_xdef_prop(thr, -3, prop_flags);  /* [holder name val] -> [holder] */
84392 	duk_pop_unsafe(thr);
84393 
84394 	return 0;
84395 
84396  fail_existing_attributes:
84397  fail_not_extensible:
84398 	DUK_ERROR_TYPE(thr, "declaration failed");
84399 	DUK_WO_NORETURN(return 0;);
84400 }
84401 
84402 DUK_INTERNAL
84403 duk_bool_t duk_js_declvar_activation(duk_hthread *thr,
84404                                      duk_activation *act,
84405                                      duk_hstring *name,
84406                                      duk_tval *val,
84407                                      duk_small_uint_t prop_flags,
84408                                      duk_bool_t is_func_decl) {
84409 	duk_hobject *env;
84410 	duk_tval tv_val_copy;
84411 
84412 	DUK_ASSERT(act != NULL);
84413 
84414 	/*
84415 	 *  Make a value copy of the input val.  This ensures that
84416 	 *  side effects cannot invalidate the pointer.
84417 	 */
84418 
84419 	DUK_TVAL_SET_TVAL(&tv_val_copy, val);
84420 	val = &tv_val_copy;
84421 
84422 	/*
84423 	 *  Delayed env creation check
84424 	 */
84425 
84426 	if (!act->var_env) {
84427 		DUK_ASSERT(act->lex_env == NULL);
84428 		duk_js_init_activation_environment_records_delayed(thr, act);
84429 		/* 'act' is a stable pointer, so still OK. */
84430 	}
84431 	DUK_ASSERT(act->lex_env != NULL);
84432 	DUK_ASSERT(act->var_env != NULL);
84433 
84434 	env = act->var_env;
84435 	DUK_ASSERT(env != NULL);
84436 	DUK_ASSERT(DUK_HOBJECT_IS_ENV(env));
84437 
84438 	return duk__declvar_helper(thr, env, name, val, prop_flags, is_func_decl);
84439 }
84440 /*
84441  *  Lexer for source files, ToNumber() string conversions, RegExp expressions,
84442  *  and JSON.
84443  *
84444  *  Provides a stream of ECMAScript tokens from an UTF-8/CESU-8 buffer.  The
84445  *  caller can also rewind the token stream into a certain position which is
84446  *  needed by the compiler part for multi-pass scanning.  Tokens are
84447  *  represented as duk_token structures, and contain line number information.
84448  *  Token types are identified with DUK_TOK_* defines.
84449  *
84450  *  Characters are decoded into a fixed size lookup window consisting of
84451  *  decoded Unicode code points, with window positions past the end of the
84452  *  input filled with an invalid codepoint (-1).  The tokenizer can thus
84453  *  perform multiple character lookups efficiently and with few sanity
84454  *  checks (such as access outside the end of the input), which keeps the
84455  *  tokenization code small at the cost of performance.
84456  *
84457  *  Character data in tokens, such as identifier names and string literals,
84458  *  is encoded into CESU-8 format on-the-fly while parsing the token in
84459  *  question.  The string data is made reachable to garbage collection by
84460  *  placing the token-related values in value stack entries allocated for
84461  *  this purpose by the caller.  The characters exist in Unicode code point
84462  *  form only in the fixed size lookup window, which keeps character data
84463  *  expansion (of especially ASCII data) low.
84464  *
84465  *  Token parsing supports the full range of Unicode characters as described
84466  *  in the E5 specification.  Parsing has been optimized for ASCII characters
84467  *  because ordinary ECMAScript code consists almost entirely of ASCII
84468  *  characters.  Matching of complex Unicode codepoint sets (such as in the
84469  *  IdentifierStart and IdentifierPart productions) is optimized for size,
84470  *  and is done using a linear scan of a bit-packed list of ranges.  This is
84471  *  very slow, but should never be entered unless the source code actually
84472  *  contains Unicode characters.
84473  *
84474  *  ECMAScript tokenization is partially context sensitive.  First,
84475  *  additional future reserved words are recognized in strict mode (see E5
84476  *  Section 7.6.1.2).  Second, a forward slash character ('/') can be
84477  *  recognized either as starting a RegExp literal or as a division operator,
84478  *  depending on context.  The caller must provide necessary context flags
84479  *  when requesting a new token.
84480  *
84481  *  Future work:
84482  *
84483  *    * Make line number tracking optional, as it consumes space.
84484  *
84485  *    * Add a feature flag for disabling UTF-8 decoding of input, as most
84486  *      source code is ASCII.  Because of Unicode escapes written in ASCII,
84487  *      this does not allow Unicode support to be removed from e.g.
84488  *      duk_unicode_is_identifier_start() nor does it allow removal of CESU-8
84489  *      encoding of e.g. string literals.
84490  *
84491  *    * Add a feature flag for disabling Unicode compliance of e.g. identifier
84492  *      names.  This allows for a build more than a kilobyte smaller, because
84493  *      Unicode ranges needed by duk_unicode_is_identifier_start() and
84494  *      duk_unicode_is_identifier_part() can be dropped.  String literals
84495  *      should still be allowed to contain escaped Unicode, so this still does
84496  *      not allow removal of CESU-8 encoding of e.g. string literals.
84497  *
84498  *    * Character lookup tables for codepoints above BMP could be stripped.
84499  *
84500  *    * Strictly speaking, E5 specification requires that source code consists
84501  *      of 16-bit code units, and if not, must be conceptually converted to
84502  *      that format first.  The current lexer processes Unicode code points
84503  *      and allows characters outside the BMP.  These should be converted to
84504  *      surrogate pairs while reading the source characters into the window,
84505  *      not after tokens have been formed (as is done now).  However, the fix
84506  *      is not trivial because two characters are decoded from one codepoint.
84507  *
84508  *    * Optimize for speed as well as size.  Large if-else ladders are (at
84509  *      least potentially) slow.
84510  */
84511 
84512 /* #include duk_internal.h -> already included */
84513 
84514 /*
84515  *  Various defines and file specific helper macros
84516  */
84517 
84518 #define DUK__MAX_RE_DECESC_DIGITS     9
84519 #define DUK__MAX_RE_QUANT_DIGITS      9   /* Does not allow e.g. 2**31-1, but one more would allow overflows of u32. */
84520 
84521 /* whether to use macros or helper function depends on call count */
84522 #define DUK__ISDIGIT(x)          ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_9)
84523 #define DUK__ISHEXDIGIT(x)       duk__is_hex_digit((x))
84524 #define DUK__ISOCTDIGIT(x)       ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_7)
84525 #define DUK__ISDIGIT03(x)        ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_3)
84526 #define DUK__ISDIGIT47(x)        ((x) >= DUK_ASC_4 && (x) <= DUK_ASC_7)
84527 
84528 /* lexer character window helpers */
84529 #define DUK__LOOKUP(lex_ctx,idx)            ((lex_ctx)->window[(idx)].codepoint)
84530 #define DUK__ADVANCECHARS(lex_ctx,count)    duk__advance_chars((lex_ctx), (count))
84531 #define DUK__ADVANCEBYTES(lex_ctx,count)    duk__advance_bytes((lex_ctx), (count))
84532 #define DUK__INITBUFFER(lex_ctx)            duk__initbuffer((lex_ctx))
84533 #define DUK__APPENDBUFFER(lex_ctx,x)        duk__appendbuffer((lex_ctx), (duk_codepoint_t) (x))
84534 #define DUK__APPENDBUFFER_ASCII(lex_ctx,x)  duk__appendbuffer_ascii((lex_ctx), (duk_codepoint_t) (x))
84535 
84536 /* lookup shorthands (note: assume context variable is named 'lex_ctx') */
84537 #define DUK__L0()  DUK__LOOKUP(lex_ctx, 0)
84538 #define DUK__L1()  DUK__LOOKUP(lex_ctx, 1)
84539 #define DUK__L2()  DUK__LOOKUP(lex_ctx, 2)
84540 #define DUK__L3()  DUK__LOOKUP(lex_ctx, 3)
84541 #define DUK__L4()  DUK__LOOKUP(lex_ctx, 4)
84542 #define DUK__L5()  DUK__LOOKUP(lex_ctx, 5)
84543 
84544 /* packed advance/token number macro used by multiple functions */
84545 #define DUK__ADVTOK(advbytes,tok)  ((((advbytes) * sizeof(duk_lexer_codepoint)) << 8) + (tok))
84546 
84547 /*
84548  *  Advance lookup window by N characters, filling in new characters as
84549  *  necessary.  After returning caller is guaranteed a character window of
84550  *  at least DUK_LEXER_WINDOW_SIZE characters.
84551  *
84552  *  The main function duk__advance_bytes() is called at least once per every
84553  *  token so it has a major lexer/compiler performance impact.  There are two
84554  *  variants for the main duk__advance_bytes() algorithm: a sliding window
84555  *  approach which is slightly faster at the cost of larger code footprint,
84556  *  and a simple copying one.
84557  *
84558  *  Decoding directly from the source string would be another lexing option.
84559  *  But the lookup window based approach has the advantage of hiding the
84560  *  source string and its encoding effectively which gives more flexibility
84561  *  going forward to e.g. support chunked streaming of source from flash.
84562  *
84563  *  Decodes UTF-8/CESU-8 leniently with support for code points from U+0000 to
84564  *  U+10FFFF, causing an error if the input is unparseable.  Leniency means:
84565  *
84566  *    * Unicode code point validation is intentionally not performed,
84567  *      except to check that the codepoint does not exceed 0x10ffff.
84568  *
84569  *    * In particular, surrogate pairs are allowed and not combined, which
84570  *      allows source files to represent all SourceCharacters with CESU-8.
84571  *      Broken surrogate pairs are allowed, as ECMAScript does not mandate
84572  *      their validation.
84573  *
84574  *    * Allow non-shortest UTF-8 encodings.
84575  *
84576  *  Leniency here causes few security concerns because all character data is
84577  *  decoded into Unicode codepoints before lexer processing, and is then
84578  *  re-encoded into CESU-8.  The source can be parsed as strict UTF-8 with
84579  *  a compiler option.  However, ECMAScript source characters include -all-
84580  *  16-bit unsigned integer codepoints, so leniency seems to be appropriate.
84581  *
84582  *  Note that codepoints above the BMP are not strictly SourceCharacters,
84583  *  but the lexer still accepts them as such.  Before ending up in a string
84584  *  or an identifier name, codepoints above BMP are converted into surrogate
84585  *  pairs and then CESU-8 encoded, resulting in 16-bit Unicode data as
84586  *  expected by ECMAScript.
84587  *
84588  *  An alternative approach to dealing with invalid or partial sequences
84589  *  would be to skip them and replace them with e.g. the Unicode replacement
84590  *  character U+FFFD.  This has limited utility because a replacement character
84591  *  will most likely cause a parse error, unless it occurs inside a string.
84592  *  Further, ECMAScript source is typically pure ASCII.
84593  *
84594  *  See:
84595  *
84596  *     http://en.wikipedia.org/wiki/UTF-8
84597  *     http://en.wikipedia.org/wiki/CESU-8
84598  *     http://tools.ietf.org/html/rfc3629
84599  *     http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences
84600  *
84601  *  Future work:
84602  *
84603  *    * Reject other invalid Unicode sequences (see Wikipedia entry for examples)
84604  *      in strict UTF-8 mode.
84605  *
84606  *    * Size optimize.  An attempt to use a 16-byte lookup table for the first
84607  *      byte resulted in a code increase though.
84608  *
84609  *    * Is checking against maximum 0x10ffff really useful?  4-byte encoding
84610  *      imposes a certain limit anyway.
84611  *
84612  *    * Support chunked streaming of source code.  Can be implemented either
84613  *      by streaming chunks of bytes or chunks of codepoints.
84614  */
84615 
84616 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
84617 DUK_LOCAL void duk__fill_lexer_buffer(duk_lexer_ctx *lex_ctx, duk_small_uint_t start_offset_bytes) {
84618 	duk_lexer_codepoint *cp, *cp_end;
84619 	duk_ucodepoint_t x;
84620 	duk_small_uint_t contlen;
84621 	const duk_uint8_t *p, *p_end;
84622 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
84623 	duk_ucodepoint_t mincp;
84624 #endif
84625 	duk_int_t input_line;
84626 
84627 	/* Use temporaries and update lex_ctx only when finished. */
84628 	input_line = lex_ctx->input_line;
84629 	p = lex_ctx->input + lex_ctx->input_offset;
84630 	p_end = lex_ctx->input + lex_ctx->input_length;
84631 
84632 	cp = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->buffer + start_offset_bytes);
84633 	cp_end = lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE;
84634 
84635 	for (; cp != cp_end; cp++) {
84636 		cp->offset = (duk_size_t) (p - lex_ctx->input);
84637 		cp->line = input_line;
84638 
84639 		/* XXX: potential issue with signed pointers, p_end < p. */
84640 		if (DUK_UNLIKELY(p >= p_end)) {
84641 			/* If input_offset were assigned a negative value, it would
84642 			 * result in a large positive value.  Most likely it would be
84643 			 * larger than input_length and be caught here.  In any case
84644 			 * no memory unsafe behavior would happen.
84645 			 */
84646 			cp->codepoint = -1;
84647 			continue;
84648 		}
84649 
84650 		x = (duk_ucodepoint_t) (*p++);
84651 
84652 		/* Fast path. */
84653 
84654 		if (DUK_LIKELY(x < 0x80UL)) {
84655 			DUK_ASSERT(x != 0x2028UL && x != 0x2029UL);  /* not LS/PS */
84656 			if (DUK_UNLIKELY(x <= 0x000dUL)) {
84657 				if ((x == 0x000aUL) ||
84658 				    ((x == 0x000dUL) && (p >= p_end || *p != 0x000aUL))) {
84659 					/* lookup for 0x000a above assumes shortest encoding now */
84660 
84661 					/* E5 Section 7.3, treat the following as newlines:
84662 					 *   LF
84663 					 *   CR [not followed by LF]
84664 					 *   LS
84665 					 *   PS
84666 					 *
84667 					 * For CR LF, CR is ignored if it is followed by LF, and the LF will bump
84668 					 * the line number.
84669 					 */
84670 					input_line++;
84671 				}
84672 			}
84673 
84674 			cp->codepoint = (duk_codepoint_t) x;
84675 			continue;
84676 		}
84677 
84678 		/* Slow path. */
84679 
84680 		if (x < 0xc0UL) {
84681 			/* 10xx xxxx -> invalid */
84682 			goto error_encoding;
84683 		} else if (x < 0xe0UL) {
84684 			/* 110x xxxx   10xx xxxx  */
84685 			contlen = 1;
84686 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
84687 			mincp = 0x80UL;
84688 #endif
84689 			x = x & 0x1fUL;
84690 		} else if (x < 0xf0UL) {
84691 			/* 1110 xxxx   10xx xxxx   10xx xxxx */
84692 			contlen = 2;
84693 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
84694 			mincp = 0x800UL;
84695 #endif
84696 			x = x & 0x0fUL;
84697 		} else if (x < 0xf8UL) {
84698 			/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx */
84699 			contlen = 3;
84700 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
84701 			mincp = 0x10000UL;
84702 #endif
84703 			x = x & 0x07UL;
84704 		} else {
84705 			/* no point in supporting encodings of 5 or more bytes */
84706 			goto error_encoding;
84707 		}
84708 
84709 		DUK_ASSERT(p_end >= p);
84710 		if ((duk_size_t) contlen > (duk_size_t) (p_end - p)) {
84711 			goto error_clipped;
84712 		}
84713 
84714 		while (contlen > 0) {
84715 			duk_small_uint_t y;
84716 			y = *p++;
84717 			if ((y & 0xc0U) != 0x80U) {
84718 				/* check that byte has the form 10xx xxxx */
84719 				goto error_encoding;
84720 			}
84721 			x = x << 6;
84722 			x += y & 0x3fUL;
84723 			contlen--;
84724 		}
84725 
84726 		/* check final character validity */
84727 
84728 		if (x > 0x10ffffUL) {
84729 			goto error_encoding;
84730 		}
84731 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
84732 		if (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) {
84733 			goto error_encoding;
84734 		}
84735 #endif
84736 
84737 		DUK_ASSERT(x != 0x000aUL && x != 0x000dUL);
84738 		if ((x == 0x2028UL) || (x == 0x2029UL)) {
84739 			input_line++;
84740 		}
84741 
84742 		cp->codepoint = (duk_codepoint_t) x;
84743 	}
84744 
84745 	lex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input);
84746 	lex_ctx->input_line = input_line;
84747 	return;
84748 
84749  error_clipped:   /* clipped codepoint */
84750  error_encoding:  /* invalid codepoint encoding or codepoint */
84751 	lex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input);
84752 	lex_ctx->input_line = input_line;
84753 
84754 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_SOURCE_DECODE_FAILED);
84755 	DUK_WO_NORETURN(return;);
84756 }
84757 
84758 DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {
84759 	duk_small_uint_t used_bytes, avail_bytes;
84760 
84761 	DUK_ASSERT_DISABLE(count_bytes >= 0);  /* unsigned */
84762 	DUK_ASSERT(count_bytes <= (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)));
84763 	DUK_ASSERT(lex_ctx->window >= lex_ctx->buffer);
84764 	DUK_ASSERT(lex_ctx->window < lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE);
84765 	DUK_ASSERT((duk_uint8_t *) lex_ctx->window + count_bytes <= (duk_uint8_t *) lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint));
84766 
84767 	/* Zero 'count' is also allowed to make call sites easier.
84768 	 * Arithmetic in bytes generates better code in GCC.
84769 	 */
84770 
84771 	lex_ctx->window = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->window + count_bytes);  /* avoid multiply */
84772 	used_bytes = (duk_small_uint_t) ((duk_uint8_t *) lex_ctx->window - (duk_uint8_t *) lex_ctx->buffer);
84773 	avail_bytes = DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint) - used_bytes;
84774 	if (avail_bytes < (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint))) {
84775 		/* Not enough data to provide a full window, so "scroll" window to
84776 		 * start of buffer and fill up the rest.
84777 		 */
84778 		duk_memmove((void *) lex_ctx->buffer,
84779 		            (const void *) lex_ctx->window,
84780 		            (size_t) avail_bytes);
84781 		lex_ctx->window = lex_ctx->buffer;
84782 		duk__fill_lexer_buffer(lex_ctx, avail_bytes);
84783 	}
84784 }
84785 
84786 DUK_LOCAL void duk__init_lexer_window(duk_lexer_ctx *lex_ctx) {
84787 	lex_ctx->window = lex_ctx->buffer;
84788 	duk__fill_lexer_buffer(lex_ctx, 0);
84789 }
84790 #else  /* DUK_USE_LEXER_SLIDING_WINDOW */
84791 DUK_LOCAL duk_codepoint_t duk__read_char(duk_lexer_ctx *lex_ctx) {
84792 	duk_ucodepoint_t x;
84793 	duk_small_uint_t len;
84794 	duk_small_uint_t i;
84795 	const duk_uint8_t *p;
84796 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
84797 	duk_ucodepoint_t mincp;
84798 #endif
84799 	duk_size_t input_offset;
84800 
84801 	input_offset = lex_ctx->input_offset;
84802 	if (DUK_UNLIKELY(input_offset >= lex_ctx->input_length)) {
84803 		/* If input_offset were assigned a negative value, it would
84804 		 * result in a large positive value.  Most likely it would be
84805 		 * larger than input_length and be caught here.  In any case
84806 		 * no memory unsafe behavior would happen.
84807 		 */
84808 		return -1;
84809 	}
84810 
84811 	p = lex_ctx->input + input_offset;
84812 	x = (duk_ucodepoint_t) (*p);
84813 
84814 	if (DUK_LIKELY(x < 0x80UL)) {
84815 		/* 0xxx xxxx -> fast path */
84816 
84817 		/* input offset tracking */
84818 		lex_ctx->input_offset++;
84819 
84820 		DUK_ASSERT(x != 0x2028UL && x != 0x2029UL);  /* not LS/PS */
84821 		if (DUK_UNLIKELY(x <= 0x000dUL)) {
84822 			if ((x == 0x000aUL) ||
84823 			    ((x == 0x000dUL) && (lex_ctx->input_offset >= lex_ctx->input_length ||
84824 			                         lex_ctx->input[lex_ctx->input_offset] != 0x000aUL))) {
84825 				/* lookup for 0x000a above assumes shortest encoding now */
84826 
84827 				/* E5 Section 7.3, treat the following as newlines:
84828 				 *   LF
84829 				 *   CR [not followed by LF]
84830 				 *   LS
84831 				 *   PS
84832 				 *
84833 				 * For CR LF, CR is ignored if it is followed by LF, and the LF will bump
84834 				 * the line number.
84835 				 */
84836 				lex_ctx->input_line++;
84837 			}
84838 		}
84839 
84840 		return (duk_codepoint_t) x;
84841 	}
84842 
84843 	/* Slow path. */
84844 
84845 	if (x < 0xc0UL) {
84846 		/* 10xx xxxx -> invalid */
84847 		goto error_encoding;
84848 	} else if (x < 0xe0UL) {
84849 		/* 110x xxxx   10xx xxxx  */
84850 		len = 2;
84851 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
84852 		mincp = 0x80UL;
84853 #endif
84854 		x = x & 0x1fUL;
84855 	} else if (x < 0xf0UL) {
84856 		/* 1110 xxxx   10xx xxxx   10xx xxxx */
84857 		len = 3;
84858 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
84859 		mincp = 0x800UL;
84860 #endif
84861 		x = x & 0x0fUL;
84862 	} else if (x < 0xf8UL) {
84863 		/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx */
84864 		len = 4;
84865 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
84866 		mincp = 0x10000UL;
84867 #endif
84868 		x = x & 0x07UL;
84869 	} else {
84870 		/* no point in supporting encodings of 5 or more bytes */
84871 		goto error_encoding;
84872 	}
84873 
84874 	DUK_ASSERT(lex_ctx->input_length >= lex_ctx->input_offset);
84875 	if ((duk_size_t) len > (duk_size_t) (lex_ctx->input_length - lex_ctx->input_offset)) {
84876 		goto error_clipped;
84877 	}
84878 
84879 	p++;
84880 	for (i = 1; i < len; i++) {
84881 		duk_small_uint_t y;
84882 		y = *p++;
84883 		if ((y & 0xc0U) != 0x80U) {
84884 			/* check that byte has the form 10xx xxxx */
84885 			goto error_encoding;
84886 		}
84887 		x = x << 6;
84888 		x += y & 0x3fUL;
84889 	}
84890 
84891 	/* check final character validity */
84892 
84893 	if (x > 0x10ffffUL) {
84894 		goto error_encoding;
84895 	}
84896 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
84897 	if (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) {
84898 		goto error_encoding;
84899 	}
84900 #endif
84901 
84902 	/* input offset tracking */
84903 	lex_ctx->input_offset += len;
84904 
84905 	/* line tracking */
84906 	DUK_ASSERT(x != 0x000aUL && x != 0x000dUL);
84907 	if ((x == 0x2028UL) || (x == 0x2029UL)) {
84908 		lex_ctx->input_line++;
84909 	}
84910 
84911 	return (duk_codepoint_t) x;
84912 
84913  error_clipped:   /* clipped codepoint */
84914  error_encoding:  /* invalid codepoint encoding or codepoint */
84915 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_SOURCE_DECODE_FAILED);
84916 	DUK_WO_NORETURN(return 0;);
84917 }
84918 
84919 DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {
84920 	duk_small_uint_t keep_bytes;
84921 	duk_lexer_codepoint *cp, *cp_end;
84922 
84923 	DUK_ASSERT_DISABLE(count_bytes >= 0);  /* unsigned */
84924 	DUK_ASSERT(count_bytes <= (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)));
84925 
84926 	/* Zero 'count' is also allowed to make call sites easier. */
84927 
84928 	keep_bytes = DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint) - count_bytes;
84929 	duk_memmove((void *) lex_ctx->window,
84930 	            (const void *) ((duk_uint8_t *) lex_ctx->window + count_bytes),
84931 	            (size_t) keep_bytes);
84932 
84933 	cp = (duk_lexer_codepoint *) ((duk_uint8_t *) lex_ctx->window + keep_bytes);
84934 	cp_end = lex_ctx->window + DUK_LEXER_WINDOW_SIZE;
84935 	for (; cp != cp_end; cp++) {
84936 		cp->offset = lex_ctx->input_offset;
84937 		cp->line = lex_ctx->input_line;
84938 		cp->codepoint = duk__read_char(lex_ctx);
84939 	}
84940 }
84941 
84942 DUK_LOCAL void duk__init_lexer_window(duk_lexer_ctx *lex_ctx) {
84943 	/* Call with count == DUK_LEXER_WINDOW_SIZE to fill buffer initially. */
84944 	duk__advance_bytes(lex_ctx, DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint));  /* fill window */
84945 }
84946 #endif  /* DUK_USE_LEXER_SLIDING_WINDOW */
84947 
84948 DUK_LOCAL void duk__advance_chars(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_chars) {
84949 	duk__advance_bytes(lex_ctx, count_chars * sizeof(duk_lexer_codepoint));
84950 }
84951 
84952 /*
84953  *  (Re)initialize the temporary byte buffer.  May be called extra times
84954  *  with little impact.
84955  */
84956 
84957 DUK_LOCAL void duk__initbuffer(duk_lexer_ctx *lex_ctx) {
84958 	/* Reuse buffer as is unless buffer has grown large. */
84959 	if (DUK_HBUFFER_DYNAMIC_GET_SIZE(lex_ctx->buf) < DUK_LEXER_TEMP_BUF_LIMIT) {
84960 		/* Keep current size */
84961 	} else {
84962 		duk_hbuffer_resize(lex_ctx->thr, lex_ctx->buf, DUK_LEXER_TEMP_BUF_LIMIT);
84963 	}
84964 
84965 	DUK_BW_INIT_WITHBUF(lex_ctx->thr, &lex_ctx->bw, lex_ctx->buf);
84966 }
84967 
84968 /*
84969  *  Append a Unicode codepoint to the temporary byte buffer.  Performs
84970  *  CESU-8 surrogate pair encoding for codepoints above the BMP.
84971  *  Existing surrogate pairs are allowed and also encoded into CESU-8.
84972  */
84973 
84974 DUK_LOCAL void duk__appendbuffer(duk_lexer_ctx *lex_ctx, duk_codepoint_t x) {
84975 	/*
84976 	 *  Since character data is only generated by decoding the source or by
84977 	 *  the compiler itself, we rely on the input codepoints being correct
84978 	 *  and avoid a check here.
84979 	 *
84980 	 *  Character data can also come here through decoding of Unicode
84981 	 *  escapes ("\udead\ubeef") so all 16-but unsigned values can be
84982 	 *  present, even when the source file itself is strict UTF-8.
84983 	 */
84984 	DUK_ASSERT(x >= 0 && x <= 0x10ffffL);
84985 
84986 	DUK_BW_WRITE_ENSURE_CESU8(lex_ctx->thr, &lex_ctx->bw, (duk_ucodepoint_t) x);
84987 }
84988 
84989 DUK_LOCAL void duk__appendbuffer_ascii(duk_lexer_ctx *lex_ctx, duk_codepoint_t x) {
84990 	/* ASCII characters can be emitted as a single byte without encoding
84991 	 * which matters for some fast paths.
84992 	 */
84993 	DUK_ASSERT(x >= 0 && x <= 0x7f);
84994 
84995 	DUK_BW_WRITE_ENSURE_U8(lex_ctx->thr, &lex_ctx->bw, (duk_uint8_t) x);
84996 }
84997 
84998 /*
84999  *  Intern the temporary byte buffer into a valstack slot
85000  *  (in practice, slot1 or slot2).
85001  */
85002 
85003 DUK_LOCAL duk_hstring *duk__internbuffer(duk_lexer_ctx *lex_ctx, duk_idx_t valstack_idx) {
85004 	DUK_ASSERT(valstack_idx == lex_ctx->slot1_idx || valstack_idx == lex_ctx->slot2_idx);
85005 
85006 	DUK_BW_PUSH_AS_STRING(lex_ctx->thr, &lex_ctx->bw);
85007 	duk_replace(lex_ctx->thr, valstack_idx);
85008 	return duk_known_hstring(lex_ctx->thr, valstack_idx);
85009 }
85010 
85011 /*
85012  *  Init lexer context
85013  */
85014 
85015 DUK_INTERNAL void duk_lexer_initctx(duk_lexer_ctx *lex_ctx) {
85016 	DUK_ASSERT(lex_ctx != NULL);
85017 
85018 	duk_memzero(lex_ctx, sizeof(*lex_ctx));
85019 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
85020 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
85021 	lex_ctx->window = NULL;
85022 #endif
85023 	lex_ctx->thr = NULL;
85024 	lex_ctx->input = NULL;
85025 	lex_ctx->buf = NULL;
85026 #endif
85027 }
85028 
85029 /*
85030  *  Set lexer input position and reinitialize lookup window.
85031  */
85032 
85033 DUK_INTERNAL void duk_lexer_getpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt) {
85034 	pt->offset = lex_ctx->window[0].offset;
85035 	pt->line = lex_ctx->window[0].line;
85036 }
85037 
85038 DUK_INTERNAL void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt) {
85039 	DUK_ASSERT_DISABLE(pt->offset >= 0);  /* unsigned */
85040 	DUK_ASSERT(pt->line >= 1);
85041 	lex_ctx->input_offset = pt->offset;
85042 	lex_ctx->input_line = pt->line;
85043 	duk__init_lexer_window(lex_ctx);
85044 }
85045 
85046 /*
85047  *  Lexing helpers
85048  */
85049 
85050 /* Numeric value of a hex digit (also covers octal and decimal digits) or
85051  * -1 if not a valid hex digit.
85052  */
85053 DUK_LOCAL duk_codepoint_t duk__hexval_validate(duk_codepoint_t x) {
85054 	duk_small_int_t t;
85055 
85056 	/* Here 'x' is a Unicode codepoint */
85057 	if (DUK_LIKELY(x >= 0 && x <= 0xff)) {
85058 		t = duk_hex_dectab[x];
85059 		if (DUK_LIKELY(t >= 0)) {
85060 			return t;
85061 		}
85062 	}
85063 
85064 	return -1;
85065 }
85066 
85067 /* Just a wrapper for call sites where 'x' is known to be valid so
85068  * we assert for it before decoding.
85069  */
85070 DUK_LOCAL duk_codepoint_t duk__hexval(duk_codepoint_t x) {
85071 	duk_codepoint_t ret;
85072 
85073 	DUK_ASSERT((x >= DUK_ASC_0 && x <= DUK_ASC_9) ||
85074 	           (x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_F) ||
85075 	           (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_F));
85076 	ret = duk__hexval_validate(x);
85077 	DUK_ASSERT(ret >= 0 && ret <= 15);
85078 	return ret;
85079 }
85080 
85081 /* having this as a separate function provided a size benefit */
85082 DUK_LOCAL duk_bool_t duk__is_hex_digit(duk_codepoint_t x) {
85083 	if (DUK_LIKELY(x >= 0 && x <= 0xff)) {
85084 		return (duk_hex_dectab[x] >= 0);
85085 	}
85086 	return 0;
85087 }
85088 
85089 /* Parse a Unicode escape of the form \xHH, \uHHHH, or \u{H+}.  Shared by
85090  * source and RegExp parsing.
85091  */
85092 DUK_LOCAL duk_codepoint_t duk__lexer_parse_escape(duk_lexer_ctx *lex_ctx, duk_bool_t allow_es6) {
85093 	duk_small_int_t digits;  /* Initial value 2 or 4 for fixed length escapes, 0 for ES2015 \u{H+}. */
85094 	duk_codepoint_t escval;
85095 	duk_codepoint_t x;
85096 	duk_small_uint_t adv;
85097 
85098 	DUK_ASSERT(DUK__L0() == DUK_ASC_BACKSLASH);  /* caller responsibilities */
85099 	DUK_ASSERT(DUK__L1() == DUK_ASC_LC_X || DUK__L1() == DUK_ASC_LC_U);
85100 	DUK_UNREF(allow_es6);
85101 
85102 	adv = 2;
85103 	digits = 2;
85104 	if (DUK__L1() == DUK_ASC_LC_U) {
85105 		digits = 4;
85106 #if defined(DUK_USE_ES6_UNICODE_ESCAPE)
85107 		if (DUK__L2() == DUK_ASC_LCURLY && allow_es6) {
85108 			digits = 0;
85109 			adv = 3;
85110 		}
85111 #endif
85112 	}
85113 	DUK__ADVANCECHARS(lex_ctx, adv);
85114 
85115 	escval = 0;
85116 	for (;;) {
85117 		/* One of the escape forms: \xHH, \uHHHH, \u{H+}.
85118 		 * The 'digits' variable tracks parsing state and is
85119 		 * initialized to:
85120 		 *
85121 		 *   \xHH     2
85122 		 *   \uHH     4
85123 		 *   \u{H+}   0 first time, updated to -1 to indicate
85124 		 *            at least one digit has been parsed
85125 		 *
85126 		 * Octal parsing is handled separately because it can be
85127 		 * done with fixed lookahead and also has validation
85128 		 * rules which depend on the escape length (which is
85129 		 * variable).
85130 		 *
85131 		 * We don't need a specific check for x < 0 (end of
85132 		 * input) or duk_unicode_is_line_terminator(x)
85133 		 * because the 'dig' decode will fail and lead to a
85134 		 * SyntaxError.
85135 		 */
85136 		duk_codepoint_t dig;
85137 
85138 		x = DUK__L0();
85139 		DUK__ADVANCECHARS(lex_ctx, 1);
85140 
85141 		dig = duk__hexval_validate(x);
85142 		if (digits > 0) {
85143 			digits--;
85144 			if (dig < 0) {
85145 				goto fail_escape;
85146 			}
85147 			DUK_ASSERT(dig >= 0x00 && dig <= 0x0f);
85148 			escval = (escval << 4) + dig;
85149 			if (digits == 0) {
85150 				DUK_ASSERT(escval >= 0 && escval <= 0xffffL);
85151 				break;
85152 			}
85153 		} else {
85154 #if defined(DUK_USE_ES6_UNICODE_ESCAPE)
85155 			DUK_ASSERT(digits == 0 /* first time */ || digits == -1 /* others */);
85156 			if (dig >= 0) {
85157 				DUK_ASSERT(dig >= 0x00 && dig <= 0x0f);
85158 				escval = (escval << 4) + dig;
85159 				if (escval > 0x10ffffL) {
85160 					goto fail_escape;
85161 				}
85162 			} else if (x == DUK_ASC_RCURLY) {
85163 				if (digits == 0) {
85164 					/* Empty escape, \u{}. */
85165 					goto fail_escape;
85166 				}
85167 				DUK_ASSERT(escval >= 0 && escval <= 0x10ffffL);
85168 				break;
85169 			} else {
85170 				goto fail_escape;
85171 			}
85172 			digits = -1;  /* Indicate we have at least one digit. */
85173 #else  /* DUK_USE_ES6_UNICODE_ESCAPE */
85174 			DUK_ASSERT(0);  /* Never happens if \u{H+} support disabled. */
85175 #endif  /* DUK_USE_ES6_UNICODE_ESCAPE */
85176 		}
85177 	}
85178 
85179 	return escval;
85180 
85181  fail_escape:
85182 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE);
85183 	DUK_WO_NORETURN(return 0;);
85184 }
85185 
85186 /* Parse legacy octal escape of the form \N{1,3}, e.g. \0, \5, \0377.  Maximum
85187  * allowed value is \0377 (U+00FF), longest match is used.  Used for both string
85188  * RegExp octal escape parsing.  Window[0] must be the slash '\' and the first
85189  * digit must already be validated to be in [0-9] by the caller.
85190  */
85191 DUK_LOCAL duk_codepoint_t duk__lexer_parse_legacy_octal(duk_lexer_ctx *lex_ctx, duk_small_uint_t *out_adv, duk_bool_t reject_annex_b) {
85192 	duk_codepoint_t cp;
85193 	duk_small_uint_t lookup_idx;
85194 	duk_small_uint_t adv;
85195 	duk_codepoint_t tmp;
85196 
85197 	DUK_ASSERT(out_adv != NULL);
85198 	DUK_ASSERT(DUK__LOOKUP(lex_ctx, 0) == DUK_ASC_BACKSLASH);
85199 	DUK_ASSERT(DUK__LOOKUP(lex_ctx, 1) >= DUK_ASC_0 && DUK__LOOKUP(lex_ctx, 1) <= DUK_ASC_9);
85200 
85201 	cp = 0;
85202 	tmp = 0;
85203 	for (lookup_idx = 1; lookup_idx <= 3; lookup_idx++) {
85204 		DUK_DDD(DUK_DDDPRINT("lookup_idx=%ld, cp=%ld", (long) lookup_idx, (long) cp));
85205 		tmp = DUK__LOOKUP(lex_ctx, lookup_idx);
85206 		if (tmp < DUK_ASC_0 || tmp > DUK_ASC_7) {
85207 			/* No more valid digits. */
85208 			break;
85209 		}
85210 		tmp = (cp << 3) + (tmp - DUK_ASC_0);
85211 		if (tmp > 0xff) {
85212 			/* Three digit octal escapes above \377 (= 0xff)
85213 			 * are not allowed.
85214 			 */
85215 			break;
85216 		}
85217 		cp = tmp;
85218 	}
85219 	DUK_DDD(DUK_DDDPRINT("final lookup_idx=%ld, cp=%ld", (long) lookup_idx, (long) cp));
85220 
85221 	adv = lookup_idx;
85222 	if (lookup_idx == 1) {
85223 		DUK_DDD(DUK_DDDPRINT("\\8 or \\9 -> treat as literal, accept in strict mode too"));
85224 		DUK_ASSERT(tmp == DUK_ASC_8 || tmp == DUK_ASC_9);
85225 		cp = tmp;
85226 		adv++;  /* correction to above, eat offending character */
85227 	} else if (lookup_idx == 2 && cp == 0) {
85228 		/* Note: 'foo\0bar' is OK in strict mode, but 'foo\00bar' is not.
85229 		 * It won't be interpreted as 'foo\u{0}0bar' but as a SyntaxError.
85230 		 */
85231 		DUK_DDD(DUK_DDDPRINT("\\0 -> accept in strict mode too"));
85232 	} else {
85233 		/* This clause also handles non-shortest zero, e.g. \00. */
85234 		if (reject_annex_b) {
85235 			DUK_DDD(DUK_DDDPRINT("non-zero octal literal %ld -> reject in strict-mode", (long) cp));
85236 			cp = -1;
85237 		} else {
85238 			DUK_DDD(DUK_DDDPRINT("non-zero octal literal %ld -> accepted", (long) cp));
85239 			DUK_ASSERT(cp >= 0 && cp <= 0xff);
85240 		}
85241 	}
85242 
85243 	*out_adv = adv;
85244 
85245 	DUK_ASSERT((cp >= 0 && cp <= 0xff) || (cp == -1 && reject_annex_b));
85246 	return cp;
85247 }
85248 
85249 /* XXX: move strict mode to lex_ctx? */
85250 DUK_LOCAL void duk__lexer_parse_string_literal(duk_lexer_ctx *lex_ctx, duk_token *out_token, duk_small_int_t quote, duk_bool_t strict_mode) {
85251 	duk_small_uint_t adv;
85252 
85253 	for (adv = 1 /* initial quote */ ;;) {
85254 		duk_codepoint_t x;
85255 
85256 		DUK__ADVANCECHARS(lex_ctx, adv);  /* eat opening quote on first loop */
85257 		x = DUK__L0();
85258 
85259 		adv = 1;
85260 		if (x == quote) {
85261 			DUK__ADVANCECHARS(lex_ctx, 1);  /* eat closing quote */
85262 			break;
85263 		} else if (x == '\\') {
85264 			/* DUK__L0        -> '\' char
85265 			 * DUK__L1 ... DUK__L5 -> more lookup
85266 			 */
85267 			duk_small_int_t emitcp = -1;
85268 
85269 			x = DUK__L1();
85270 
85271 			/* How much to advance before next loop. */
85272 			adv = 2;  /* note: long live range */
85273 
85274 			switch (x) {
85275 			case '\'':
85276 				emitcp = 0x0027;
85277 				break;
85278 			case '"':
85279 				emitcp = 0x0022;
85280 				break;
85281 			case '\\':
85282 				emitcp = 0x005c;
85283 				break;
85284 			case 'b':
85285 				emitcp = 0x0008;
85286 				break;
85287 			case 'f':
85288 				emitcp = 0x000c;
85289 				break;
85290 			case 'n':
85291 				emitcp = 0x000a;
85292 				break;
85293 			case 'r':
85294 				emitcp = 0x000d;
85295 				break;
85296 			case 't':
85297 				emitcp = 0x0009;
85298 				break;
85299 			case 'v':
85300 				emitcp = 0x000b;
85301 				break;
85302 			case 'x':
85303 			case 'u': {
85304 				duk_codepoint_t esc_cp;
85305 				esc_cp = duk__lexer_parse_escape(lex_ctx, 1 /*allow_es6*/);
85306 				DUK__APPENDBUFFER(lex_ctx, esc_cp);
85307 				adv = 0;
85308 				break;
85309 			}
85310 			default: {
85311 				if (duk_unicode_is_line_terminator(x)) {
85312 					/* line continuation */
85313 					if (x == 0x000d && DUK__L2() == 0x000a) {
85314 						/* CR LF again a special case */
85315 						adv = 3;  /* line terminator, CR, LF */
85316 					}
85317 				} else if (DUK__ISDIGIT(x)) {
85318 					/*
85319 					 *  Octal escape or zero escape:
85320 					 *    \0                                     (lookahead not OctalDigit)
85321 					 *    \1 ... \7                              (lookahead not OctalDigit)
85322 					 *    \ZeroToThree OctalDigit                (lookahead not OctalDigit)
85323 					 *    \FourToSeven OctalDigit                (no lookahead restrictions)
85324 					 *    \ZeroToThree OctalDigit OctalDigit     (no lookahead restrictions)
85325 					 *
85326 					 *  Zero escape is part of the standard syntax.  Octal escapes are
85327 					 *  defined in E5 Section B.1.2, and are only allowed in non-strict mode.
85328 					 *  Any other productions starting with a decimal digit are invalid
85329 					 *  but are in practice treated like identity escapes.
85330 					 *
85331 					 *  Parse octal (up to 3 digits) from the lookup window.
85332 					 */
85333 
85334 					emitcp = duk__lexer_parse_legacy_octal(lex_ctx, &adv, strict_mode /*reject_annex_b*/);
85335 					if (emitcp < 0) {
85336 						goto fail_escape;
85337 					}
85338 				} else if (x < 0) {
85339 					goto fail_unterminated;
85340 				} else {
85341 					/* escaped NonEscapeCharacter */
85342 					DUK__APPENDBUFFER(lex_ctx, x);
85343 				}
85344 			}  /* end default clause */
85345 			}  /* end switch */
85346 
85347 			/* Shared handling for single codepoint escapes. */
85348 			if (emitcp >= 0) {
85349 				DUK__APPENDBUFFER(lex_ctx, emitcp);
85350 			}
85351 
85352 			/* Track number of escapes; count not really needed but directive
85353 			 * prologues need to detect whether there were any escapes or line
85354 			 * continuations or not.
85355 			 */
85356 			out_token->num_escapes++;
85357 		} else if (x >= 0x20 && x <= 0x7f) {
85358 			/* Fast path for ASCII case, avoids line terminator
85359 			 * check and CESU-8 encoding.
85360 			 */
85361 			DUK_ASSERT(x >= 0);
85362 			DUK_ASSERT(!duk_unicode_is_line_terminator(x));
85363 			DUK_ASSERT(x != quote);
85364 			DUK_ASSERT(x != DUK_ASC_BACKSLASH);
85365 			DUK__APPENDBUFFER_ASCII(lex_ctx, x);
85366 		} else if (x < 0 || duk_unicode_is_line_terminator(x)) {
85367 			goto fail_unterminated;
85368 		} else {
85369 			/* Character which is part of the string but wasn't handled
85370 			 * by the fast path.
85371 			 */
85372 			DUK__APPENDBUFFER(lex_ctx, x);
85373 		}
85374 	} /* string parse loop */
85375 
85376 	return;
85377 
85378  fail_escape:
85379 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE);
85380 	DUK_WO_NORETURN(return;);
85381 
85382  fail_unterminated:
85383 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_STRING);
85384 	DUK_WO_NORETURN(return;);
85385 }
85386 
85387 /* Skip to end-of-line (or end-of-file), used for single line comments. */
85388 DUK_LOCAL void duk__lexer_skip_to_endofline(duk_lexer_ctx *lex_ctx) {
85389 	for (;;) {
85390 		duk_codepoint_t x;
85391 
85392 		x = DUK__L0();
85393 		if (x < 0 || duk_unicode_is_line_terminator(x)) {
85394 			break;
85395 		}
85396 		DUK__ADVANCECHARS(lex_ctx, 1);
85397 	}
85398 }
85399 
85400 /*
85401  *  Parse ECMAScript source InputElementDiv or InputElementRegExp
85402  *  (E5 Section 7), skipping whitespace, comments, and line terminators.
85403  *
85404  *  Possible results are:
85405  *    (1) a token
85406  *    (2) a line terminator (skipped)
85407  *    (3) a comment (skipped)
85408  *    (4) EOF
85409  *
85410  *  White space is automatically skipped from the current position (but
85411  *  not after the input element).  If input has already ended, returns
85412  *  DUK_TOK_EOF indefinitely.  If a parse error occurs, uses an DUK_ERROR()
85413  *  macro call (and hence a longjmp through current heap longjmp context).
85414  *  Comments and line terminator tokens are automatically skipped.
85415  *
85416  *  The input element being matched is determined by regexp_mode; if set,
85417  *  parses a InputElementRegExp, otherwise a InputElementDiv.  The
85418  *  difference between these are handling of productions starting with a
85419  *  forward slash.
85420  *
85421  *  If strict_mode is set, recognizes additional future reserved words
85422  *  specific to strict mode, and refuses to parse octal literals.
85423  *
85424  *  The matching strategy below is to (currently) use a six character
85425  *  lookup window to quickly determine which production is the -longest-
85426  *  matching one, and then parse that.  The top-level if-else clauses
85427  *  match the first character, and the code blocks for each clause
85428  *  handle -all- alternatives for that first character.  ECMAScript
85429  *  specification uses the "longest match wins" semantics, so the order
85430  *  of the if-clauses matters.
85431  *
85432  *  Misc notes:
85433  *
85434  *    * ECMAScript numeric literals do not accept a sign character.
85435  *      Consequently e.g. "-1.0" is parsed as two tokens: a negative
85436  *      sign and a positive numeric literal.  The compiler performs
85437  *      the negation during compilation, so this has no adverse impact.
85438  *
85439  *    * There is no token for "undefined": it is just a value available
85440  *      from the global object (or simply established by doing a reference
85441  *      to an undefined value).
85442  *
85443  *    * Some contexts want Identifier tokens, which are IdentifierNames
85444  *      excluding reserved words, while some contexts want IdentifierNames
85445  *      directly.  In the latter case e.g. "while" is interpreted as an
85446  *      identifier name, not a DUK_TOK_WHILE token.  The solution here is
85447  *      to provide both token types: DUK_TOK_WHILE goes to 't' while
85448  *      DUK_TOK_IDENTIFIER goes to 't_nores', and 'slot1' always contains
85449  *      the identifier / keyword name.
85450  *
85451  *    * Directive prologue needs to identify string literals such as
85452  *      "use strict" and 'use strict', which are sensitive to line
85453  *      continuations and escape sequences.  For instance, "use\u0020strict"
85454  *      is a valid directive but is distinct from "use strict".  The solution
85455  *      here is to decode escapes while tokenizing, but to keep track of the
85456  *      number of escapes.  Directive detection can then check that the
85457  *      number of escapes is zero.
85458  *
85459  *    * Multi-line comments with one or more internal LineTerminator are
85460  *      treated like a line terminator to comply with automatic semicolon
85461  *      insertion.
85462  */
85463 
85464 DUK_INTERNAL
85465 void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
85466                                       duk_token *out_token,
85467                                       duk_bool_t strict_mode,
85468                                       duk_bool_t regexp_mode) {
85469 	duk_codepoint_t x;           /* temporary, must be signed and 32-bit to hold Unicode code points */
85470 	duk_small_uint_t advtok = 0; /* (advance << 8) + token_type, updated at function end,
85471 	                              * init is unnecessary but suppresses "may be used uninitialized" warnings.
85472 	                              */
85473 	duk_bool_t got_lineterm = 0;  /* got lineterm preceding non-whitespace, non-lineterm token */
85474 
85475 	if (++lex_ctx->token_count >= lex_ctx->token_limit) {
85476 		goto fail_token_limit;
85477 	}
85478 
85479 	out_token->t = DUK_TOK_EOF;
85480 	out_token->t_nores = DUK_TOK_INVALID;  /* marker: copy t if not changed */
85481 #if 0  /* not necessary to init, disabled for faster parsing */
85482 	out_token->num = DUK_DOUBLE_NAN;
85483 	out_token->str1 = NULL;
85484 	out_token->str2 = NULL;
85485 #endif
85486 	out_token->num_escapes = 0;
85487 	/* out_token->lineterm set by caller */
85488 
85489 	/* This would be nice, but parsing is faster without resetting the
85490 	 * value slots.  The only side effect is that references to temporary
85491 	 * string values may linger until lexing is finished; they're then
85492 	 * freed normally.
85493 	 */
85494 #if 0
85495 	duk_to_undefined(lex_ctx->thr, lex_ctx->slot1_idx);
85496 	duk_to_undefined(lex_ctx->thr, lex_ctx->slot2_idx);
85497 #endif
85498 
85499 	/* 'advtok' indicates how much to advance and which token id to assign
85500 	 * at the end.  This shared functionality minimizes code size.  All
85501 	 * code paths are required to set 'advtok' to some value, so no default
85502 	 * init value is used.  Code paths calling DUK_ERROR() never return so
85503 	 * they don't need to set advtok.
85504 	 */
85505 
85506 	/*
85507 	 *  Matching order:
85508 	 *
85509 	 *    Punctuator first chars, also covers comments, regexps
85510 	 *    LineTerminator
85511 	 *    Identifier or reserved word, also covers null/true/false literals
85512 	 *    NumericLiteral
85513 	 *    StringLiteral
85514 	 *    EOF
85515 	 *
85516 	 *  The order does not matter as long as the longest match is
85517 	 *  always correctly identified.  There are order dependencies
85518 	 *  in the clauses, so it's not trivial to convert to a switch.
85519 	 */
85520 
85521  restart_lineupdate:
85522 	out_token->start_line = lex_ctx->window[0].line;
85523 
85524  restart:
85525 	out_token->start_offset = lex_ctx->window[0].offset;
85526 
85527 	x = DUK__L0();
85528 
85529 	switch (x) {
85530 	case DUK_ASC_SPACE:
85531 	case DUK_ASC_HT:  /* fast paths for space and tab */
85532 		DUK__ADVANCECHARS(lex_ctx, 1);
85533 		goto restart;
85534 	case DUK_ASC_LF:  /* LF line terminator; CR LF and Unicode lineterms are handled in slow path */
85535 		DUK__ADVANCECHARS(lex_ctx, 1);
85536 		got_lineterm = 1;
85537 		goto restart_lineupdate;
85538 #if defined(DUK_USE_SHEBANG_COMMENTS)
85539 	case DUK_ASC_HASH:  /* '#' */
85540 		if (DUK__L1() == DUK_ASC_EXCLAMATION && lex_ctx->window[0].offset == 0 &&
85541 		    (lex_ctx->flags & DUK_COMPILE_SHEBANG)) {
85542 			/* "Shebang" comment ('#! ...') on first line. */
85543 			/* DUK__ADVANCECHARS(lex_ctx, 2) would be correct here, but not necessary */
85544 			duk__lexer_skip_to_endofline(lex_ctx);
85545 			goto restart;  /* line terminator will be handled on next round */
85546 		}
85547 		goto fail_token;
85548 #endif  /* DUK_USE_SHEBANG_COMMENTS */
85549 	case DUK_ASC_SLASH:  /* '/' */
85550 		if (DUK__L1() == DUK_ASC_SLASH) {
85551 			/*
85552 			 *  E5 Section 7.4, allow SourceCharacter (which is any 16-bit
85553 			 *  code point).
85554 			 */
85555 
85556 			/* DUK__ADVANCECHARS(lex_ctx, 2) would be correct here, but not necessary */
85557 			duk__lexer_skip_to_endofline(lex_ctx);
85558 			goto restart;  /* line terminator will be handled on next round */
85559 		} else if (DUK__L1() == DUK_ASC_STAR) {
85560 			/*
85561 			 *  E5 Section 7.4.  If the multi-line comment contains a newline,
85562 			 *  it is treated like a single line terminator for automatic
85563 			 *  semicolon insertion.
85564 			 */
85565 
85566 			duk_bool_t last_asterisk = 0;
85567 			DUK__ADVANCECHARS(lex_ctx, 2);
85568 			for (;;) {
85569 				x = DUK__L0();
85570 				if (x < 0) {
85571 					goto fail_unterm_comment;
85572 				}
85573 				DUK__ADVANCECHARS(lex_ctx, 1);
85574 				if (last_asterisk && x == DUK_ASC_SLASH) {
85575 					break;
85576 				}
85577 				if (duk_unicode_is_line_terminator(x)) {
85578 					got_lineterm = 1;
85579 				}
85580 				last_asterisk = (x == DUK_ASC_STAR);
85581 			}
85582 			goto restart_lineupdate;
85583 		} else if (regexp_mode) {
85584 #if defined(DUK_USE_REGEXP_SUPPORT)
85585 			/*
85586 			 *  "/" followed by something in regexp mode.  See E5 Section 7.8.5.
85587 			 *
85588 			 *  RegExp parsing is a bit complex.  First, the regexp body is delimited
85589 			 *  by forward slashes, but the body may also contain forward slashes as
85590 			 *  part of an escape sequence or inside a character class (delimited by
85591 			 *  square brackets).  A mini state machine is used to implement these.
85592 			 *
85593 			 *  Further, an early (parse time) error must be thrown if the regexp
85594 			 *  would cause a run-time error when used in the expression new RegExp(...).
85595 			 *  Parsing here simply extracts the (candidate) regexp, and also accepts
85596 			 *  invalid regular expressions (which are delimited properly).  The caller
85597 			 *  (compiler) must perform final validation and regexp compilation.
85598 			 *
85599 			 *  RegExp first char may not be '/' (single line comment) or '*' (multi-
85600 			 *  line comment).  These have already been checked above, so there is no
85601 			 *  need below for special handling of the first regexp character as in
85602 			 *  the E5 productions.
85603 			 *
85604 			 *  About unicode escapes within regexp literals:
85605 			 *
85606 			 *      E5 Section 7.8.5 grammar does NOT accept \uHHHH escapes.
85607 			 *      However, Section 6 states that regexps accept the escapes,
85608 			 *      see paragraph starting with "In string literals...".
85609 			 *      The regexp grammar, which sees the decoded regexp literal
85610 			 *      (after lexical parsing) DOES have a \uHHHH unicode escape.
85611 			 *      So, for instance:
85612 			 *
85613 			 *          /\u1234/
85614 			 *
85615 			 *      should first be parsed by the lexical grammar as:
85616 			 *
85617 			 *          '\' 'u'      RegularExpressionBackslashSequence
85618 			 *          '1'          RegularExpressionNonTerminator
85619 			 *          '2'          RegularExpressionNonTerminator
85620 			 *          '3'          RegularExpressionNonTerminator
85621 			 *          '4'          RegularExpressionNonTerminator
85622 			 *
85623 			 *      and the escape itself is then parsed by the regexp engine.
85624 			 *      This is the current implementation.
85625 			 *
85626 			 *  Minor spec inconsistency:
85627 			 *
85628 			 *      E5 Section 7.8.5 RegularExpressionBackslashSequence is:
85629 			 *
85630 			 *         \ RegularExpressionNonTerminator
85631 			 *
85632 			 *      while Section A.1 RegularExpressionBackslashSequence is:
85633 			 *
85634 			 *         \ NonTerminator
85635 			 *
85636 			 *      The latter is not normative and a typo.
85637 			 *
85638 			 */
85639 
85640 			/* first, parse regexp body roughly */
85641 
85642 			duk_small_int_t state = 0;  /* 0=base, 1=esc, 2=class, 3=class+esc */
85643 
85644 			DUK__INITBUFFER(lex_ctx);
85645 			for (;;) {
85646 				DUK__ADVANCECHARS(lex_ctx, 1);  /* skip opening slash on first loop */
85647 				x = DUK__L0();
85648 				if (x < 0 || duk_unicode_is_line_terminator(x)) {
85649 					goto fail_unterm_regexp;
85650 				}
85651 				x = DUK__L0();  /* re-read to avoid spill / fetch */
85652 				if (state == 0) {
85653 					if (x == DUK_ASC_SLASH) {
85654 						DUK__ADVANCECHARS(lex_ctx, 1);  /* eat closing slash */
85655 						break;
85656 					} else if (x == DUK_ASC_BACKSLASH) {
85657 						state = 1;
85658 					} else if (x == DUK_ASC_LBRACKET) {
85659 						state = 2;
85660 					}
85661 				} else if (state == 1) {
85662 					state = 0;
85663 				} else if (state == 2) {
85664 					if (x == DUK_ASC_RBRACKET) {
85665 						state = 0;
85666 					} else if (x == DUK_ASC_BACKSLASH) {
85667 						state = 3;
85668 					}
85669 				} else { /* state == 3 */
85670 					state = 2;
85671 				}
85672 				DUK__APPENDBUFFER(lex_ctx, x);
85673 			}
85674 			out_token->str1 = duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
85675 
85676 			/* second, parse flags */
85677 
85678 			DUK__INITBUFFER(lex_ctx);
85679 			for (;;) {
85680 				x = DUK__L0();
85681 				if (!duk_unicode_is_identifier_part(x)) {
85682 					break;
85683 				}
85684 				x = DUK__L0();  /* re-read to avoid spill / fetch */
85685 				DUK__APPENDBUFFER(lex_ctx, x);
85686 				DUK__ADVANCECHARS(lex_ctx, 1);
85687 			}
85688 			out_token->str2 = duk__internbuffer(lex_ctx, lex_ctx->slot2_idx);
85689 
85690 			DUK__INITBUFFER(lex_ctx);  /* free some memory */
85691 
85692 			/* validation of the regexp is caller's responsibility */
85693 
85694 			advtok = DUK__ADVTOK(0, DUK_TOK_REGEXP);
85695 #else  /* DUK_USE_REGEXP_SUPPORT */
85696 			goto fail_regexp_support;
85697 #endif  /* DUK_USE_REGEXP_SUPPORT */
85698 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
85699 			/* "/=" and not in regexp mode */
85700 			advtok = DUK__ADVTOK(2, DUK_TOK_DIV_EQ);
85701 		} else {
85702 			/* "/" and not in regexp mode */
85703 			advtok = DUK__ADVTOK(1, DUK_TOK_DIV);
85704 		}
85705 		break;
85706 	case DUK_ASC_LCURLY:  /* '{' */
85707 		advtok = DUK__ADVTOK(1, DUK_TOK_LCURLY);
85708 		break;
85709 	case DUK_ASC_RCURLY:  /* '}' */
85710 		advtok = DUK__ADVTOK(1, DUK_TOK_RCURLY);
85711 		break;
85712 	case DUK_ASC_LPAREN:  /* '(' */
85713 		advtok = DUK__ADVTOK(1, DUK_TOK_LPAREN);
85714 		break;
85715 	case DUK_ASC_RPAREN:  /* ')' */
85716 		advtok = DUK__ADVTOK(1, DUK_TOK_RPAREN);
85717 		break;
85718 	case DUK_ASC_LBRACKET:  /* '[' */
85719 		advtok = DUK__ADVTOK(1, DUK_TOK_LBRACKET);
85720 		break;
85721 	case DUK_ASC_RBRACKET:  /* ']' */
85722 		advtok = DUK__ADVTOK(1, DUK_TOK_RBRACKET);
85723 		break;
85724 	case DUK_ASC_PERIOD:  /* '.' */
85725 		if (DUK__ISDIGIT(DUK__L1())) {
85726 			/* Period followed by a digit can only start DecimalLiteral
85727 			 * (handled in slow path).  We could jump straight into the
85728 			 * DecimalLiteral handling but should avoid goto to inside
85729 			 * a block.
85730 			 */
85731 			goto slow_path;
85732 		}
85733 		advtok = DUK__ADVTOK(1, DUK_TOK_PERIOD);
85734 		break;
85735 	case DUK_ASC_SEMICOLON:  /* ';' */
85736 		advtok = DUK__ADVTOK(1, DUK_TOK_SEMICOLON);
85737 		break;
85738 	case DUK_ASC_COMMA:  /* ',' */
85739 		advtok = DUK__ADVTOK(1, DUK_TOK_COMMA);
85740 		break;
85741 	case DUK_ASC_LANGLE:  /* '<' */
85742 #if defined(DUK_USE_HTML_COMMENTS)
85743 		if (DUK__L1() == DUK_ASC_EXCLAMATION && DUK__L2() == DUK_ASC_MINUS && DUK__L3() == DUK_ASC_MINUS) {
85744 			/*
85745 			 *  ES2015: B.1.3, handle "<!--" SingleLineHTMLOpenComment
85746 			 */
85747 
85748 			/* DUK__ADVANCECHARS(lex_ctx, 4) would be correct here, but not necessary */
85749 			duk__lexer_skip_to_endofline(lex_ctx);
85750 			goto restart;  /* line terminator will be handled on next round */
85751 		}
85752 		else
85753 #endif  /* DUK_USE_HTML_COMMENTS */
85754 		if (DUK__L1() == DUK_ASC_LANGLE && DUK__L2() == DUK_ASC_EQUALS) {
85755 			advtok = DUK__ADVTOK(3, DUK_TOK_ALSHIFT_EQ);
85756 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
85757 			advtok = DUK__ADVTOK(2, DUK_TOK_LE);
85758 		} else if (DUK__L1() == DUK_ASC_LANGLE) {
85759 			advtok = DUK__ADVTOK(2, DUK_TOK_ALSHIFT);
85760 		} else {
85761 			advtok = DUK__ADVTOK(1, DUK_TOK_LT);
85762 		}
85763 		break;
85764 	case DUK_ASC_RANGLE:  /* '>' */
85765 		if (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_RANGLE && DUK__L3() == DUK_ASC_EQUALS) {
85766 			advtok = DUK__ADVTOK(4, DUK_TOK_RSHIFT_EQ);
85767 		} else if (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_RANGLE) {
85768 			advtok = DUK__ADVTOK(3, DUK_TOK_RSHIFT);
85769 		} else if (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_EQUALS) {
85770 			advtok = DUK__ADVTOK(3, DUK_TOK_ARSHIFT_EQ);
85771 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
85772 			advtok = DUK__ADVTOK(2, DUK_TOK_GE);
85773 		} else if (DUK__L1() == DUK_ASC_RANGLE) {
85774 			advtok = DUK__ADVTOK(2, DUK_TOK_ARSHIFT);
85775 		} else {
85776 			advtok = DUK__ADVTOK(1, DUK_TOK_GT);
85777 		}
85778 		break;
85779 	case DUK_ASC_EQUALS:  /* '=' */
85780 		if (DUK__L1() == DUK_ASC_EQUALS && DUK__L2() == DUK_ASC_EQUALS) {
85781 			advtok = DUK__ADVTOK(3, DUK_TOK_SEQ);
85782 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
85783 			advtok = DUK__ADVTOK(2, DUK_TOK_EQ);
85784 		} else {
85785 			advtok = DUK__ADVTOK(1, DUK_TOK_EQUALSIGN);
85786 		}
85787 		break;
85788 	case DUK_ASC_EXCLAMATION:  /* '!' */
85789 		if (DUK__L1() == DUK_ASC_EQUALS && DUK__L2() == DUK_ASC_EQUALS) {
85790 			advtok = DUK__ADVTOK(3, DUK_TOK_SNEQ);
85791 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
85792 			advtok = DUK__ADVTOK(2, DUK_TOK_NEQ);
85793 		} else {
85794 			advtok = DUK__ADVTOK(1, DUK_TOK_LNOT);
85795 		}
85796 		break;
85797 	case DUK_ASC_PLUS:  /* '+' */
85798 		if (DUK__L1() == DUK_ASC_PLUS) {
85799 			advtok = DUK__ADVTOK(2, DUK_TOK_INCREMENT);
85800 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
85801 			advtok = DUK__ADVTOK(2, DUK_TOK_ADD_EQ);
85802 		} else {
85803 			advtok = DUK__ADVTOK(1, DUK_TOK_ADD);
85804 		}
85805 		break;
85806 	case DUK_ASC_MINUS:  /* '-' */
85807 #if defined(DUK_USE_HTML_COMMENTS)
85808 		if (got_lineterm && DUK__L1() == DUK_ASC_MINUS && DUK__L2() == DUK_ASC_RANGLE) {
85809 			/*
85810 			 *  ES2015: B.1.3, handle "-->" SingleLineHTMLCloseComment
85811 			 *  Only allowed:
85812 			 *  - on new line
85813 			 *  - preceded only by whitespace
85814 			 *  - preceded by end of multiline comment and optional whitespace
85815 			 *
85816 			 * Since whitespace generates no tokens, and multiline comments
85817 			 * are treated as a line ending, consulting `got_lineterm` is
85818 			 * sufficient to test for these three options.
85819 			 */
85820 
85821 			/* DUK__ADVANCECHARS(lex_ctx, 3) would be correct here, but not necessary */
85822 			duk__lexer_skip_to_endofline(lex_ctx);
85823 			goto restart;  /* line terminator will be handled on next round */
85824 		} else
85825 #endif  /* DUK_USE_HTML_COMMENTS */
85826 		if (DUK__L1() == DUK_ASC_MINUS) {
85827 			advtok = DUK__ADVTOK(2, DUK_TOK_DECREMENT);
85828 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
85829 			advtok = DUK__ADVTOK(2, DUK_TOK_SUB_EQ);
85830 		} else {
85831 			advtok = DUK__ADVTOK(1, DUK_TOK_SUB);
85832 		}
85833 		break;
85834 	case DUK_ASC_STAR:  /* '*' */
85835 #if defined(DUK_USE_ES7_EXP_OPERATOR)
85836 		if (DUK__L1() == DUK_ASC_STAR && DUK__L2() == DUK_ASC_EQUALS) {
85837 			advtok = DUK__ADVTOK(3, DUK_TOK_EXP_EQ);
85838 		} else if (DUK__L1() == DUK_ASC_STAR) {
85839 			advtok = DUK__ADVTOK(2, DUK_TOK_EXP);
85840 		} else
85841 #endif
85842 		if (DUK__L1() == DUK_ASC_EQUALS) {
85843 			advtok = DUK__ADVTOK(2, DUK_TOK_MUL_EQ);
85844 		} else {
85845 			advtok = DUK__ADVTOK(1, DUK_TOK_MUL);
85846 		}
85847 		break;
85848 	case DUK_ASC_PERCENT:  /* '%' */
85849 		if (DUK__L1() == DUK_ASC_EQUALS) {
85850 			advtok = DUK__ADVTOK(2, DUK_TOK_MOD_EQ);
85851 		} else {
85852 			advtok = DUK__ADVTOK(1, DUK_TOK_MOD);
85853 		}
85854 		break;
85855 	case DUK_ASC_AMP:  /* '&' */
85856 		if (DUK__L1() == DUK_ASC_AMP) {
85857 			advtok = DUK__ADVTOK(2, DUK_TOK_LAND);
85858 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
85859 			advtok = DUK__ADVTOK(2, DUK_TOK_BAND_EQ);
85860 		} else {
85861 			advtok = DUK__ADVTOK(1, DUK_TOK_BAND);
85862 		}
85863 		break;
85864 	case DUK_ASC_PIPE:  /* '|' */
85865 		if (DUK__L1() == DUK_ASC_PIPE) {
85866 			advtok = DUK__ADVTOK(2, DUK_TOK_LOR);
85867 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
85868 			advtok = DUK__ADVTOK(2, DUK_TOK_BOR_EQ);
85869 		} else {
85870 			advtok = DUK__ADVTOK(1, DUK_TOK_BOR);
85871 		}
85872 		break;
85873 	case DUK_ASC_CARET:  /* '^' */
85874 		if (DUK__L1() == DUK_ASC_EQUALS) {
85875 			advtok = DUK__ADVTOK(2, DUK_TOK_BXOR_EQ);
85876 		} else {
85877 			advtok = DUK__ADVTOK(1, DUK_TOK_BXOR);
85878 		}
85879 		break;
85880 	case DUK_ASC_TILDE:  /* '~' */
85881 		advtok = DUK__ADVTOK(1, DUK_TOK_BNOT);
85882 		break;
85883 	case DUK_ASC_QUESTION:  /* '?' */
85884 		advtok = DUK__ADVTOK(1, DUK_TOK_QUESTION);
85885 		break;
85886 	case DUK_ASC_COLON:  /* ':' */
85887 		advtok = DUK__ADVTOK(1, DUK_TOK_COLON);
85888 		break;
85889 	case DUK_ASC_DOUBLEQUOTE:    /* '"' */
85890 	case DUK_ASC_SINGLEQUOTE: {  /* '\'' */
85891 		DUK__INITBUFFER(lex_ctx);
85892 		duk__lexer_parse_string_literal(lex_ctx, out_token, x /*quote*/, strict_mode);
85893 		duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
85894 		out_token->str1 = duk_known_hstring(lex_ctx->thr, lex_ctx->slot1_idx);
85895 
85896 		DUK__INITBUFFER(lex_ctx);  /* free some memory */
85897 
85898 		advtok = DUK__ADVTOK(0, DUK_TOK_STRING);
85899 		break;
85900 	}
85901 	default:
85902 		goto slow_path;
85903 	}  /* switch */
85904 
85905 	goto skip_slow_path;
85906 
85907  slow_path:
85908 	if (duk_unicode_is_line_terminator(x)) {
85909 		if (x == 0x000d && DUK__L1() == 0x000a) {
85910 			/*
85911 			 *  E5 Section 7.3: CR LF is detected as a single line terminator for
85912 			 *  line numbers.  Here we also detect it as a single line terminator
85913 			 *  token.
85914 			 */
85915 			DUK__ADVANCECHARS(lex_ctx, 2);
85916 		} else {
85917 			DUK__ADVANCECHARS(lex_ctx, 1);
85918 		}
85919 		got_lineterm = 1;
85920 		goto restart_lineupdate;
85921 	} else if (duk_unicode_is_identifier_start(x) || x == DUK_ASC_BACKSLASH) {
85922 		/*
85923 		 *  Parse an identifier and then check whether it is:
85924 		 *    - reserved word (keyword or other reserved word)
85925 		 *    - "null"  (NullLiteral)
85926 		 *    - "true"  (BooleanLiteral)
85927 		 *    - "false" (BooleanLiteral)
85928 		 *    - anything else => identifier
85929 		 *
85930 		 *  This does not follow the E5 productions cleanly, but is
85931 		 *  useful and compact.
85932 		 *
85933 		 *  Note that identifiers may contain Unicode escapes,
85934 		 *  see E5 Sections 6 and 7.6.  They must be decoded first,
85935 		 *  and the result checked against allowed characters.
85936 		 *  The above if-clause accepts an identifier start and an
85937 		 *  '\' character -- no other token can begin with a '\'.
85938 		 *
85939 		 *  Note that "get" and "set" are not reserved words in E5
85940 		 *  specification so they are recognized as plain identifiers
85941 		 *  (the tokens DUK_TOK_GET and DUK_TOK_SET are actually not
85942 		 *  used now).  The compiler needs to work around this.
85943 		 *
85944 		 *  Strictly speaking, following ECMAScript longest match
85945 		 *  specification, an invalid escape for the first character
85946 		 *  should cause a syntax error.  However, an invalid escape
85947 		 *  for IdentifierParts should just terminate the identifier
85948 		 *  early (longest match), and let the next tokenization
85949 		 *  fail.  For instance Rhino croaks with 'foo\z' when
85950 		 *  parsing the identifier.  This has little practical impact.
85951 		 */
85952 
85953 		duk_small_uint_t i, i_end;
85954 		duk_bool_t first = 1;
85955 		duk_hstring *str;
85956 
85957 		DUK__INITBUFFER(lex_ctx);
85958 		for (;;) {
85959 			/* re-lookup first char on first loop */
85960 			if (DUK__L0() == DUK_ASC_BACKSLASH) {
85961 				duk_codepoint_t esc_cp;
85962 				if (DUK__L1() != DUK_ASC_LC_U) {
85963 					goto fail_escape;
85964 				}
85965 				esc_cp = duk__lexer_parse_escape(lex_ctx, 1 /*allow_es6*/);
85966 				DUK__APPENDBUFFER(lex_ctx, esc_cp);
85967 
85968 				/* IdentifierStart is stricter than IdentifierPart, so if the first
85969 				 * character is escaped, must have a stricter check here.
85970 				 */
85971 				if (!(first ? duk_unicode_is_identifier_start(esc_cp) : duk_unicode_is_identifier_part(esc_cp))) {
85972 					goto fail_escape;
85973 				}
85974 
85975 				/* Track number of escapes: necessary for proper keyword
85976 				 * detection.
85977 				 */
85978 				out_token->num_escapes++;
85979 			} else {
85980 				/* Note: first character is checked against this.  But because
85981 				 * IdentifierPart includes all IdentifierStart characters, and
85982 				 * the first character (if unescaped) has already been checked
85983 				 * in the if condition, this is OK.
85984 				 */
85985 				if (!duk_unicode_is_identifier_part(DUK__L0())) {
85986 					break;
85987 				}
85988 				DUK__APPENDBUFFER(lex_ctx, DUK__L0());
85989 				DUK__ADVANCECHARS(lex_ctx, 1);
85990 			}
85991 			first = 0;
85992 		}
85993 
85994 		out_token->str1 = duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
85995 		str = out_token->str1;
85996 		out_token->t_nores = DUK_TOK_IDENTIFIER;
85997 
85998 		DUK__INITBUFFER(lex_ctx);  /* free some memory */
85999 
86000 		/*
86001 		 *  Interned identifier is compared against reserved words, which are
86002 		 *  currently interned into the heap context.  See genbuiltins.py.
86003 		 *
86004 		 *  Note that an escape in the identifier disables recognition of
86005 		 *  keywords; e.g. "\u0069f = 1;" is a valid statement (assigns to
86006 		 *  identifier named "if").  This is not necessarily compliant,
86007 		 *  see test-dec-escaped-char-in-keyword.js.
86008 		 *
86009 		 *  Note: "get" and "set" are awkward.  They are not officially
86010 		 *  ReservedWords (and indeed e.g. "var set = 1;" is valid), and
86011 		 *  must come out as DUK_TOK_IDENTIFIER.  The compiler needs to
86012 		 *  work around this a bit.
86013 		 */
86014 
86015 		/* XXX: optimize by adding the token numbers directly into the
86016 		 * always interned duk_hstring objects (there should be enough
86017 		 * flag bits free for that)?
86018 		 */
86019 
86020 		i_end = (strict_mode ? DUK_STRIDX_END_RESERVED : DUK_STRIDX_START_STRICT_RESERVED);
86021 
86022 		advtok = DUK__ADVTOK(0, DUK_TOK_IDENTIFIER);
86023 		if (out_token->num_escapes == 0) {
86024 			for (i = DUK_STRIDX_START_RESERVED; i < i_end; i++) {
86025 				DUK_ASSERT_DISABLE(i >= 0);  /* unsigned */
86026 				DUK_ASSERT(i < DUK_HEAP_NUM_STRINGS);
86027 				if (DUK_HTHREAD_GET_STRING(lex_ctx->thr, i) == str) {
86028 					advtok = DUK__ADVTOK(0, DUK_STRIDX_TO_TOK(i));
86029 					break;
86030 				}
86031 			}
86032 		}
86033 	} else if (DUK__ISDIGIT(x) || (x == DUK_ASC_PERIOD)) {
86034 		/* Note: decimal number may start with a period, but must be followed by a digit */
86035 
86036 		/*
86037 		 *  Pre-parsing for decimal, hex, octal (both legacy and ES2015),
86038 		 *  and binary literals, followed by an actual parser step
86039 		 *  provided by numconv.
86040 		 *
86041 		 *  Note: the leading sign character ('+' or '-') is -not- part of
86042 		 *  the production in E5 grammar, and that the a DecimalLiteral
86043 		 *  starting with a '0' must be followed by a non-digit.
86044 		 *
86045 		 *  XXX: the two step parsing process is quite awkward, it would
86046 		 *  be more straightforward to allow numconv to parse the longest
86047 		 *  valid prefix (it already does that, it only needs to indicate
86048 		 *  where the input ended).  However, the lexer decodes characters
86049 		 *  using a limited lookup window, so this is not a trivial change.
86050 		 */
86051 
86052 		/* XXX: because of the final check below (that the literal is not
86053 		 * followed by a digit), this could maybe be simplified, if we bail
86054 		 * out early from a leading zero (and if there are no periods etc).
86055 		 * Maybe too complex.
86056 		 */
86057 
86058 		duk_double_t val;
86059 		duk_bool_t legacy_oct = 0;
86060 		duk_small_int_t state;  /* 0=before period/exp,
86061 		                         * 1=after period, before exp
86062 		                         * 2=after exp, allow '+' or '-'
86063 		                         * 3=after exp and exp sign
86064 		                         */
86065 		duk_small_uint_t s2n_flags;
86066 		duk_codepoint_t y, z;
86067 		duk_small_int_t s2n_radix = 10;
86068 		duk_small_uint_t pre_adv = 0;
86069 
86070 		DUK__INITBUFFER(lex_ctx);
86071 		y = DUK__L1();
86072 
86073 		if (x == DUK_ASC_0) {
86074 			z = DUK_LOWERCASE_CHAR_ASCII(y);
86075 
86076 			pre_adv = 2;  /* default for 0xNNN, 0oNNN, 0bNNN. */
86077 			if (z == DUK_ASC_LC_X) {
86078 				s2n_radix = 16;
86079 			} else if (z == DUK_ASC_LC_O) {
86080 				s2n_radix = 8;
86081 			} else if (z == DUK_ASC_LC_B) {
86082 				s2n_radix = 2;
86083 			} else {
86084 				pre_adv = 0;
86085 				if (DUK__ISDIGIT(y)) {
86086 					if (strict_mode) {
86087 						/* Reject octal like \07 but also octal-lookalike
86088 						 * decimal like \08 in strict mode.
86089 						 */
86090 						goto fail_number_literal;
86091 					} else {
86092 						/* Legacy OctalIntegerLiteral or octal-lookalice
86093 						 * decimal.  Deciding between the two happens below
86094 						 * in digit scanning.
86095 						 */
86096 						DUK__APPENDBUFFER(lex_ctx, x);
86097 						pre_adv = 1;
86098 						legacy_oct = 1;
86099 						s2n_radix = 8;  /* tentative unless conflicting digits found */
86100 					}
86101 				}
86102 			}
86103 		}
86104 
86105 		DUK__ADVANCECHARS(lex_ctx, pre_adv);
86106 
86107 		/* XXX: we could parse integers here directly, and fall back
86108 		 * to numconv only when encountering a fractional expression
86109 		 * or when an octal literal turned out to be decimal (0778 etc).
86110 		 */
86111 		state = 0;
86112 		for (;;) {
86113 			x = DUK__L0();  /* re-lookup curr char on first round */
86114 			if (DUK__ISDIGIT(x)) {
86115 				/* Note: intentionally allow leading zeroes here, as the
86116 				 * actual parser will check for them.
86117 				 */
86118 				if (state == 0 && legacy_oct && (x == DUK_ASC_8 || x == DUK_ASC_9)) {
86119 					/* Started out as an octal-lookalike
86120 					 * but interpreted as decimal, e.g.
86121 					 * '0779' -> 779.  This also means
86122 					 * that fractions are allowed, e.g.
86123 					 * '0779.123' is allowed but '0777.123'
86124 					 * is not!
86125 					 */
86126 					s2n_radix = 10;
86127 				}
86128 				if (state == 2) {
86129 					state = 3;
86130 				}
86131 			} else if (s2n_radix == 16 && DUK__ISHEXDIGIT(x)) {
86132 				/* Note: 'e' and 'E' are also accepted here. */
86133 				;
86134 			} else if (x == DUK_ASC_PERIOD) {
86135 				if (state >= 1 || s2n_radix != 10) {
86136 					break;
86137 				} else {
86138 					state = 1;
86139 				}
86140 			} else if (x == DUK_ASC_LC_E || x == DUK_ASC_UC_E) {
86141 				if (state >= 2 || s2n_radix != 10) {
86142 					break;
86143 				} else {
86144 					state = 2;
86145 				}
86146 			} else if (x == DUK_ASC_MINUS || x == DUK_ASC_PLUS) {
86147 				if (state != 2) {
86148 					break;
86149 				} else {
86150 					state = 3;
86151 				}
86152 			} else {
86153 				break;
86154 			}
86155 			DUK__APPENDBUFFER(lex_ctx, x);
86156 			DUK__ADVANCECHARS(lex_ctx, 1);
86157 		}
86158 
86159 		/* XXX: better coercion */
86160 		(void) duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
86161 
86162 		if (s2n_radix != 10) {
86163 			/* For bases other than 10, integer only. */
86164 			s2n_flags = DUK_S2N_FLAG_ALLOW_LEADING_ZERO;
86165 		} else {
86166 			s2n_flags = DUK_S2N_FLAG_ALLOW_EXP |
86167 			            DUK_S2N_FLAG_ALLOW_FRAC |
86168 			            DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
86169 			            DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
86170 			            DUK_S2N_FLAG_ALLOW_LEADING_ZERO;
86171 		}
86172 
86173 		duk_dup(lex_ctx->thr, lex_ctx->slot1_idx);
86174 		duk_numconv_parse(lex_ctx->thr, s2n_radix, s2n_flags);
86175 		val = duk_to_number_m1(lex_ctx->thr);
86176 		if (DUK_ISNAN(val)) {
86177 			goto fail_number_literal;
86178 		}
86179 		duk_replace(lex_ctx->thr, lex_ctx->slot1_idx);  /* could also just pop? */
86180 
86181 		DUK__INITBUFFER(lex_ctx);  /* free some memory */
86182 
86183 		/* Section 7.8.3 (note): NumericLiteral must be followed by something other than
86184 		 * IdentifierStart or DecimalDigit.
86185 		 */
86186 
86187 		if (DUK__ISDIGIT(DUK__L0()) || duk_unicode_is_identifier_start(DUK__L0())) {
86188 			goto fail_number_literal;
86189 		}
86190 
86191 		out_token->num = val;
86192 		advtok = DUK__ADVTOK(0, DUK_TOK_NUMBER);
86193 	} else if (duk_unicode_is_whitespace(DUK__LOOKUP(lex_ctx, 0))) {
86194 		DUK__ADVANCECHARS(lex_ctx, 1);
86195 		goto restart;
86196 	} else if (x < 0) {
86197 		advtok = DUK__ADVTOK(0, DUK_TOK_EOF);
86198 	} else {
86199 		goto fail_token;
86200 	}
86201  skip_slow_path:
86202 
86203 	/*
86204 	 *  Shared exit path
86205 	 */
86206 
86207 	DUK__ADVANCEBYTES(lex_ctx, advtok >> 8);
86208 	out_token->t = advtok & 0xff;
86209 	if (out_token->t_nores == DUK_TOK_INVALID) {
86210 		out_token->t_nores = out_token->t;
86211 	}
86212 	out_token->lineterm = got_lineterm;
86213 
86214 	/* Automatic semicolon insertion is allowed if a token is preceded
86215 	 * by line terminator(s), or terminates a statement list (right curly
86216 	 * or EOF).
86217 	 */
86218 	if (got_lineterm || out_token->t == DUK_TOK_RCURLY || out_token->t == DUK_TOK_EOF) {
86219 		out_token->allow_auto_semi = 1;
86220 	} else {
86221 		out_token->allow_auto_semi = 0;
86222 	}
86223 
86224 	return;
86225 
86226  fail_token_limit:
86227 	DUK_ERROR_RANGE(lex_ctx->thr, DUK_STR_TOKEN_LIMIT);
86228 	DUK_WO_NORETURN(return;);
86229 
86230  fail_token:
86231 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_TOKEN);
86232 	DUK_WO_NORETURN(return;);
86233 
86234  fail_number_literal:
86235 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_NUMBER_LITERAL);
86236 	DUK_WO_NORETURN(return;);
86237 
86238  fail_escape:
86239 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE);
86240 	DUK_WO_NORETURN(return;);
86241 
86242  fail_unterm_regexp:
86243 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_REGEXP);
86244 	DUK_WO_NORETURN(return;);
86245 
86246  fail_unterm_comment:
86247 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_COMMENT);
86248 	DUK_WO_NORETURN(return;);
86249 
86250 #if !defined(DUK_USE_REGEXP_SUPPORT)
86251  fail_regexp_support:
86252 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_REGEXP_SUPPORT_DISABLED);
86253 	DUK_WO_NORETURN(return;);
86254 #endif
86255 }
86256 
86257 #if defined(DUK_USE_REGEXP_SUPPORT)
86258 
86259 /*
86260  *  Parse a RegExp token.  The grammar is described in E5 Section 15.10.
86261  *  Terminal constructions (such as quantifiers) are parsed directly here.
86262  *
86263  *  0xffffffffU is used as a marker for "infinity" in quantifiers.  Further,
86264  *  DUK__MAX_RE_QUANT_DIGITS limits the maximum number of digits that
86265  *  will be accepted for a quantifier.
86266  */
86267 
86268 DUK_INTERNAL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token) {
86269 	duk_small_uint_t advtok = 0;  /* init is unnecessary but suppresses "may be used uninitialized" warnings */
86270 	duk_codepoint_t x, y;
86271 
86272 	if (++lex_ctx->token_count >= lex_ctx->token_limit) {
86273 		goto fail_token_limit;
86274 	}
86275 
86276 	duk_memzero(out_token, sizeof(*out_token));
86277 
86278 	x = DUK__L0();
86279 	y = DUK__L1();
86280 
86281 	DUK_DDD(DUK_DDDPRINT("parsing regexp token, L0=%ld, L1=%ld", (long) x, (long) y));
86282 
86283 	switch (x) {
86284 	case DUK_ASC_PIPE: {
86285 		advtok = DUK__ADVTOK(1, DUK_RETOK_DISJUNCTION);
86286 		break;
86287 	}
86288 	case DUK_ASC_CARET: {
86289 		advtok = DUK__ADVTOK(1, DUK_RETOK_ASSERT_START);
86290 		break;
86291 	}
86292 	case DUK_ASC_DOLLAR: {
86293 		advtok = DUK__ADVTOK(1, DUK_RETOK_ASSERT_END);
86294 		break;
86295 	}
86296 	case DUK_ASC_QUESTION: {
86297 		out_token->qmin = 0;
86298 		out_token->qmax = 1;
86299 		if (y == DUK_ASC_QUESTION) {
86300 			advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
86301 			out_token->greedy = 0;
86302 		} else {
86303 			advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
86304 			out_token->greedy = 1;
86305 		}
86306 		break;
86307 	}
86308 	case DUK_ASC_STAR: {
86309 		out_token->qmin = 0;
86310 		out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
86311 		if (y == DUK_ASC_QUESTION) {
86312 			advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
86313 			out_token->greedy = 0;
86314 		} else {
86315 			advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
86316 			out_token->greedy = 1;
86317 		}
86318 		break;
86319 	}
86320 	case DUK_ASC_PLUS: {
86321 		out_token->qmin = 1;
86322 		out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
86323 		if (y == DUK_ASC_QUESTION) {
86324 			advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
86325 			out_token->greedy = 0;
86326 		} else {
86327 			advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
86328 			out_token->greedy = 1;
86329 		}
86330 		break;
86331 	}
86332 	case DUK_ASC_LCURLY: {
86333 		/* Production allows 'DecimalDigits', including leading zeroes */
86334 		duk_uint32_t val1 = 0;
86335 		duk_uint32_t val2 = DUK_RE_QUANTIFIER_INFINITE;
86336 		duk_small_int_t digits = 0;
86337 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
86338 		duk_lexer_point lex_pt;
86339 #endif
86340 
86341 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
86342 		/* Store lexer position, restoring if quantifier is invalid. */
86343 		DUK_LEXER_GETPOINT(lex_ctx, &lex_pt);
86344 #endif
86345 
86346 		for (;;) {
86347 			DUK__ADVANCECHARS(lex_ctx, 1);  /* eat '{' on entry */
86348 			x = DUK__L0();
86349 			if (DUK__ISDIGIT(x)) {
86350 				digits++;
86351 				val1 = val1 * 10 + (duk_uint32_t) duk__hexval(x);
86352 			} else if (x == DUK_ASC_COMMA) {
86353 				if (digits > DUK__MAX_RE_QUANT_DIGITS) {
86354 					goto invalid_quantifier;
86355 				}
86356 				if (val2 != DUK_RE_QUANTIFIER_INFINITE) {
86357 					goto invalid_quantifier;
86358 				}
86359 				if (DUK__L1() == DUK_ASC_RCURLY) {
86360 					/* form: { DecimalDigits , }, val1 = min count */
86361 					if (digits == 0) {
86362 						goto invalid_quantifier;
86363 					}
86364 					out_token->qmin = val1;
86365 					out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
86366 					DUK__ADVANCECHARS(lex_ctx, 2);
86367 					break;
86368 				}
86369 				val2 = val1;
86370 				val1 = 0;
86371 				digits = 0;  /* not strictly necessary because of lookahead '}' above */
86372 			} else if (x == DUK_ASC_RCURLY) {
86373 				if (digits > DUK__MAX_RE_QUANT_DIGITS) {
86374 					goto invalid_quantifier;
86375 				}
86376 				if (digits == 0) {
86377 					goto invalid_quantifier;
86378 				}
86379 				if (val2 != DUK_RE_QUANTIFIER_INFINITE) {
86380 					/* val2 = min count, val1 = max count */
86381 					out_token->qmin = val2;
86382 					out_token->qmax = val1;
86383 				} else {
86384 					/* val1 = count */
86385 					out_token->qmin = val1;
86386 					out_token->qmax = val1;
86387 				}
86388 				DUK__ADVANCECHARS(lex_ctx, 1);
86389 				break;
86390 			} else {
86391 				goto invalid_quantifier;
86392 			}
86393 		}
86394 		if (DUK__L0() == DUK_ASC_QUESTION) {
86395 			out_token->greedy = 0;
86396 			DUK__ADVANCECHARS(lex_ctx, 1);
86397 		} else {
86398 			out_token->greedy = 1;
86399 		}
86400 		advtok = DUK__ADVTOK(0, DUK_RETOK_QUANTIFIER);
86401 		break;
86402  invalid_quantifier:
86403 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
86404 		/* Failed to match the quantifier, restore lexer and parse
86405 		 * opening brace as a literal.
86406 		 */
86407 		DUK_LEXER_SETPOINT(lex_ctx, &lex_pt);
86408 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_CHAR);
86409 		out_token->num = DUK_ASC_LCURLY;
86410 #else
86411 		goto fail_quantifier;
86412 #endif
86413 		break;
86414 	}
86415 	case DUK_ASC_PERIOD: {
86416 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_PERIOD);
86417 		break;
86418 	}
86419 	case DUK_ASC_BACKSLASH: {
86420 		/* The E5.1 specification does not seem to allow IdentifierPart characters
86421 		 * to be used as identity escapes.  Unfortunately this includes '$', which
86422 		 * cannot be escaped as '\$'; it needs to be escaped e.g. as '\u0024'.
86423 		 * Many other implementations (including V8 and Rhino, for instance) do
86424 		 * accept '\$' as a valid identity escape, which is quite pragmatic, and
86425 		 * ES2015 Annex B relaxes the rules to allow these (and other) real world forms.
86426 		 */
86427 
86428 		advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR);  /* default: char escape (two chars) */
86429 		if (y == DUK_ASC_LC_B) {
86430 			advtok = DUK__ADVTOK(2, DUK_RETOK_ASSERT_WORD_BOUNDARY);
86431 		} else if (y == DUK_ASC_UC_B) {
86432 			advtok = DUK__ADVTOK(2, DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY);
86433 		} else if (y == DUK_ASC_LC_F) {
86434 			out_token->num = 0x000c;
86435 		} else if (y == DUK_ASC_LC_N) {
86436 			out_token->num = 0x000a;
86437 		} else if (y == DUK_ASC_LC_T) {
86438 			out_token->num = 0x0009;
86439 		} else if (y == DUK_ASC_LC_R) {
86440 			out_token->num = 0x000d;
86441 		} else if (y == DUK_ASC_LC_V) {
86442 			out_token->num = 0x000b;
86443 		} else if (y == DUK_ASC_LC_C) {
86444 			x = DUK__L2();
86445 			if ((x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_Z) ||
86446 			    (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_Z)) {
86447 				out_token->num = (duk_uint32_t) (x % 32);
86448 				advtok = DUK__ADVTOK(3, DUK_RETOK_ATOM_CHAR);
86449 			} else {
86450 				goto fail_escape;
86451 			}
86452 		} else if (y == DUK_ASC_LC_X || y == DUK_ASC_LC_U) {
86453 			/* The token value is the Unicode codepoint without
86454 			 * it being decode into surrogate pair characters
86455 			 * here.  The \u{H+} is only allowed in Unicode mode
86456 			 * which we don't support yet.
86457 			 */
86458 			out_token->num = (duk_uint32_t) duk__lexer_parse_escape(lex_ctx, 0 /*allow_es6*/);
86459 			advtok = DUK__ADVTOK(0, DUK_RETOK_ATOM_CHAR);
86460 		} else if (y == DUK_ASC_LC_D) {
86461 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_DIGIT);
86462 		} else if (y == DUK_ASC_UC_D) {
86463 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_NOT_DIGIT);
86464 		} else if (y == DUK_ASC_LC_S) {
86465 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_WHITE);
86466 		} else if (y == DUK_ASC_UC_S) {
86467 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_NOT_WHITE);
86468 		} else if (y == DUK_ASC_LC_W) {
86469 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_WORD_CHAR);
86470 		} else if (y == DUK_ASC_UC_W) {
86471 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_NOT_WORD_CHAR);
86472 		} else if (DUK__ISDIGIT(y)) {
86473 			/* E5 Section 15.10.2.11 */
86474 			if (y == DUK_ASC_0) {
86475 				if (DUK__ISDIGIT(DUK__L2())) {
86476 					goto fail_escape;
86477 				}
86478 				out_token->num = 0x0000;
86479 				advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR);
86480 			} else {
86481 				/* XXX: shared parsing? */
86482 				duk_uint32_t val = 0;
86483 				duk_small_int_t i;
86484 				for (i = 0; ; i++) {
86485 					if (i >= DUK__MAX_RE_DECESC_DIGITS) {
86486 						goto fail_escape;
86487 					}
86488 					DUK__ADVANCECHARS(lex_ctx, 1);  /* eat backslash on entry */
86489 					x = DUK__L0();
86490 					if (!DUK__ISDIGIT(x)) {
86491 						break;
86492 					}
86493 					val = val * 10 + (duk_uint32_t) duk__hexval(x);
86494 				}
86495 				/* DUK__L0() cannot be a digit, because the loop doesn't terminate if it is */
86496 				advtok = DUK__ADVTOK(0, DUK_RETOK_ATOM_BACKREFERENCE);
86497 				out_token->num = val;
86498 			}
86499 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
86500 		} else if (y >= 0) {
86501 			/* For ES2015 Annex B, accept any source character as identity
86502 			 * escape except 'c' which is used for control characters.
86503 			 * http://www.ecma-international.org/ecma-262/6.0/#sec-regular-expressions-patterns
86504 			 * Careful not to match end-of-buffer (<0) here.
86505 			 * This is not yet full ES2015 Annex B because cases above
86506 			 * (like hex escape) won't backtrack.
86507 			 */
86508 			DUK_ASSERT(y != DUK_ASC_LC_C);  /* covered above */
86509 #else  /* DUK_USE_ES6_REGEXP_SYNTAX */
86510 		} else if ((y >= 0 && !duk_unicode_is_identifier_part(y)) ||
86511 		           y == DUK_UNICODE_CP_ZWNJ ||
86512 		           y == DUK_UNICODE_CP_ZWJ) {
86513 			/* For ES5.1 identity escapes are not allowed for identifier
86514 			 * parts.  This conflicts with a lot of real world code as this
86515 			 * doesn't e.g. allow escaping a dollar sign as /\$/, see
86516 			 * test-regexp-identity-escape-dollar.js.
86517 			 */
86518 #endif  /* DUK_USE_ES6_REGEXP_SYNTAX */
86519 			out_token->num = (duk_uint32_t) y;
86520 		} else {
86521 			goto fail_escape;
86522 		}
86523 		break;
86524 	}
86525 	case DUK_ASC_LPAREN: {
86526 		/* XXX: naming is inconsistent: ATOM_END_GROUP ends an ASSERT_START_LOOKAHEAD */
86527 
86528 		if (y == DUK_ASC_QUESTION) {
86529 			if (DUK__L2() == DUK_ASC_EQUALS) {
86530 				/* (?= */
86531 				advtok = DUK__ADVTOK(3, DUK_RETOK_ASSERT_START_POS_LOOKAHEAD);
86532 			} else if (DUK__L2() == DUK_ASC_EXCLAMATION) {
86533 				/* (?! */
86534 				advtok = DUK__ADVTOK(3, DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD);
86535 			} else if (DUK__L2() == DUK_ASC_COLON) {
86536 				/* (?: */
86537 				advtok = DUK__ADVTOK(3, DUK_RETOK_ATOM_START_NONCAPTURE_GROUP);
86538 			} else {
86539 				goto fail_group;
86540 			}
86541 		} else {
86542 			/* ( */
86543 			advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_START_CAPTURE_GROUP);
86544 		}
86545 		break;
86546 	}
86547 	case DUK_ASC_RPAREN: {
86548 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_END_GROUP);
86549 		break;
86550 	}
86551 	case DUK_ASC_LBRACKET: {
86552 		/*
86553 		 *  To avoid creating a heavy intermediate value for the list of ranges,
86554 		 *  only the start token ('[' or '[^') is parsed here.  The regexp
86555 		 *  compiler parses the ranges itself.
86556 		 */
86557 
86558 		/* XXX: with DUK_USE_ES6_REGEXP_SYNTAX we should allow left bracket
86559 		 * literal too, but it's not easy to parse without backtracking.
86560 		 */
86561 
86562 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_START_CHARCLASS);
86563 		if (y == DUK_ASC_CARET) {
86564 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_START_CHARCLASS_INVERTED);
86565 		}
86566 		break;
86567 	}
86568 #if !defined(DUK_USE_ES6_REGEXP_SYNTAX)
86569 	case DUK_ASC_RCURLY:
86570 	case DUK_ASC_RBRACKET: {
86571 		/* Although these could be parsed as PatternCharacters unambiguously (here),
86572 		 * E5 Section 15.10.1 grammar explicitly forbids these as PatternCharacters.
86573 		 */
86574 		goto fail_invalid_char;
86575 		break;
86576 	}
86577 #endif
86578 	case -1: {
86579 		/* EOF */
86580 		advtok = DUK__ADVTOK(0, DUK_TOK_EOF);
86581 		break;
86582 	}
86583 	default: {
86584 		/* PatternCharacter, all excluded characters are matched by cases above */
86585 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_CHAR);
86586 		out_token->num = (duk_uint32_t) x;
86587 		break;
86588 	}
86589 	}
86590 
86591 	/*
86592 	 *  Shared exit path
86593 	 */
86594 
86595 	DUK__ADVANCEBYTES(lex_ctx, advtok >> 8);
86596 	out_token->t = advtok & 0xff;
86597 	return;
86598 
86599  fail_token_limit:
86600 	DUK_ERROR_RANGE(lex_ctx->thr, DUK_STR_TOKEN_LIMIT);
86601 	DUK_WO_NORETURN(return;);
86602 
86603  fail_escape:
86604 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_ESCAPE);
86605 	DUK_WO_NORETURN(return;);
86606 
86607  fail_group:
86608 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_GROUP);
86609 	DUK_WO_NORETURN(return;);
86610 
86611 #if !defined(DUK_USE_ES6_REGEXP_SYNTAX)
86612  fail_invalid_char:
86613 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_CHARACTER);
86614 	DUK_WO_NORETURN(return;);
86615 
86616  fail_quantifier:
86617 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_QUANTIFIER);
86618 	DUK_WO_NORETURN(return;);
86619 #endif
86620 }
86621 
86622 /*
86623  *  Special parser for character classes; calls callback for every
86624  *  range parsed and returns the number of ranges present.
86625  */
86626 
86627 /* XXX: this duplicates functionality in duk_regexp.c where a similar loop is
86628  * required anyway.  We could use that BUT we need to update the regexp compiler
86629  * 'nranges' too.  Work this out a bit more cleanly to save space.
86630  */
86631 
86632 /* XXX: the handling of character range detection is a bit convoluted.
86633  * Try to simplify and make smaller.
86634  */
86635 
86636 /* XXX: logic for handling character ranges is now incorrect, it will accept
86637  * e.g. [\d-z] whereas it should croak from it?  SMJS accepts this too, though.
86638  *
86639  * Needs a read through and a lot of additional tests.
86640  */
86641 
86642 DUK_LOCAL
86643 void duk__emit_u16_direct_ranges(duk_lexer_ctx *lex_ctx,
86644                                  duk_re_range_callback gen_range,
86645                                  void *userdata,
86646                                  const duk_uint16_t *ranges,
86647                                  duk_small_int_t num) {
86648 	const duk_uint16_t *ranges_end;
86649 
86650 	DUK_UNREF(lex_ctx);
86651 
86652 	ranges_end = ranges + num;
86653 	while (ranges < ranges_end) {
86654 		/* mark range 'direct', bypass canonicalization (see Wiki) */
86655 		gen_range(userdata, (duk_codepoint_t) ranges[0], (duk_codepoint_t) ranges[1], 1);
86656 		ranges += 2;
86657 	}
86658 }
86659 
86660 DUK_INTERNAL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata) {
86661 	duk_codepoint_t start = -1;
86662 	duk_codepoint_t ch;
86663 	duk_codepoint_t x;
86664 	duk_bool_t dash = 0;
86665 	duk_small_uint_t adv = 0;
86666 
86667 	DUK_DD(DUK_DDPRINT("parsing regexp ranges"));
86668 
86669 	for (;;) {
86670 		DUK__ADVANCECHARS(lex_ctx, adv);
86671 		adv = 1;
86672 
86673 		x = DUK__L0();
86674 
86675 		ch = -1;  /* not strictly necessary, but avoids "uninitialized variable" warnings */
86676 		DUK_UNREF(ch);
86677 
86678 		if (x < 0) {
86679 			goto fail_unterm_charclass;
86680 		} else if (x == DUK_ASC_RBRACKET) {
86681 			if (start >= 0) {
86682 				gen_range(userdata, start, start, 0);
86683 			}
86684 			DUK__ADVANCECHARS(lex_ctx, 1);  /* eat ']' before finishing */
86685 			break;
86686 		} else if (x == DUK_ASC_MINUS) {
86687 			if (start >= 0 && !dash && DUK__L1() != DUK_ASC_RBRACKET) {
86688 				/* '-' as a range indicator */
86689 				dash = 1;
86690 				continue;
86691 			} else {
86692 				/* '-' verbatim */
86693 				ch = x;
86694 			}
86695 		} else if (x == DUK_ASC_BACKSLASH) {
86696 			/*
86697 			 *  The escapes are same as outside a character class, except that \b has a
86698 			 *  different meaning, and \B and backreferences are prohibited (see E5
86699 			 *  Section 15.10.2.19).  However, it's difficult to share code because we
86700 			 *  handle e.g. "\n" very differently: here we generate a single character
86701 			 *  range for it.
86702 			 */
86703 
86704 			/* XXX: ES2015 surrogate pair handling. */
86705 
86706 			x = DUK__L1();
86707 
86708 			adv = 2;
86709 
86710 			if (x == DUK_ASC_LC_B) {
86711 				/* Note: '\b' in char class is different than outside (assertion),
86712 				 * '\B' is not allowed and is caught by the duk_unicode_is_identifier_part()
86713 				 * check below.
86714 				 */
86715 				ch = 0x0008;
86716 			} else if (x == DUK_ASC_LC_F) {
86717 				ch = 0x000c;
86718 			} else if (x == DUK_ASC_LC_N) {
86719 				ch = 0x000a;
86720 			} else if (x == DUK_ASC_LC_T) {
86721 				ch = 0x0009;
86722 			} else if (x == DUK_ASC_LC_R) {
86723 				ch = 0x000d;
86724 			} else if (x == DUK_ASC_LC_V) {
86725 				ch = 0x000b;
86726 			} else if (x == DUK_ASC_LC_C) {
86727 				x = DUK__L2();
86728 				adv = 3;
86729 				if ((x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_Z) ||
86730 				    (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_Z)) {
86731 					ch = (x % 32);
86732 				} else {
86733 					goto fail_escape;
86734 				}
86735 			} else if (x == DUK_ASC_LC_X || x == DUK_ASC_LC_U) {
86736 				/* The \u{H+} form is only allowed in Unicode mode which
86737 				 * we don't support yet.
86738 				 */
86739 				ch = duk__lexer_parse_escape(lex_ctx, 0 /*allow_es6*/);
86740 				adv = 0;
86741 			} else if (x == DUK_ASC_LC_D) {
86742 				duk__emit_u16_direct_ranges(lex_ctx,
86743 				                            gen_range,
86744 				                            userdata,
86745 				                            duk_unicode_re_ranges_digit,
86746 				                            sizeof(duk_unicode_re_ranges_digit) / sizeof(duk_uint16_t));
86747 				ch = -1;
86748 			} else if (x == DUK_ASC_UC_D) {
86749 				duk__emit_u16_direct_ranges(lex_ctx,
86750 				                            gen_range,
86751 				                            userdata,
86752 				                            duk_unicode_re_ranges_not_digit,
86753 				                            sizeof(duk_unicode_re_ranges_not_digit) / sizeof(duk_uint16_t));
86754 				ch = -1;
86755 			} else if (x == DUK_ASC_LC_S) {
86756 				duk__emit_u16_direct_ranges(lex_ctx,
86757 				                            gen_range,
86758 				                            userdata,
86759 				                            duk_unicode_re_ranges_white,
86760 				                            sizeof(duk_unicode_re_ranges_white) / sizeof(duk_uint16_t));
86761 				ch = -1;
86762 			} else if (x == DUK_ASC_UC_S) {
86763 				duk__emit_u16_direct_ranges(lex_ctx,
86764 				                            gen_range,
86765 				                            userdata,
86766 				                            duk_unicode_re_ranges_not_white,
86767 				                            sizeof(duk_unicode_re_ranges_not_white) / sizeof(duk_uint16_t));
86768 				ch = -1;
86769 			} else if (x == DUK_ASC_LC_W) {
86770 				duk__emit_u16_direct_ranges(lex_ctx,
86771 				                            gen_range,
86772 				                            userdata,
86773 				                            duk_unicode_re_ranges_wordchar,
86774 				                            sizeof(duk_unicode_re_ranges_wordchar) / sizeof(duk_uint16_t));
86775 				ch = -1;
86776 			} else if (x == DUK_ASC_UC_W) {
86777 				duk__emit_u16_direct_ranges(lex_ctx,
86778 				                            gen_range,
86779 				                            userdata,
86780 				                            duk_unicode_re_ranges_not_wordchar,
86781 				                            sizeof(duk_unicode_re_ranges_not_wordchar) / sizeof(duk_uint16_t));
86782 				ch = -1;
86783 			} else if (DUK__ISDIGIT(x)) {
86784 				/* DecimalEscape, only \0 is allowed, no leading
86785 				 * zeroes are allowed.
86786 				 *
86787 				 * ES2015 Annex B also allows (maximal match) legacy
86788 				 * octal escapes up to \377 and \8 and \9 are
86789 				 * accepted as literal '8' and '9', also in strict mode.
86790 				 */
86791 
86792 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
86793 				ch = duk__lexer_parse_legacy_octal(lex_ctx, &adv, 0 /*reject_annex_b*/);
86794 				DUK_ASSERT(ch >= 0);  /* no rejections */
86795 #else
86796 				if (x == DUK_ASC_0 && !DUK__ISDIGIT(DUK__L2())) {
86797 					ch = 0x0000;
86798 				} else {
86799 					goto fail_escape;
86800 				}
86801 #endif
86802 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
86803 			} else if (x >= 0) {
86804 				/* IdentityEscape: ES2015 Annex B allows almost all
86805 				 * source characters here.  Match anything except
86806 				 * EOF here.
86807 				 */
86808 				ch = x;
86809 #else  /* DUK_USE_ES6_REGEXP_SYNTAX */
86810 			} else if (!duk_unicode_is_identifier_part(x)) {
86811 				/* IdentityEscape: ES5.1 doesn't allow identity escape
86812 				 * for identifier part characters, which conflicts with
86813 				 * some real world code.  For example, it doesn't allow
86814 				 * /[\$]/ which is awkward.
86815 				 */
86816 				ch = x;
86817 #endif  /* DUK_USE_ES6_REGEXP_SYNTAX */
86818 			} else {
86819 				goto fail_escape;
86820 			}
86821 		} else {
86822 			/* character represents itself */
86823 			ch = x;
86824 		}
86825 
86826 		/* ch is a literal character here or -1 if parsed entity was
86827 		 * an escape such as "\s".
86828 		 */
86829 
86830 		if (ch < 0) {
86831 			/* multi-character sets not allowed as part of ranges, see
86832 			 * E5 Section 15.10.2.15, abstract operation CharacterRange.
86833 			 */
86834 			if (start >= 0) {
86835 				if (dash) {
86836 					goto fail_range;
86837 				} else {
86838 					gen_range(userdata, start, start, 0);
86839 					start = -1;
86840 					/* dash is already 0 */
86841 				}
86842 			}
86843 		} else {
86844 			if (start >= 0) {
86845 				if (dash) {
86846 					if (start > ch) {
86847 						goto fail_range;
86848 					}
86849 					gen_range(userdata, start, ch, 0);
86850 					start = -1;
86851 					dash = 0;
86852 				} else {
86853 					gen_range(userdata, start, start, 0);
86854 					start = ch;
86855 					/* dash is already 0 */
86856 				}
86857 			} else {
86858 				start = ch;
86859 			}
86860 		}
86861 	}
86862 
86863 	return;
86864 
86865  fail_escape:
86866 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_ESCAPE);
86867 	DUK_WO_NORETURN(return;);
86868 
86869  fail_range:
86870 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_RANGE);
86871 	DUK_WO_NORETURN(return;);
86872 
86873  fail_unterm_charclass:
86874 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_CHARCLASS);
86875 	DUK_WO_NORETURN(return;);
86876 }
86877 
86878 #endif  /* DUK_USE_REGEXP_SUPPORT */
86879 
86880 /* automatic undefs */
86881 #undef DUK__ADVANCEBYTES
86882 #undef DUK__ADVANCECHARS
86883 #undef DUK__ADVTOK
86884 #undef DUK__APPENDBUFFER
86885 #undef DUK__APPENDBUFFER_ASCII
86886 #undef DUK__INITBUFFER
86887 #undef DUK__ISDIGIT
86888 #undef DUK__ISDIGIT03
86889 #undef DUK__ISDIGIT47
86890 #undef DUK__ISHEXDIGIT
86891 #undef DUK__ISOCTDIGIT
86892 #undef DUK__L0
86893 #undef DUK__L1
86894 #undef DUK__L2
86895 #undef DUK__L3
86896 #undef DUK__L4
86897 #undef DUK__L5
86898 #undef DUK__LOOKUP
86899 #undef DUK__MAX_RE_DECESC_DIGITS
86900 #undef DUK__MAX_RE_QUANT_DIGITS
86901 /*
86902  *  Number-to-string and string-to-number conversions.
86903  *
86904  *  Slow path number-to-string and string-to-number conversion is based on
86905  *  a Dragon4 variant, with fast paths for small integers.  Big integer
86906  *  arithmetic is needed for guaranteeing that the conversion is correct
86907  *  and uses a minimum number of digits.  The big number arithmetic has a
86908  *  fixed maximum size and does not require dynamic allocations.
86909  *
86910  *  See: doc/number-conversion.rst.
86911  */
86912 
86913 /* #include duk_internal.h -> already included */
86914 
86915 #define DUK__IEEE_DOUBLE_EXP_BIAS  1023
86916 #define DUK__IEEE_DOUBLE_EXP_MIN   (-1022)   /* biased exp == 0 -> denormal, exp -1022 */
86917 
86918 #define DUK__DIGITCHAR(x)  duk_lc_digits[(x)]
86919 
86920 /*
86921  *  Tables generated with util/gennumdigits.py.
86922  *
86923  *  duk__str2num_digits_for_radix indicates, for each radix, how many input
86924  *  digits should be considered significant for string-to-number conversion.
86925  *  The input is also padded to this many digits to give the Dragon4
86926  *  conversion enough (apparent) precision to work with.
86927  *
86928  *  duk__str2num_exp_limits indicates, for each radix, the radix-specific
86929  *  minimum/maximum exponent values (for a Dragon4 integer mantissa)
86930  *  below and above which the number is guaranteed to underflow to zero
86931  *  or overflow to Infinity.  This allows parsing to keep bigint values
86932  *  bounded.
86933  */
86934 
86935 DUK_LOCAL const duk_uint8_t duk__str2num_digits_for_radix[] = {
86936 	69, 44, 35, 30, 27, 25, 23, 22, 20, 20,    /* 2 to 11 */
86937 	20, 19, 19, 18, 18, 17, 17, 17, 16, 16,    /* 12 to 21 */
86938 	16, 16, 16, 15, 15, 15, 15, 15, 15, 14,    /* 22 to 31 */
86939 	14, 14, 14, 14, 14                         /* 31 to 36 */
86940 };
86941 
86942 typedef struct {
86943 	duk_int16_t upper;
86944 	duk_int16_t lower;
86945 } duk__exp_limits;
86946 
86947 DUK_LOCAL const duk__exp_limits duk__str2num_exp_limits[] = {
86948 	{ 957, -1147 }, { 605, -725 },  { 479, -575 },  { 414, -496 },
86949 	{ 372, -446 },  { 342, -411 },  { 321, -384 },  { 304, -364 },
86950 	{ 291, -346 },  { 279, -334 },  { 268, -323 },  { 260, -312 },
86951 	{ 252, -304 },  { 247, -296 },  { 240, -289 },  { 236, -283 },
86952 	{ 231, -278 },  { 227, -273 },  { 223, -267 },  { 220, -263 },
86953 	{ 216, -260 },  { 213, -256 },  { 210, -253 },  { 208, -249 },
86954 	{ 205, -246 },  { 203, -244 },  { 201, -241 },  { 198, -239 },
86955 	{ 196, -237 },  { 195, -234 },  { 193, -232 },  { 191, -230 },
86956 	{ 190, -228 },  { 188, -226 },  { 187, -225 },
86957 };
86958 
86959 /*
86960  *  Limited functionality bigint implementation.
86961  *
86962  *  Restricted to non-negative numbers with less than 32 * DUK__BI_MAX_PARTS bits,
86963  *  with the caller responsible for ensuring this is never exceeded.  No memory
86964  *  allocation (except stack) is needed for bigint computation.  Operations
86965  *  have been tailored for number conversion needs.
86966  *
86967  *  Argument order is "assignment order", i.e. target first, then arguments:
86968  *  x <- y * z  -->  duk__bi_mul(x, y, z);
86969  */
86970 
86971 /* This upper value has been experimentally determined; debug build will check
86972  * bigint size with assertions.
86973  */
86974 #define DUK__BI_MAX_PARTS  37  /* 37x32 = 1184 bits */
86975 
86976 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
86977 #define DUK__BI_PRINT(name,x)  duk__bi_print((name),(x))
86978 #else
86979 #define DUK__BI_PRINT(name,x)
86980 #endif
86981 
86982 /* Current size is about 152 bytes. */
86983 typedef struct {
86984 	duk_small_int_t n;
86985 	duk_uint32_t v[DUK__BI_MAX_PARTS];  /* low to high */
86986 } duk__bigint;
86987 
86988 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
86989 DUK_LOCAL void duk__bi_print(const char *name, duk__bigint *x) {
86990 	/* Overestimate required size; debug code so not critical to be tight. */
86991 	char buf[DUK__BI_MAX_PARTS * 9 + 64];
86992 	char *p = buf;
86993 	duk_small_int_t i;
86994 
86995 	/* No NUL term checks in this debug code. */
86996 	p += DUK_SPRINTF(p, "%p n=%ld", (void *) x, (long) x->n);
86997 	if (x->n == 0) {
86998 		p += DUK_SPRINTF(p, " 0");
86999 	}
87000 	for (i = x->n - 1; i >= 0; i--) {
87001 		p += DUK_SPRINTF(p, " %08lx", (unsigned long) x->v[i]);
87002 	}
87003 
87004 	DUK_DDD(DUK_DDDPRINT("%s: %s", (const char *) name, (const char *) buf));
87005 }
87006 #endif
87007 
87008 #if defined(DUK_USE_ASSERTIONS)
87009 DUK_LOCAL duk_small_int_t duk__bi_is_valid(duk__bigint *x) {
87010 	return (duk_small_int_t)
87011 	       ( ((x->n >= 0) && (x->n <= DUK__BI_MAX_PARTS)) /* is valid size */ &&
87012 	         ((x->n == 0) || (x->v[x->n - 1] != 0)) /* is normalized */ );
87013 }
87014 #endif
87015 
87016 DUK_LOCAL void duk__bi_normalize(duk__bigint *x) {
87017 	duk_small_int_t i;
87018 
87019 	for (i = x->n - 1; i >= 0; i--) {
87020 		if (x->v[i] != 0) {
87021 			break;
87022 		}
87023 	}
87024 
87025 	/* Note: if 'x' is zero, x->n becomes 0 here */
87026 	x->n = i + 1;
87027 	DUK_ASSERT(duk__bi_is_valid(x));
87028 }
87029 
87030 /* x <- y */
87031 DUK_LOCAL void duk__bi_copy(duk__bigint *x, duk__bigint *y) {
87032 	duk_small_int_t n;
87033 
87034 	n = y->n;
87035 	x->n = n;
87036 	/* No need to special case n == 0. */
87037 	duk_memcpy((void *) x->v, (const void *) y->v, (size_t) (sizeof(duk_uint32_t) * (size_t) n));
87038 }
87039 
87040 DUK_LOCAL void duk__bi_set_small(duk__bigint *x, duk_uint32_t v) {
87041 	if (v == 0U) {
87042 		x->n = 0;
87043 	} else {
87044 		x->n = 1;
87045 		x->v[0] = v;
87046 	}
87047 	DUK_ASSERT(duk__bi_is_valid(x));
87048 }
87049 
87050 /* Return value: <0  <=>  x < y
87051  *                0  <=>  x == y
87052  *               >0  <=>  x > y
87053  */
87054 DUK_LOCAL int duk__bi_compare(duk__bigint *x, duk__bigint *y) {
87055 	duk_small_int_t i, nx, ny;
87056 	duk_uint32_t tx, ty;
87057 
87058 	DUK_ASSERT(duk__bi_is_valid(x));
87059 	DUK_ASSERT(duk__bi_is_valid(y));
87060 
87061 	nx = x->n;
87062 	ny = y->n;
87063 	if (nx > ny) {
87064 		goto ret_gt;
87065 	}
87066 	if (nx < ny) {
87067 		goto ret_lt;
87068 	}
87069 	for (i = nx - 1; i >= 0; i--) {
87070 		tx = x->v[i];
87071 		ty = y->v[i];
87072 
87073 		if (tx > ty) {
87074 			goto ret_gt;
87075 		}
87076 		if (tx < ty) {
87077 			goto ret_lt;
87078 		}
87079 	}
87080 
87081 	return 0;
87082 
87083  ret_gt:
87084 	return 1;
87085 
87086  ret_lt:
87087 	return -1;
87088 }
87089 
87090 /* x <- y + z */
87091 #if defined(DUK_USE_64BIT_OPS)
87092 DUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
87093 	duk_uint64_t tmp;
87094 	duk_small_int_t i, ny, nz;
87095 
87096 	DUK_ASSERT(duk__bi_is_valid(y));
87097 	DUK_ASSERT(duk__bi_is_valid(z));
87098 
87099 	if (z->n > y->n) {
87100 		duk__bigint *t;
87101 		t = y; y = z; z = t;
87102 	}
87103 	DUK_ASSERT(y->n >= z->n);
87104 
87105 	ny = y->n; nz = z->n;
87106 	tmp = 0U;
87107 	for (i = 0; i < ny; i++) {
87108 		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
87109 		tmp += y->v[i];
87110 		if (i < nz) {
87111 			tmp += z->v[i];
87112 		}
87113 		x->v[i] = (duk_uint32_t) (tmp & 0xffffffffUL);
87114 		tmp = tmp >> 32;
87115 	}
87116 	if (tmp != 0U) {
87117 		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
87118 		x->v[i++] = (duk_uint32_t) tmp;
87119 	}
87120 	x->n = i;
87121 	DUK_ASSERT(x->n <= DUK__BI_MAX_PARTS);
87122 
87123 	/* no need to normalize */
87124 	DUK_ASSERT(duk__bi_is_valid(x));
87125 }
87126 #else  /* DUK_USE_64BIT_OPS */
87127 DUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
87128 	duk_uint32_t carry, tmp1, tmp2;
87129 	duk_small_int_t i, ny, nz;
87130 
87131 	DUK_ASSERT(duk__bi_is_valid(y));
87132 	DUK_ASSERT(duk__bi_is_valid(z));
87133 
87134 	if (z->n > y->n) {
87135 		duk__bigint *t;
87136 		t = y; y = z; z = t;
87137 	}
87138 	DUK_ASSERT(y->n >= z->n);
87139 
87140 	ny = y->n; nz = z->n;
87141 	carry = 0U;
87142 	for (i = 0; i < ny; i++) {
87143 		/* Carry is detected based on wrapping which relies on exact 32-bit
87144 		 * types.
87145 		 */
87146 		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
87147 		tmp1 = y->v[i];
87148 		tmp2 = tmp1;
87149 		if (i < nz) {
87150 			tmp2 += z->v[i];
87151 		}
87152 
87153 		/* Careful with carry condition:
87154 		 *  - If carry not added: 0x12345678 + 0 + 0xffffffff = 0x12345677 (< 0x12345678)
87155 		 *  - If carry added:     0x12345678 + 1 + 0xffffffff = 0x12345678 (== 0x12345678)
87156 		 */
87157 		if (carry) {
87158 			tmp2++;
87159 			carry = (tmp2 <= tmp1 ? 1U : 0U);
87160 		} else {
87161 			carry = (tmp2 < tmp1 ? 1U : 0U);
87162 		}
87163 
87164 		x->v[i] = tmp2;
87165 	}
87166 	if (carry) {
87167 		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
87168 		DUK_ASSERT(carry == 1U);
87169 		x->v[i++] = carry;
87170 	}
87171 	x->n = i;
87172 	DUK_ASSERT(x->n <= DUK__BI_MAX_PARTS);
87173 
87174 	/* no need to normalize */
87175 	DUK_ASSERT(duk__bi_is_valid(x));
87176 }
87177 #endif  /* DUK_USE_64BIT_OPS */
87178 
87179 /* x <- y + z */
87180 DUK_LOCAL void duk__bi_add_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
87181 	duk__bigint tmp;
87182 
87183 	DUK_ASSERT(duk__bi_is_valid(y));
87184 
87185 	/* XXX: this could be optimized; there is only one call site now though */
87186 	duk__bi_set_small(&tmp, z);
87187 	duk__bi_add(x, y, &tmp);
87188 
87189 	DUK_ASSERT(duk__bi_is_valid(x));
87190 }
87191 
87192 #if 0  /* unused */
87193 /* x <- x + y, use t as temp */
87194 DUK_LOCAL void duk__bi_add_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
87195 	duk__bi_add(t, x, y);
87196 	duk__bi_copy(x, t);
87197 }
87198 #endif
87199 
87200 /* x <- y - z, require x >= y => z >= 0, i.e. y >= z */
87201 #if defined(DUK_USE_64BIT_OPS)
87202 DUK_LOCAL void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
87203 	duk_small_int_t i, ny, nz;
87204 	duk_uint32_t ty, tz;
87205 	duk_int64_t tmp;
87206 
87207 	DUK_ASSERT(duk__bi_is_valid(y));
87208 	DUK_ASSERT(duk__bi_is_valid(z));
87209 	DUK_ASSERT(duk__bi_compare(y, z) >= 0);
87210 	DUK_ASSERT(y->n >= z->n);
87211 
87212 	ny = y->n; nz = z->n;
87213 	tmp = 0;
87214 	for (i = 0; i < ny; i++) {
87215 		ty = y->v[i];
87216 		if (i < nz) {
87217 			tz = z->v[i];
87218 		} else {
87219 			tz = 0;
87220 		}
87221 		tmp = (duk_int64_t) ty - (duk_int64_t) tz + tmp;
87222 		x->v[i] = (duk_uint32_t) ((duk_uint64_t) tmp & 0xffffffffUL);
87223 		tmp = tmp >> 32;  /* 0 or -1 */
87224 	}
87225 	DUK_ASSERT(tmp == 0);
87226 
87227 	x->n = i;
87228 	duk__bi_normalize(x);  /* need to normalize, may even cancel to 0 */
87229 	DUK_ASSERT(duk__bi_is_valid(x));
87230 }
87231 #else
87232 DUK_LOCAL void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
87233 	duk_small_int_t i, ny, nz;
87234 	duk_uint32_t tmp1, tmp2, borrow;
87235 
87236 	DUK_ASSERT(duk__bi_is_valid(y));
87237 	DUK_ASSERT(duk__bi_is_valid(z));
87238 	DUK_ASSERT(duk__bi_compare(y, z) >= 0);
87239 	DUK_ASSERT(y->n >= z->n);
87240 
87241 	ny = y->n; nz = z->n;
87242 	borrow = 0U;
87243 	for (i = 0; i < ny; i++) {
87244 		/* Borrow is detected based on wrapping which relies on exact 32-bit
87245 		 * types.
87246 		 */
87247 		tmp1 = y->v[i];
87248 		tmp2 = tmp1;
87249 		if (i < nz) {
87250 			tmp2 -= z->v[i];
87251 		}
87252 
87253 		/* Careful with borrow condition:
87254 		 *  - If borrow not subtracted: 0x12345678 - 0 - 0xffffffff = 0x12345679 (> 0x12345678)
87255 		 *  - If borrow subtracted:     0x12345678 - 1 - 0xffffffff = 0x12345678 (== 0x12345678)
87256 		 */
87257 		if (borrow) {
87258 			tmp2--;
87259 			borrow = (tmp2 >= tmp1 ? 1U : 0U);
87260 		} else {
87261 			borrow = (tmp2 > tmp1 ? 1U : 0U);
87262 		}
87263 
87264 		x->v[i] = tmp2;
87265 	}
87266 	DUK_ASSERT(borrow == 0U);
87267 
87268 	x->n = i;
87269 	duk__bi_normalize(x);  /* need to normalize, may even cancel to 0 */
87270 	DUK_ASSERT(duk__bi_is_valid(x));
87271 }
87272 #endif
87273 
87274 #if 0  /* unused */
87275 /* x <- y - z */
87276 DUK_LOCAL void duk__bi_sub_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
87277 	duk__bigint tmp;
87278 
87279 	DUK_ASSERT(duk__bi_is_valid(y));
87280 
87281 	/* XXX: this could be optimized */
87282 	duk__bi_set_small(&tmp, z);
87283 	duk__bi_sub(x, y, &tmp);
87284 
87285 	DUK_ASSERT(duk__bi_is_valid(x));
87286 }
87287 #endif
87288 
87289 /* x <- x - y, use t as temp */
87290 DUK_LOCAL void duk__bi_sub_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
87291 	duk__bi_sub(t, x, y);
87292 	duk__bi_copy(x, t);
87293 }
87294 
87295 /* x <- y * z */
87296 DUK_LOCAL void duk__bi_mul(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
87297 	duk_small_int_t i, j, nx, nz;
87298 
87299 	DUK_ASSERT(duk__bi_is_valid(y));
87300 	DUK_ASSERT(duk__bi_is_valid(z));
87301 
87302 	nx = y->n + z->n;  /* max possible */
87303 	DUK_ASSERT(nx <= DUK__BI_MAX_PARTS);
87304 
87305 	if (nx == 0) {
87306 		/* Both inputs are zero; cases where only one is zero can go
87307 		 * through main algorithm.
87308 		 */
87309 		x->n = 0;
87310 		return;
87311 	}
87312 
87313 	duk_memzero((void *) x->v, (size_t) (sizeof(duk_uint32_t) * (size_t) nx));
87314 	x->n = nx;
87315 
87316 	nz = z->n;
87317 	for (i = 0; i < y->n; i++) {
87318 #if defined(DUK_USE_64BIT_OPS)
87319 		duk_uint64_t tmp = 0U;
87320 		for (j = 0; j < nz; j++) {
87321 			tmp += (duk_uint64_t) y->v[i] * (duk_uint64_t) z->v[j] + x->v[i+j];
87322 			x->v[i+j] = (duk_uint32_t) (tmp & 0xffffffffUL);
87323 			tmp = tmp >> 32;
87324 		}
87325 		if (tmp > 0) {
87326 			DUK_ASSERT(i + j < nx);
87327 			DUK_ASSERT(i + j < DUK__BI_MAX_PARTS);
87328 			DUK_ASSERT(x->v[i+j] == 0U);
87329 			x->v[i+j] = (duk_uint32_t) tmp;
87330 		}
87331 #else
87332 		/*
87333 		 *  Multiply + add + carry for 32-bit components using only 16x16->32
87334 		 *  multiplies and carry detection based on unsigned overflow.
87335 		 *
87336 		 *    1st mult, 32-bit: (A*2^16 + B)
87337 		 *    2nd mult, 32-bit: (C*2^16 + D)
87338 		 *    3rd add, 32-bit: E
87339 		 *    4th add, 32-bit: F
87340 		 *
87341 		 *      (AC*2^16 + B) * (C*2^16 + D) + E + F
87342 		 *    = AC*2^32 + AD*2^16 + BC*2^16 + BD + E + F
87343 		 *    = AC*2^32 + (AD + BC)*2^16 + (BD + E + F)
87344 		 *    = AC*2^32 + AD*2^16 + BC*2^16 + (BD + E + F)
87345 		 */
87346 		duk_uint32_t a, b, c, d, e, f;
87347 		duk_uint32_t r, s, t;
87348 
87349 		a = y->v[i]; b = a & 0xffffUL; a = a >> 16;
87350 
87351 		f = 0;
87352 		for (j = 0; j < nz; j++) {
87353 			c = z->v[j]; d = c & 0xffffUL; c = c >> 16;
87354 			e = x->v[i+j];
87355 
87356 			/* build result as: (r << 32) + s: start with (BD + E + F) */
87357 			r = 0;
87358 			s = b * d;
87359 
87360 			/* add E */
87361 			t = s + e;
87362 			if (t < s) { r++; }  /* carry */
87363 			s = t;
87364 
87365 			/* add F */
87366 			t = s + f;
87367 			if (t < s) { r++; }  /* carry */
87368 			s = t;
87369 
87370 			/* add BC*2^16 */
87371 			t = b * c;
87372 			r += (t >> 16);
87373 			t = s + ((t & 0xffffUL) << 16);
87374 			if (t < s) { r++; }  /* carry */
87375 			s = t;
87376 
87377 			/* add AD*2^16 */
87378 			t = a * d;
87379 			r += (t >> 16);
87380 			t = s + ((t & 0xffffUL) << 16);
87381 			if (t < s) { r++; }  /* carry */
87382 			s = t;
87383 
87384 			/* add AC*2^32 */
87385 			t = a * c;
87386 			r += t;
87387 
87388 			DUK_DDD(DUK_DDDPRINT("ab=%08lx cd=%08lx ef=%08lx -> rs=%08lx %08lx",
87389 			                     (unsigned long) y->v[i], (unsigned long) z->v[j],
87390 			                     (unsigned long) x->v[i+j], (unsigned long) r,
87391 			                     (unsigned long) s));
87392 
87393 			x->v[i+j] = s;
87394 			f = r;
87395 		}
87396 		if (f > 0U) {
87397 			DUK_ASSERT(i + j < nx);
87398 			DUK_ASSERT(i + j < DUK__BI_MAX_PARTS);
87399 			DUK_ASSERT(x->v[i+j] == 0U);
87400 			x->v[i+j] = (duk_uint32_t) f;
87401 		}
87402 #endif  /* DUK_USE_64BIT_OPS */
87403 	}
87404 
87405 	duk__bi_normalize(x);
87406 	DUK_ASSERT(duk__bi_is_valid(x));
87407 }
87408 
87409 /* x <- y * z */
87410 DUK_LOCAL void duk__bi_mul_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
87411 	duk__bigint tmp;
87412 
87413 	DUK_ASSERT(duk__bi_is_valid(y));
87414 
87415 	/* XXX: this could be optimized */
87416 	duk__bi_set_small(&tmp, z);
87417 	duk__bi_mul(x, y, &tmp);
87418 
87419 	DUK_ASSERT(duk__bi_is_valid(x));
87420 }
87421 
87422 /* x <- x * y, use t as temp */
87423 DUK_LOCAL void duk__bi_mul_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
87424 	duk__bi_mul(t, x, y);
87425 	duk__bi_copy(x, t);
87426 }
87427 
87428 /* x <- x * y, use t as temp */
87429 DUK_LOCAL void duk__bi_mul_small_copy(duk__bigint *x, duk_uint32_t y, duk__bigint *t) {
87430 	duk__bi_mul_small(t, x, y);
87431 	duk__bi_copy(x, t);
87432 }
87433 
87434 DUK_LOCAL int duk__bi_is_even(duk__bigint *x) {
87435 	DUK_ASSERT(duk__bi_is_valid(x));
87436 	return (x->n == 0) || ((x->v[0] & 0x01) == 0);
87437 }
87438 
87439 DUK_LOCAL int duk__bi_is_zero(duk__bigint *x) {
87440 	DUK_ASSERT(duk__bi_is_valid(x));
87441 	return (x->n == 0);  /* this is the case for normalized numbers */
87442 }
87443 
87444 /* Bigint is 2^52.  Used to detect normalized IEEE double mantissa values
87445  * which are at the lowest edge (next floating point value downwards has
87446  * a different exponent).  The lowest mantissa has the form:
87447  *
87448  *     1000........000    (52 zeroes; only "hidden bit" is set)
87449  */
87450 DUK_LOCAL duk_small_int_t duk__bi_is_2to52(duk__bigint *x) {
87451 	DUK_ASSERT(duk__bi_is_valid(x));
87452 	return (duk_small_int_t)
87453 	        (x->n == 2) && (x->v[0] == 0U) && (x->v[1] == (1U << (52-32)));
87454 }
87455 
87456 /* x <- (1<<y) */
87457 DUK_LOCAL void duk__bi_twoexp(duk__bigint *x, duk_small_int_t y) {
87458 	duk_small_int_t n, r;
87459 
87460 	n = (y / 32) + 1;
87461 	DUK_ASSERT(n > 0);
87462 	r = y % 32;
87463 	duk_memzero((void *) x->v, sizeof(duk_uint32_t) * (size_t) n);
87464 	x->n = n;
87465 	x->v[n - 1] = (((duk_uint32_t) 1) << r);
87466 }
87467 
87468 /* x <- b^y; use t1 and t2 as temps */
87469 DUK_LOCAL void duk__bi_exp_small(duk__bigint *x, duk_small_int_t b, duk_small_int_t y, duk__bigint *t1, duk__bigint *t2) {
87470 	/* Fast path the binary case */
87471 
87472 	DUK_ASSERT(x != t1 && x != t2 && t1 != t2);  /* distinct bignums, easy mistake to make */
87473 	DUK_ASSERT(b >= 0);
87474 	DUK_ASSERT(y >= 0);
87475 
87476 	if (b == 2) {
87477 		duk__bi_twoexp(x, y);
87478 		return;
87479 	}
87480 
87481 	/* http://en.wikipedia.org/wiki/Exponentiation_by_squaring */
87482 
87483 	DUK_DDD(DUK_DDDPRINT("exp_small: b=%ld, y=%ld", (long) b, (long) y));
87484 
87485 	duk__bi_set_small(x, 1);
87486 	duk__bi_set_small(t1, (duk_uint32_t) b);
87487 	for (;;) {
87488 		/* Loop structure ensures that we don't compute t1^2 unnecessarily
87489 		 * on the final round, as that might create a bignum exceeding the
87490 		 * current DUK__BI_MAX_PARTS limit.
87491 		 */
87492 		if (y & 0x01) {
87493 			duk__bi_mul_copy(x, t1, t2);
87494 		}
87495 		y = y >> 1;
87496 		if (y == 0) {
87497 			break;
87498 		}
87499 		duk__bi_mul_copy(t1, t1, t2);
87500 	}
87501 
87502 	DUK__BI_PRINT("exp_small result", x);
87503 }
87504 
87505 /*
87506  *  A Dragon4 number-to-string variant, based on:
87507  *
87508  *    Guy L. Steele Jr., Jon L. White: "How to Print Floating-Point Numbers
87509  *    Accurately"
87510  *
87511  *    Robert G. Burger, R. Kent Dybvig: "Printing Floating-Point Numbers
87512  *    Quickly and Accurately"
87513  *
87514  *  The current algorithm is based on Figure 1 of the Burger-Dybvig paper,
87515  *  i.e. the base implementation without logarithm estimation speedups
87516  *  (these would increase code footprint considerably).  Fixed-format output
87517  *  does not follow the suggestions in the paper; instead, we generate an
87518  *  extra digit and round-with-carry.
87519  *
87520  *  The same algorithm is used for number parsing (with b=10 and B=2)
87521  *  by generating one extra digit and doing rounding manually.
87522  *
87523  *  See doc/number-conversion.rst for limitations.
87524  */
87525 
87526 /* Maximum number of digits generated. */
87527 #define DUK__MAX_OUTPUT_DIGITS          1040  /* (Number.MAX_VALUE).toString(2).length == 1024, + slack */
87528 
87529 /* Maximum number of characters in formatted value. */
87530 #define DUK__MAX_FORMATTED_LENGTH       1040  /* (-Number.MAX_VALUE).toString(2).length == 1025, + slack */
87531 
87532 /* Number and (minimum) size of bigints in the nc_ctx structure. */
87533 #define DUK__NUMCONV_CTX_NUM_BIGINTS    7
87534 #define DUK__NUMCONV_CTX_BIGINTS_SIZE   (sizeof(duk__bigint) * DUK__NUMCONV_CTX_NUM_BIGINTS)
87535 
87536 typedef struct {
87537 	/* Currently about 7*152 = 1064 bytes.  The space for these
87538 	 * duk__bigints is used also as a temporary buffer for generating
87539 	 * the final string.  This is a bit awkard; a union would be
87540 	 * more correct.
87541 	 */
87542 	duk__bigint f, r, s, mp, mm, t1, t2;
87543 
87544 	duk_small_int_t is_s2n;        /* if 1, doing a string-to-number; else doing a number-to-string */
87545 	duk_small_int_t is_fixed;      /* if 1, doing a fixed format output (not free format) */
87546 	duk_small_int_t req_digits;    /* requested number of output digits; 0 = free-format */
87547 	duk_small_int_t abs_pos;       /* digit position is absolute, not relative */
87548 	duk_small_int_t e;             /* exponent for 'f' */
87549 	duk_small_int_t b;             /* input radix */
87550 	duk_small_int_t B;             /* output radix */
87551 	duk_small_int_t k;             /* see algorithm */
87552 	duk_small_int_t low_ok;        /* see algorithm */
87553 	duk_small_int_t high_ok;       /* see algorithm */
87554 	duk_small_int_t unequal_gaps;  /* m+ != m- (very rarely) */
87555 
87556 	/* Buffer used for generated digits, values are in the range [0,B-1]. */
87557 	duk_uint8_t digits[DUK__MAX_OUTPUT_DIGITS];
87558 	duk_small_int_t count;  /* digit count */
87559 } duk__numconv_stringify_ctx;
87560 
87561 /* Note: computes with 'idx' in assertions, so caller beware.
87562  * 'idx' is preincremented, i.e. '1' on first call, because it
87563  * is more convenient for the caller.
87564  */
87565 #define DUK__DRAGON4_OUTPUT_PREINC(nc_ctx,preinc_idx,x)  do { \
87566 		DUK_ASSERT((preinc_idx) - 1 >= 0); \
87567 		DUK_ASSERT((preinc_idx) - 1 < DUK__MAX_OUTPUT_DIGITS); \
87568 		((nc_ctx)->digits[(preinc_idx) - 1]) = (duk_uint8_t) (x); \
87569 	} while (0)
87570 
87571 DUK_LOCAL duk_size_t duk__dragon4_format_uint32(duk_uint8_t *buf, duk_uint32_t x, duk_small_int_t radix) {
87572 	duk_uint8_t *p;
87573 	duk_size_t len;
87574 	duk_small_int_t dig;
87575 	duk_uint32_t t;
87576 
87577 	DUK_ASSERT(buf != NULL);
87578 	DUK_ASSERT(radix >= 2 && radix <= 36);
87579 
87580 	/* A 32-bit unsigned integer formats to at most 32 digits (the
87581 	 * worst case happens with radix == 2).  Output the digits backwards,
87582 	 * and use a memmove() to get them in the right place.
87583 	 */
87584 
87585 	p = buf + 32;
87586 	for (;;) {
87587 		t = x / (duk_uint32_t) radix;
87588 		dig = (duk_small_int_t) (x - t * (duk_uint32_t) radix);
87589 		x = t;
87590 
87591 		DUK_ASSERT(dig >= 0 && dig < 36);
87592 		*(--p) = DUK__DIGITCHAR(dig);
87593 
87594 		if (x == 0) {
87595 			break;
87596 		}
87597 	}
87598 	len = (duk_size_t) ((buf + 32) - p);
87599 
87600 	duk_memmove((void *) buf, (const void *) p, (size_t) len);
87601 
87602 	return len;
87603 }
87604 
87605 DUK_LOCAL void duk__dragon4_prepare(duk__numconv_stringify_ctx *nc_ctx) {
87606 	duk_small_int_t lowest_mantissa;
87607 
87608 #if 1
87609 	/* Assume IEEE round-to-even, so that shorter encoding can be used
87610 	 * when round-to-even would produce correct result.  By removing
87611 	 * this check (and having low_ok == high_ok == 0) the results would
87612 	 * still be accurate but in some cases longer than necessary.
87613 	 */
87614 	if (duk__bi_is_even(&nc_ctx->f)) {
87615 		DUK_DDD(DUK_DDDPRINT("f is even"));
87616 		nc_ctx->low_ok = 1;
87617 		nc_ctx->high_ok = 1;
87618 	} else {
87619 		DUK_DDD(DUK_DDDPRINT("f is odd"));
87620 		nc_ctx->low_ok = 0;
87621 		nc_ctx->high_ok = 0;
87622 	}
87623 #else
87624 	/* Note: not honoring round-to-even should work but now generates incorrect
87625 	 * results.  For instance, 1e23 serializes to "a000...", i.e. the first digit
87626 	 * equals the radix (10).  Scaling stops one step too early in this case.
87627 	 * Don't know why this is the case, but since this code path is unused, it
87628 	 * doesn't matter.
87629 	 */
87630 	nc_ctx->low_ok = 0;
87631 	nc_ctx->high_ok = 0;
87632 #endif
87633 
87634 	/* For string-to-number, pretend we never have the lowest mantissa as there
87635 	 * is no natural "precision" for inputs.  Having lowest_mantissa == 0, we'll
87636 	 * fall into the base cases for both e >= 0 and e < 0.
87637 	 */
87638 	if (nc_ctx->is_s2n) {
87639 		lowest_mantissa = 0;
87640 	} else {
87641 		lowest_mantissa = duk__bi_is_2to52(&nc_ctx->f);
87642 	}
87643 
87644 	nc_ctx->unequal_gaps = 0;
87645 	if (nc_ctx->e >= 0) {
87646 		/* exponent non-negative (and thus not minimum exponent) */
87647 
87648 		if (lowest_mantissa) {
87649 			/* (>= e 0) AND (= f (expt b (- p 1)))
87650 			 *
87651 			 * be <- (expt b e) == b^e
87652 			 * be1 <- (* be b) == (expt b (+ e 1)) == b^(e+1)
87653 			 * r <- (* f be1 2) == 2 * f * b^(e+1)    [if b==2 -> f * b^(e+2)]
87654 			 * s <- (* b 2)                           [if b==2 -> 4]
87655 			 * m+ <- be1 == b^(e+1)
87656 			 * m- <- be == b^e
87657 			 * k <- 0
87658 			 * B <- B
87659 			 * low_ok <- round
87660 			 * high_ok <- round
87661 			 */
87662 
87663 			DUK_DDD(DUK_DDDPRINT("non-negative exponent (not smallest exponent); "
87664 			                     "lowest mantissa value for this exponent -> "
87665 			                     "unequal gaps"));
87666 
87667 			duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2);  /* mm <- b^e */
87668 			duk__bi_mul_small(&nc_ctx->mp, &nc_ctx->mm, (duk_uint32_t) nc_ctx->b);           /* mp <- b^(e+1) */
87669 			duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
87670 			duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp);              /* r <- (2 * f) * b^(e+1) */
87671 			duk__bi_set_small(&nc_ctx->s, (duk_uint32_t) (nc_ctx->b * 2));  /* s <- 2 * b */
87672 			nc_ctx->unequal_gaps = 1;
87673 		} else {
87674 			/* (>= e 0) AND (not (= f (expt b (- p 1))))
87675 			 *
87676 			 * be <- (expt b e) == b^e
87677 			 * r <- (* f be 2) == 2 * f * b^e    [if b==2 -> f * b^(e+1)]
87678 			 * s <- 2
87679 			 * m+ <- be == b^e
87680 			 * m- <- be == b^e
87681 			 * k <- 0
87682 			 * B <- B
87683 			 * low_ok <- round
87684 			 * high_ok <- round
87685 			 */
87686 
87687 			DUK_DDD(DUK_DDDPRINT("non-negative exponent (not smallest exponent); "
87688 			                     "not lowest mantissa for this exponent -> "
87689 			                     "equal gaps"));
87690 
87691 			duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2);  /* mm <- b^e */
87692 			duk__bi_copy(&nc_ctx->mp, &nc_ctx->mm);                /* mp <- b^e */
87693 			duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
87694 			duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp);     /* r <- (2 * f) * b^e */
87695 			duk__bi_set_small(&nc_ctx->s, 2);                      /* s <- 2 */
87696 		}
87697 	} else {
87698 		/* When doing string-to-number, lowest_mantissa is always 0 so
87699 		 * the exponent check, while incorrect, won't matter.
87700 		 */
87701 		if (nc_ctx->e > DUK__IEEE_DOUBLE_EXP_MIN /*not minimum exponent*/ &&
87702 		    lowest_mantissa /* lowest mantissa for this exponent*/) {
87703 			/* r <- (* f b 2)                                [if b==2 -> (* f 4)]
87704 			 * s <- (* (expt b (- 1 e)) 2) == b^(1-e) * 2    [if b==2 -> b^(2-e)]
87705 			 * m+ <- b == 2
87706 			 * m- <- 1
87707 			 * k <- 0
87708 			 * B <- B
87709 			 * low_ok <- round
87710 			 * high_ok <- round
87711 			 */
87712 
87713 			DUK_DDD(DUK_DDDPRINT("negative exponent; not minimum exponent and "
87714 			                     "lowest mantissa for this exponent -> "
87715 			                     "unequal gaps"));
87716 
87717 			duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, (duk_uint32_t) (nc_ctx->b * 2));  /* r <- (2 * b) * f */
87718 			duk__bi_exp_small(&nc_ctx->t1, nc_ctx->b, 1 - nc_ctx->e, &nc_ctx->s, &nc_ctx->t2);  /* NB: use 's' as temp on purpose */
87719 			duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2);             /* s <- b^(1-e) * 2 */
87720 			duk__bi_set_small(&nc_ctx->mp, 2);
87721 			duk__bi_set_small(&nc_ctx->mm, 1);
87722 			nc_ctx->unequal_gaps = 1;
87723 		} else {
87724 			/* r <- (* f 2)
87725 			 * s <- (* (expt b (- e)) 2) == b^(-e) * 2    [if b==2 -> b^(1-e)]
87726 			 * m+ <- 1
87727 			 * m- <- 1
87728 			 * k <- 0
87729 			 * B <- B
87730 			 * low_ok <- round
87731 			 * high_ok <- round
87732 			 */
87733 
87734 			DUK_DDD(DUK_DDDPRINT("negative exponent; minimum exponent or not "
87735 			                     "lowest mantissa for this exponent -> "
87736 			                     "equal gaps"));
87737 
87738 			duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, 2);            /* r <- 2 * f */
87739 			duk__bi_exp_small(&nc_ctx->t1, nc_ctx->b, -nc_ctx->e, &nc_ctx->s, &nc_ctx->t2);  /* NB: use 's' as temp on purpose */
87740 			duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2);           /* s <- b^(-e) * 2 */
87741 			duk__bi_set_small(&nc_ctx->mp, 1);
87742 			duk__bi_set_small(&nc_ctx->mm, 1);
87743 		}
87744 	}
87745 }
87746 
87747 DUK_LOCAL void duk__dragon4_scale(duk__numconv_stringify_ctx *nc_ctx) {
87748 	duk_small_int_t k = 0;
87749 
87750 	/* This is essentially the 'scale' algorithm, with recursion removed.
87751 	 * Note that 'k' is either correct immediately, or will move in one
87752 	 * direction in the loop.  There's no need to do the low/high checks
87753 	 * on every round (like the Scheme algorithm does).
87754 	 *
87755 	 * The scheme algorithm finds 'k' and updates 's' simultaneously,
87756 	 * while the logical algorithm finds 'k' with 's' having its initial
87757 	 * value, after which 's' is updated separately (see the Burger-Dybvig
87758 	 * paper, Section 3.1, steps 2 and 3).
87759 	 *
87760 	 * The case where m+ == m- (almost always) is optimized for, because
87761 	 * it reduces the bigint operations considerably and almost always
87762 	 * applies.  The scale loop only needs to work with m+, so this works.
87763 	 */
87764 
87765 	/* XXX: this algorithm could be optimized quite a lot by using e.g.
87766 	 * a logarithm based estimator for 'k' and performing B^n multiplication
87767 	 * using a lookup table or using some bit-representation based exp
87768 	 * algorithm.  Currently we just loop, with significant performance
87769 	 * impact for very large and very small numbers.
87770 	 */
87771 
87772 	DUK_DDD(DUK_DDDPRINT("scale: B=%ld, low_ok=%ld, high_ok=%ld",
87773 	                     (long) nc_ctx->B, (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
87774 	DUK__BI_PRINT("r(init)", &nc_ctx->r);
87775 	DUK__BI_PRINT("s(init)", &nc_ctx->s);
87776 	DUK__BI_PRINT("mp(init)", &nc_ctx->mp);
87777 	DUK__BI_PRINT("mm(init)", &nc_ctx->mm);
87778 
87779 	for (;;) {
87780 		DUK_DDD(DUK_DDDPRINT("scale loop (inc k), k=%ld", (long) k));
87781 		DUK__BI_PRINT("r", &nc_ctx->r);
87782 		DUK__BI_PRINT("s", &nc_ctx->s);
87783 		DUK__BI_PRINT("m+", &nc_ctx->mp);
87784 		DUK__BI_PRINT("m-", &nc_ctx->mm);
87785 
87786 		duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 = (+ r m+) */
87787 		if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1)) {
87788 			DUK_DDD(DUK_DDDPRINT("k is too low"));
87789 			/* r <- r
87790 			 * s <- (* s B)
87791 			 * m+ <- m+
87792 			 * m- <- m-
87793 			 * k <- (+ k 1)
87794 			 */
87795 
87796 			duk__bi_mul_small_copy(&nc_ctx->s, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
87797 			k++;
87798 		} else {
87799 			break;
87800 		}
87801 	}
87802 
87803 	/* k > 0 -> k was too low, and cannot be too high */
87804 	if (k > 0) {
87805 		goto skip_dec_k;
87806 	}
87807 
87808 	for (;;) {
87809 		DUK_DDD(DUK_DDDPRINT("scale loop (dec k), k=%ld", (long) k));
87810 		DUK__BI_PRINT("r", &nc_ctx->r);
87811 		DUK__BI_PRINT("s", &nc_ctx->s);
87812 		DUK__BI_PRINT("m+", &nc_ctx->mp);
87813 		DUK__BI_PRINT("m-", &nc_ctx->mm);
87814 
87815 		duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 = (+ r m+) */
87816 		duk__bi_mul_small(&nc_ctx->t2, &nc_ctx->t1, (duk_uint32_t) nc_ctx->B);   /* t2 = (* (+ r m+) B) */
87817 		if (duk__bi_compare(&nc_ctx->t2, &nc_ctx->s) <= (nc_ctx->high_ok ? -1 : 0)) {
87818 			DUK_DDD(DUK_DDDPRINT("k is too high"));
87819 			/* r <- (* r B)
87820 			 * s <- s
87821 			 * m+ <- (* m+ B)
87822 			 * m- <- (* m- B)
87823 			 * k <- (- k 1)
87824 			 */
87825 			duk__bi_mul_small_copy(&nc_ctx->r, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
87826 			duk__bi_mul_small_copy(&nc_ctx->mp, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
87827 			if (nc_ctx->unequal_gaps) {
87828 				DUK_DDD(DUK_DDDPRINT("m+ != m- -> need to update m- too"));
87829 				duk__bi_mul_small_copy(&nc_ctx->mm, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
87830 			}
87831 			k--;
87832 		} else {
87833 			break;
87834 		}
87835 	}
87836 
87837  skip_dec_k:
87838 
87839 	if (!nc_ctx->unequal_gaps) {
87840 		DUK_DDD(DUK_DDDPRINT("equal gaps, copy m- from m+"));
87841 		duk__bi_copy(&nc_ctx->mm, &nc_ctx->mp);  /* mm <- mp */
87842 	}
87843 	nc_ctx->k = k;
87844 
87845 	DUK_DDD(DUK_DDDPRINT("final k: %ld", (long) k));
87846 	DUK__BI_PRINT("r(final)", &nc_ctx->r);
87847 	DUK__BI_PRINT("s(final)", &nc_ctx->s);
87848 	DUK__BI_PRINT("mp(final)", &nc_ctx->mp);
87849 	DUK__BI_PRINT("mm(final)", &nc_ctx->mm);
87850 }
87851 
87852 DUK_LOCAL void duk__dragon4_generate(duk__numconv_stringify_ctx *nc_ctx) {
87853 	duk_small_int_t tc1, tc2;    /* terminating conditions */
87854 	duk_small_int_t d;           /* current digit */
87855 	duk_small_int_t count = 0;   /* digit count */
87856 
87857 	/*
87858 	 *  Digit generation loop.
87859 	 *
87860 	 *  Different termination conditions:
87861 	 *
87862 	 *    1. Free format output.  Terminate when shortest accurate
87863 	 *       representation found.
87864 	 *
87865 	 *    2. Fixed format output, with specific number of digits.
87866 	 *       Ignore termination conditions, terminate when digits
87867 	 *       generated.  Caller requests an extra digit and rounds.
87868 	 *
87869 	 *    3. Fixed format output, with a specific absolute cut-off
87870 	 *       position (e.g. 10 digits after decimal point).  Note
87871 	 *       that we always generate at least one digit, even if
87872 	 *       the digit is below the cut-off point already.
87873 	 */
87874 
87875 	for (;;) {
87876 		DUK_DDD(DUK_DDDPRINT("generate loop, count=%ld, k=%ld, B=%ld, low_ok=%ld, high_ok=%ld",
87877 		                     (long) count, (long) nc_ctx->k, (long) nc_ctx->B,
87878 		                     (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
87879 		DUK__BI_PRINT("r", &nc_ctx->r);
87880 		DUK__BI_PRINT("s", &nc_ctx->s);
87881 		DUK__BI_PRINT("m+", &nc_ctx->mp);
87882 		DUK__BI_PRINT("m-", &nc_ctx->mm);
87883 
87884 		/* (quotient-remainder (* r B) s) using a dummy subtraction loop */
87885 		duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, (duk_uint32_t) nc_ctx->B);       /* t1 <- (* r B) */
87886 		d = 0;
87887 		for (;;) {
87888 			if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) {
87889 				break;
87890 			}
87891 			duk__bi_sub_copy(&nc_ctx->t1, &nc_ctx->s, &nc_ctx->t2);  /* t1 <- t1 - s */
87892 			d++;
87893 		}
87894 		duk__bi_copy(&nc_ctx->r, &nc_ctx->t1);  /* r <- (remainder (* r B) s) */
87895 		                                        /* d <- (quotient (* r B) s)   (in range 0...B-1) */
87896 		DUK_DDD(DUK_DDDPRINT("-> d(quot)=%ld", (long) d));
87897 		DUK__BI_PRINT("r(rem)", &nc_ctx->r);
87898 
87899 		duk__bi_mul_small_copy(&nc_ctx->mp, (duk_uint32_t) nc_ctx->B, &nc_ctx->t2); /* m+ <- (* m+ B) */
87900 		duk__bi_mul_small_copy(&nc_ctx->mm, (duk_uint32_t) nc_ctx->B, &nc_ctx->t2); /* m- <- (* m- B) */
87901 		DUK__BI_PRINT("mp(upd)", &nc_ctx->mp);
87902 		DUK__BI_PRINT("mm(upd)", &nc_ctx->mm);
87903 
87904 		/* Terminating conditions.  For fixed width output, we just ignore the
87905 		 * terminating conditions (and pretend that tc1 == tc2 == false).  The
87906 		 * the current shortcut for fixed-format output is to generate a few
87907 		 * extra digits and use rounding (with carry) to finish the output.
87908 		 */
87909 
87910 		if (nc_ctx->is_fixed == 0) {
87911 			/* free-form */
87912 			tc1 = (duk__bi_compare(&nc_ctx->r, &nc_ctx->mm) <= (nc_ctx->low_ok ? 0 : -1));
87913 
87914 			duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 <- (+ r m+) */
87915 			tc2 = (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1));
87916 
87917 			DUK_DDD(DUK_DDDPRINT("tc1=%ld, tc2=%ld", (long) tc1, (long) tc2));
87918 		} else {
87919 			/* fixed-format */
87920 			tc1 = 0;
87921 			tc2 = 0;
87922 		}
87923 
87924 		/* Count is incremented before DUK__DRAGON4_OUTPUT_PREINC() call
87925 		 * on purpose, which is taken into account by the macro.
87926 		 */
87927 		count++;
87928 
87929 		if (tc1) {
87930 			if (tc2) {
87931 				/* tc1 = true, tc2 = true */
87932 				duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, 2);
87933 				if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) {  /* (< (* r 2) s) */
87934 					DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r > s: output d --> %ld (k=%ld)",
87935 					                     (long) d, (long) nc_ctx->k));
87936 					DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
87937 				} else {
87938 					DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r <= s: output d+1 --> %ld (k=%ld)",
87939 					                     (long) (d + 1), (long) nc_ctx->k));
87940 					DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
87941 				}
87942 				break;
87943 			} else {
87944 				/* tc1 = true, tc2 = false */
87945 				DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=false: output d --> %ld (k=%ld)",
87946 				                     (long) d, (long) nc_ctx->k));
87947 				DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
87948 				break;
87949 			}
87950 		} else {
87951 			if (tc2) {
87952 				/* tc1 = false, tc2 = true */
87953 				DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=true: output d+1 --> %ld (k=%ld)",
87954 				                     (long) (d + 1), (long) nc_ctx->k));
87955 				DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
87956 				break;
87957 			} else {
87958 				/* tc1 = false, tc2 = false */
87959 				DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=false: output d --> %ld (k=%ld)",
87960 				                     (long) d, (long) nc_ctx->k));
87961 				DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
87962 
87963 				/* r <- r    (updated above: r <- (remainder (* r B) s)
87964 				 * s <- s
87965 				 * m+ <- m+  (updated above: m+ <- (* m+ B)
87966 				 * m- <- m-  (updated above: m- <- (* m- B)
87967 				 * B, low_ok, high_ok are fixed
87968 				 */
87969 
87970 				/* fall through and continue for-loop */
87971 			}
87972 		}
87973 
87974 		/* fixed-format termination conditions */
87975 		if (nc_ctx->is_fixed) {
87976 			if (nc_ctx->abs_pos) {
87977 				int pos = nc_ctx->k - count + 1;  /* count is already incremented, take into account */
87978 				DUK_DDD(DUK_DDDPRINT("fixed format, absolute: abs pos=%ld, k=%ld, count=%ld, req=%ld",
87979 				                     (long) pos, (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));
87980 				if (pos <= nc_ctx->req_digits) {
87981 					DUK_DDD(DUK_DDDPRINT("digit position reached req_digits, end generate loop"));
87982 					break;
87983 				}
87984 			} else {
87985 				DUK_DDD(DUK_DDDPRINT("fixed format, relative: k=%ld, count=%ld, req=%ld",
87986 				                     (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));
87987 				if (count >= nc_ctx->req_digits) {
87988 					DUK_DDD(DUK_DDDPRINT("digit count reached req_digits, end generate loop"));
87989 					break;
87990 				}
87991 			}
87992 		}
87993 	}  /* for */
87994 
87995 	nc_ctx->count = count;
87996 
87997 	DUK_DDD(DUK_DDDPRINT("generate finished"));
87998 
87999 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
88000 	{
88001 		duk_uint8_t buf[2048];
88002 		duk_small_int_t i, t;
88003 		duk_memzero(buf, sizeof(buf));
88004 		for (i = 0; i < nc_ctx->count; i++) {
88005 			t = nc_ctx->digits[i];
88006 			if (t < 0 || t > 36) {
88007 				buf[i] = (duk_uint8_t) '?';
88008 			} else {
88009 				buf[i] = (duk_uint8_t) DUK__DIGITCHAR(t);
88010 			}
88011 		}
88012 		DUK_DDD(DUK_DDDPRINT("-> generated digits; k=%ld, digits='%s'",
88013 		                     (long) nc_ctx->k, (const char *) buf));
88014 	}
88015 #endif
88016 }
88017 
88018 /* Round up digits to a given position.  If position is out-of-bounds,
88019  * does nothing.  If carry propagates over the first digit, a '1' is
88020  * prepended to digits and 'k' will be updated.  Return value indicates
88021  * whether carry propagated over the first digit.
88022  *
88023  * Note that nc_ctx->count is NOT updated based on the rounding position
88024  * (it is updated only if carry overflows over the first digit and an
88025  * extra digit is prepended).
88026  */
88027 DUK_LOCAL duk_small_int_t duk__dragon4_fixed_format_round(duk__numconv_stringify_ctx *nc_ctx, duk_small_int_t round_idx) {
88028 	duk_small_int_t t;
88029 	duk_uint8_t *p;
88030 	duk_uint8_t roundup_limit;
88031 	duk_small_int_t ret = 0;
88032 
88033 	/*
88034 	 *  round_idx points to the digit which is considered for rounding; the
88035 	 *  digit to its left is the final digit of the rounded value.  If round_idx
88036 	 *  is zero, rounding will be performed; the result will either be an empty
88037 	 *  rounded value or if carry happens a '1' digit is generated.
88038 	 */
88039 
88040 	if (round_idx >= nc_ctx->count) {
88041 		DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld >= %ld (count)) -> no rounding",
88042 		                     (long) round_idx, (long) nc_ctx->count));
88043 		return 0;
88044 	} else if (round_idx < 0) {
88045 		DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld < 0) -> no rounding",
88046 		                     (long) round_idx));
88047 		return 0;
88048 	}
88049 
88050 	/*
88051 	 *  Round-up limit.
88052 	 *
88053 	 *  For even values, divides evenly, e.g. 10 -> roundup_limit=5.
88054 	 *
88055 	 *  For odd values, rounds up, e.g. 3 -> roundup_limit=2.
88056 	 *  If radix is 3, 0/3 -> down, 1/3 -> down, 2/3 -> up.
88057 	 */
88058 	roundup_limit = (duk_uint8_t) ((nc_ctx->B + 1) / 2);
88059 
88060 	p = &nc_ctx->digits[round_idx];
88061 	if (*p >= roundup_limit) {
88062 		DUK_DDD(DUK_DDDPRINT("fixed-format rounding carry required"));
88063 		/* carry */
88064 		for (;;) {
88065 			*p = 0;
88066 			if (p == &nc_ctx->digits[0]) {
88067 				DUK_DDD(DUK_DDDPRINT("carry propagated to first digit -> special case handling"));
88068 				duk_memmove((void *) (&nc_ctx->digits[1]),
88069 				            (const void *) (&nc_ctx->digits[0]),
88070 				            (size_t) (sizeof(char) * (size_t) nc_ctx->count));
88071 				nc_ctx->digits[0] = 1;  /* don't increase 'count' */
88072 				nc_ctx->k++;  /* position of highest digit changed */
88073 				nc_ctx->count++;  /* number of digits changed */
88074 				ret = 1;
88075 				break;
88076 			}
88077 
88078 			DUK_DDD(DUK_DDDPRINT("fixed-format rounding carry: B=%ld, roundup_limit=%ld, p=%p, digits=%p",
88079 			                     (long) nc_ctx->B, (long) roundup_limit, (void *) p, (void *) nc_ctx->digits));
88080 			p--;
88081 			t = *p;
88082 			DUK_DDD(DUK_DDDPRINT("digit before carry: %ld", (long) t));
88083 			if (++t < nc_ctx->B) {
88084 				DUK_DDD(DUK_DDDPRINT("rounding carry terminated"));
88085 				*p = (duk_uint8_t) t;
88086 				break;
88087 			}
88088 
88089 			DUK_DDD(DUK_DDDPRINT("wraps, carry to next digit"));
88090 		}
88091 	}
88092 
88093 	return ret;
88094 }
88095 
88096 #define DUK__NO_EXP  (65536)  /* arbitrary marker, outside valid exp range */
88097 
88098 DUK_LOCAL void duk__dragon4_convert_and_push(duk__numconv_stringify_ctx *nc_ctx,
88099                                              duk_hthread *thr,
88100                                              duk_small_int_t radix,
88101                                              duk_small_int_t digits,
88102                                              duk_small_uint_t flags,
88103                                              duk_small_int_t neg) {
88104 	duk_small_int_t k;
88105 	duk_small_int_t pos, pos_end;
88106 	duk_small_int_t expt;
88107 	duk_small_int_t dig;
88108 	duk_uint8_t *q;
88109 	duk_uint8_t *buf;
88110 
88111 	/*
88112 	 *  The string conversion here incorporates all the necessary ECMAScript
88113 	 *  semantics without attempting to be generic.  nc_ctx->digits contains
88114 	 *  nc_ctx->count digits (>= 1), with the topmost digit's 'position'
88115 	 *  indicated by nc_ctx->k as follows:
88116 	 *
88117 	 *    digits="123" count=3 k=0   -->   0.123
88118 	 *    digits="123" count=3 k=1   -->   1.23
88119 	 *    digits="123" count=3 k=5   -->   12300
88120 	 *    digits="123" count=3 k=-1  -->   0.0123
88121 	 *
88122 	 *  Note that the identifier names used for format selection are different
88123 	 *  in Burger-Dybvig paper and ECMAScript specification (quite confusingly
88124 	 *  so, because e.g. 'k' has a totally different meaning in each).  See
88125 	 *  documentation for discussion.
88126 	 *
88127 	 *  ECMAScript doesn't specify any specific behavior for format selection
88128 	 *  (e.g. when to use exponent notation) for non-base-10 numbers.
88129 	 *
88130 	 *  The bigint space in the context is reused for string output, as there
88131 	 *  is more than enough space for that (>1kB at the moment), and we avoid
88132 	 *  allocating even more stack.
88133 	 */
88134 
88135 	DUK_ASSERT(DUK__NUMCONV_CTX_BIGINTS_SIZE >= DUK__MAX_FORMATTED_LENGTH);
88136 	DUK_ASSERT(nc_ctx->count >= 1);
88137 
88138 	k = nc_ctx->k;
88139 	buf = (duk_uint8_t *) &nc_ctx->f;  /* XXX: union would be more correct */
88140 	q = buf;
88141 
88142 	/* Exponent handling: if exponent format is used, record exponent value and
88143 	 * fake k such that one leading digit is generated (e.g. digits=123 -> "1.23").
88144 	 *
88145 	 * toFixed() prevents exponent use; otherwise apply a set of criteria to
88146 	 * match the other API calls (toString(), toPrecision, etc).
88147 	 */
88148 
88149 	expt = DUK__NO_EXP;
88150 	if (!nc_ctx->abs_pos /* toFixed() */) {
88151 		if ((flags & DUK_N2S_FLAG_FORCE_EXP) ||             /* exponential notation forced */
88152 		    ((flags & DUK_N2S_FLAG_NO_ZERO_PAD) &&          /* fixed precision and zero padding would be required */
88153 	             (k - digits >= 1)) ||                          /* (e.g. k=3, digits=2 -> "12X") */
88154 		    ((k > 21 || k <= -6) && (radix == 10))) {       /* toString() conditions */
88155 			DUK_DDD(DUK_DDDPRINT("use exponential notation: k=%ld -> expt=%ld",
88156 			                     (long) k, (long) (k - 1)));
88157 			expt = k - 1;  /* e.g. 12.3 -> digits="123" k=2 -> 1.23e1 */
88158 			k = 1;  /* generate mantissa with a single leading whole number digit */
88159 		}
88160 	}
88161 
88162 	if (neg) {
88163 		*q++ = '-';
88164 	}
88165 
88166 	/* Start position (inclusive) and end position (exclusive) */
88167 	pos = (k >= 1 ? k : 1);
88168 	if (nc_ctx->is_fixed) {
88169 		if (nc_ctx->abs_pos) {
88170 			/* toFixed() */
88171 			pos_end = -digits;
88172 		} else {
88173 			pos_end = k - digits;
88174 		}
88175 	} else {
88176 		pos_end = k - nc_ctx->count;
88177 	}
88178 	if (pos_end > 0) {
88179 		pos_end = 0;
88180 	}
88181 
88182 	DUK_DDD(DUK_DDDPRINT("expt=%ld, k=%ld, count=%ld, pos=%ld, pos_end=%ld, is_fixed=%ld, "
88183 	                     "digits=%ld, abs_pos=%ld",
88184 	                     (long) expt, (long) k, (long) nc_ctx->count, (long) pos, (long) pos_end,
88185 	                     (long) nc_ctx->is_fixed, (long) digits, (long) nc_ctx->abs_pos));
88186 
88187 	/* Digit generation */
88188 	while (pos > pos_end) {
88189 		DUK_DDD(DUK_DDDPRINT("digit generation: pos=%ld, pos_end=%ld",
88190 		                     (long) pos, (long) pos_end));
88191 		if (pos == 0) {
88192 			*q++ = (duk_uint8_t) '.';
88193 		}
88194 		if (pos > k) {
88195 			*q++ = (duk_uint8_t) '0';
88196 		} else if (pos <= k - nc_ctx->count) {
88197 			*q++ = (duk_uint8_t) '0';
88198 		} else {
88199 			dig = nc_ctx->digits[k - pos];
88200 			DUK_ASSERT(dig >= 0 && dig < nc_ctx->B);
88201 			*q++ = (duk_uint8_t) DUK__DIGITCHAR(dig);
88202 		}
88203 
88204 		pos--;
88205 	}
88206 	DUK_ASSERT(pos <= 1);
88207 
88208 	/* Exponent */
88209 	if (expt != DUK__NO_EXP) {
88210 		/*
88211 		 *  Exponent notation for non-base-10 numbers isn't specified in ECMAScript
88212 		 *  specification, as it never explicitly turns up: non-decimal numbers can
88213 		 *  only be formatted with Number.prototype.toString([radix]) and for that,
88214 		 *  behavior is not explicitly specified.
88215 		 *
88216 		 *  Logical choices include formatting the exponent as decimal (e.g. binary
88217 		 *  100000 as 1e+5) or in current radix (e.g. binary 100000 as 1e+101).
88218 		 *  The Dragon4 algorithm (in the original paper) prints the exponent value
88219 		 *  in the target radix B.  However, for radix values 15 and above, the
88220 		 *  exponent separator 'e' is no longer easily parseable.  Consider, for
88221 		 *  instance, the number "1.faecee+1c".
88222 		 */
88223 
88224 		duk_size_t len;
88225 		char expt_sign;
88226 
88227 		*q++ = 'e';
88228 		if (expt >= 0) {
88229 			expt_sign = '+';
88230 		} else {
88231 			expt_sign = '-';
88232 			expt = -expt;
88233 		}
88234 		*q++ = (duk_uint8_t) expt_sign;
88235 		len = duk__dragon4_format_uint32(q, (duk_uint32_t) expt, radix);
88236 		q += len;
88237 	}
88238 
88239 	duk_push_lstring(thr, (const char *) buf, (size_t) (q - buf));
88240 }
88241 
88242 /*
88243  *  Conversion helpers
88244  */
88245 
88246 DUK_LOCAL void duk__dragon4_double_to_ctx(duk__numconv_stringify_ctx *nc_ctx, duk_double_t x) {
88247 	duk_double_union u;
88248 	duk_uint32_t tmp;
88249 	duk_small_int_t expt;
88250 
88251 	/*
88252 	 *    seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
88253 	 *       A        B        C        D        E        F        G        H
88254 	 *
88255 	 *    s       sign bit
88256 	 *    eee...  exponent field
88257 	 *    fff...  fraction
88258 	 *
88259 	 *    ieee value = 1.ffff... * 2^(e - 1023)  (normal)
88260 	 *               = 0.ffff... * 2^(-1022)     (denormal)
88261 	 *
88262 	 *    algorithm v = f * b^e
88263 	 */
88264 
88265 	DUK_DBLUNION_SET_DOUBLE(&u, x);
88266 
88267 	nc_ctx->f.n = 2;
88268 
88269 	tmp = DUK_DBLUNION_GET_LOW32(&u);
88270 	nc_ctx->f.v[0] = tmp;
88271 	tmp = DUK_DBLUNION_GET_HIGH32(&u);
88272 	nc_ctx->f.v[1] = tmp & 0x000fffffUL;
88273 	expt = (duk_small_int_t) ((tmp >> 20) & 0x07ffUL);
88274 
88275 	if (expt == 0) {
88276 		/* denormal */
88277 		expt = DUK__IEEE_DOUBLE_EXP_MIN - 52;
88278 		duk__bi_normalize(&nc_ctx->f);
88279 	} else {
88280 		/* normal: implicit leading 1-bit */
88281 		nc_ctx->f.v[1] |= 0x00100000UL;
88282 		expt = expt - DUK__IEEE_DOUBLE_EXP_BIAS - 52;
88283 		DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f));  /* true, because v[1] has at least one bit set */
88284 	}
88285 
88286 	DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f));
88287 
88288 	nc_ctx->e = expt;
88289 }
88290 
88291 DUK_LOCAL void duk__dragon4_ctx_to_double(duk__numconv_stringify_ctx *nc_ctx, duk_double_t *x) {
88292 	duk_double_union u;
88293 	duk_small_int_t expt;
88294 	duk_small_int_t i;
88295 	duk_small_int_t bitstart;
88296 	duk_small_int_t bitround;
88297 	duk_small_int_t bitidx;
88298 	duk_small_int_t skip_round;
88299 	duk_uint32_t t, v;
88300 
88301 	DUK_ASSERT(nc_ctx->count == 53 + 1);
88302 
88303 	/* Sometimes this assert is not true right now; it will be true after
88304 	 * rounding.  See: test-bug-numconv-mantissa-assert.js.
88305 	 */
88306 	DUK_ASSERT_DISABLE(nc_ctx->digits[0] == 1);  /* zero handled by caller */
88307 
88308 	/* Should not be required because the code below always sets both high
88309 	 * and low parts, but at least gcc-4.4.5 fails to deduce this correctly
88310 	 * (perhaps because the low part is set (seemingly) conditionally in a
88311 	 * loop), so this is here to avoid the bogus warning.
88312 	 */
88313 	duk_memzero((void *) &u, sizeof(u));
88314 
88315 	/*
88316 	 *  Figure out how generated digits match up with the mantissa,
88317 	 *  and then perform rounding.  If mantissa overflows, need to
88318 	 *  recompute the exponent (it is bumped and may overflow to
88319 	 *  infinity).
88320 	 *
88321 	 *  For normal numbers the leading '1' is hidden and ignored,
88322 	 *  and the last bit is used for rounding:
88323 	 *
88324 	 *                          rounding pt
88325 	 *       <--------52------->|
88326 	 *     1 x x x x ... x x x x|y  ==>  x x x x ... x x x x
88327 	 *
88328 	 *  For denormals, the leading '1' is included in the number,
88329 	 *  and the rounding point is different:
88330 	 *
88331 	 *                      rounding pt
88332 	 *     <--52 or less--->|
88333 	 *     1 x x x x ... x x|x x y  ==>  0 0 ... 1 x x ... x x
88334 	 *
88335 	 *  The largest denormals will have a mantissa beginning with
88336 	 *  a '1' (the explicit leading bit); smaller denormals will
88337 	 *  have leading zero bits.
88338 	 *
88339 	 *  If the exponent would become too high, the result becomes
88340 	 *  Infinity.  If the exponent is so small that the entire
88341 	 *  mantissa becomes zero, the result becomes zero.
88342 	 *
88343 	 *  Note: the Dragon4 'k' is off-by-one with respect to the IEEE
88344 	 *  exponent.  For instance, k==0 indicates that the leading '1'
88345 	 *  digit is at the first binary fraction position (0.1xxx...);
88346 	 *  the corresponding IEEE exponent would be -1.
88347 	 */
88348 
88349 	skip_round = 0;
88350 
88351  recheck_exp:
88352 
88353 	expt = nc_ctx->k - 1;   /* IEEE exp without bias */
88354 	if (expt > 1023) {
88355 		/* Infinity */
88356 		bitstart = -255;  /* needed for inf: causes mantissa to become zero,
88357 		                   * and rounding to be skipped.
88358 		                   */
88359 		expt = 2047;
88360 	} else if (expt >= -1022) {
88361 		/* normal */
88362 		bitstart = 1;  /* skip leading digit */
88363 		expt += DUK__IEEE_DOUBLE_EXP_BIAS;
88364 		DUK_ASSERT(expt >= 1 && expt <= 2046);
88365 	} else {
88366 		/* denormal or zero */
88367 		bitstart = 1023 + expt;  /* expt==-1023 -> bitstart=0 (leading 1);
88368 		                          * expt==-1024 -> bitstart=-1 (one left of leading 1), etc
88369 		                          */
88370 		expt = 0;
88371 	}
88372 	bitround = bitstart + 52;
88373 
88374 	DUK_DDD(DUK_DDDPRINT("ieee expt=%ld, bitstart=%ld, bitround=%ld",
88375 	                     (long) expt, (long) bitstart, (long) bitround));
88376 
88377 	if (!skip_round) {
88378 		if (duk__dragon4_fixed_format_round(nc_ctx, bitround)) {
88379 			/* Corner case: see test-numconv-parse-mant-carry.js.  We could
88380 			 * just bump the exponent and update bitstart, but it's more robust
88381 			 * to recompute (but avoid rounding twice).
88382 			 */
88383 			DUK_DDD(DUK_DDDPRINT("rounding caused exponent to be bumped, recheck exponent"));
88384 			skip_round = 1;
88385 			goto recheck_exp;
88386 		}
88387 	}
88388 
88389 	/*
88390 	 *  Create mantissa
88391 	 */
88392 
88393 	t = 0;
88394 	for (i = 0; i < 52; i++) {
88395 		bitidx = bitstart + 52 - 1 - i;
88396 		if (bitidx >= nc_ctx->count) {
88397 			v = 0;
88398 		} else if (bitidx < 0) {
88399 			v = 0;
88400 		} else {
88401 			v = nc_ctx->digits[bitidx];
88402 		}
88403 		DUK_ASSERT(v == 0 || v == 1);
88404 		t += v << (i % 32);
88405 		if (i == 31) {
88406 			/* low 32 bits is complete */
88407 			DUK_DBLUNION_SET_LOW32(&u, t);
88408 			t = 0;
88409 		}
88410 	}
88411 	/* t has high mantissa */
88412 
88413 	DUK_DDD(DUK_DDDPRINT("mantissa is complete: %08lx %08lx",
88414 	                     (unsigned long) t,
88415 	                     (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));
88416 
88417 	DUK_ASSERT(expt >= 0 && expt <= 0x7ffL);
88418 	t += ((duk_uint32_t) expt) << 20;
88419 #if 0  /* caller handles sign change */
88420 	if (negative) {
88421 		t |= 0x80000000U;
88422 	}
88423 #endif
88424 	DUK_DBLUNION_SET_HIGH32(&u, t);
88425 
88426 	DUK_DDD(DUK_DDDPRINT("number is complete: %08lx %08lx",
88427 	                     (unsigned long) DUK_DBLUNION_GET_HIGH32(&u),
88428 	                     (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));
88429 
88430 	*x = DUK_DBLUNION_GET_DOUBLE(&u);
88431 }
88432 
88433 /*
88434  *  Exposed number-to-string API
88435  *
88436  *  Input: [ number ]
88437  *  Output: [ string ]
88438  */
88439 
88440 DUK_LOCAL DUK_NOINLINE void duk__numconv_stringify_raw(duk_hthread *thr, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags) {
88441 	duk_double_t x;
88442 	duk_small_int_t c;
88443 	duk_small_int_t neg;
88444 	duk_uint32_t uval;
88445 	duk__numconv_stringify_ctx nc_ctx_alloc;  /* large context; around 2kB now */
88446 	duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;
88447 
88448 	x = (duk_double_t) duk_require_number(thr, -1);
88449 	duk_pop(thr);
88450 
88451 	/*
88452 	 *  Handle special cases (NaN, infinity, zero).
88453 	 */
88454 
88455 	c = (duk_small_int_t) DUK_FPCLASSIFY(x);
88456 	if (DUK_SIGNBIT((double) x)) {
88457 		x = -x;
88458 		neg = 1;
88459 	} else {
88460 		neg = 0;
88461 	}
88462 
88463 	/* NaN sign bit is platform specific with unpacked, un-normalized NaNs */
88464 	DUK_ASSERT(c == DUK_FP_NAN || DUK_SIGNBIT((double) x) == 0);
88465 
88466 	if (c == DUK_FP_NAN) {
88467 		duk_push_hstring_stridx(thr, DUK_STRIDX_NAN);
88468 		return;
88469 	} else if (c == DUK_FP_INFINITE) {
88470 		if (neg) {
88471 			/* -Infinity */
88472 			duk_push_hstring_stridx(thr, DUK_STRIDX_MINUS_INFINITY);
88473 		} else {
88474 			/* Infinity */
88475 			duk_push_hstring_stridx(thr, DUK_STRIDX_INFINITY);
88476 		}
88477 		return;
88478 	} else if (c == DUK_FP_ZERO) {
88479 		/* We can't shortcut zero here if it goes through special formatting
88480 		 * (such as forced exponential notation).
88481 		 */
88482 		;
88483 	}
88484 
88485 	/*
88486 	 *  Handle integers in 32-bit range (that is, [-(2**32-1),2**32-1])
88487 	 *  specially, as they're very likely for embedded programs.  This
88488 	 *  is now done for all radix values.  We must be careful not to use
88489 	 *  the fast path when special formatting (e.g. forced exponential)
88490 	 *  is in force.
88491 	 *
88492 	 *  XXX: could save space by supporting radix 10 only and using
88493 	 *  sprintf "%lu" for the fast path and for exponent formatting.
88494 	 */
88495 
88496 	uval = duk_double_to_uint32_t(x);
88497 	if (duk_double_equals((double) uval, x) &&  /* integer number in range */
88498 	    flags == 0) {                           /* no special formatting */
88499 		/* use bigint area as a temp */
88500 		duk_uint8_t *buf = (duk_uint8_t *) (&nc_ctx->f);
88501 		duk_uint8_t *p = buf;
88502 
88503 		DUK_ASSERT(DUK__NUMCONV_CTX_BIGINTS_SIZE >= 32 + 1);  /* max size: radix=2 + sign */
88504 		if (neg && uval != 0) {
88505 			/* no negative sign for zero */
88506 			*p++ = (duk_uint8_t) '-';
88507 		}
88508 		p += duk__dragon4_format_uint32(p, uval, radix);
88509 		duk_push_lstring(thr, (const char *) buf, (duk_size_t) (p - buf));
88510 		return;
88511 	}
88512 
88513 	/*
88514 	 *  Dragon4 setup.
88515 	 *
88516 	 *  Convert double from IEEE representation for conversion;
88517 	 *  normal finite values have an implicit leading 1-bit.  The
88518 	 *  slow path algorithm doesn't handle zero, so zero is special
88519 	 *  cased here but still creates a valid nc_ctx, and goes
88520 	 *  through normal formatting in case special formatting has
88521 	 *  been requested (e.g. forced exponential format: 0 -> "0e+0").
88522 	 */
88523 
88524 	/* Would be nice to bulk clear the allocation, but the context
88525 	 * is 1-2 kilobytes and nothing should rely on it being zeroed.
88526 	 */
88527 #if 0
88528 	duk_memzero((void *) nc_ctx, sizeof(*nc_ctx));  /* slow init, do only for slow path cases */
88529 #endif
88530 
88531 	nc_ctx->is_s2n = 0;
88532 	nc_ctx->b = 2;
88533 	nc_ctx->B = radix;
88534 	nc_ctx->abs_pos = 0;
88535 	if (flags & DUK_N2S_FLAG_FIXED_FORMAT) {
88536 		nc_ctx->is_fixed = 1;
88537 		if (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {
88538 			/* absolute req_digits; e.g. digits = 1 -> last digit is 0,
88539 			 * but add an extra digit for rounding.
88540 			 */
88541 			nc_ctx->abs_pos = 1;
88542 			nc_ctx->req_digits = (-digits + 1) - 1;
88543 		} else {
88544 			nc_ctx->req_digits = digits + 1;
88545 		}
88546 	} else {
88547 		nc_ctx->is_fixed = 0;
88548 		nc_ctx->req_digits = 0;
88549 	}
88550 
88551 	if (c == DUK_FP_ZERO) {
88552 		/* Zero special case: fake requested number of zero digits; ensure
88553 		 * no sign bit is printed.  Relative and absolute fixed format
88554 		 * require separate handling.
88555 		 */
88556 		duk_small_int_t count;
88557 		if (nc_ctx->is_fixed) {
88558 			if (nc_ctx->abs_pos) {
88559 				count = digits + 2;  /* lead zero + 'digits' fractions + 1 for rounding */
88560 			} else {
88561 				count = digits + 1;  /* + 1 for rounding */
88562 			}
88563 		} else {
88564 			count = 1;
88565 		}
88566 		DUK_DDD(DUK_DDDPRINT("count=%ld", (long) count));
88567 		DUK_ASSERT(count >= 1);
88568 		duk_memzero((void *) nc_ctx->digits, (size_t) count);
88569 		nc_ctx->count = count;
88570 		nc_ctx->k = 1;  /* 0.000... */
88571 		neg = 0;
88572 		goto zero_skip;
88573 	}
88574 
88575 	duk__dragon4_double_to_ctx(nc_ctx, x);   /* -> sets 'f' and 'e' */
88576 	DUK__BI_PRINT("f", &nc_ctx->f);
88577 	DUK_DDD(DUK_DDDPRINT("e=%ld", (long) nc_ctx->e));
88578 
88579 	/*
88580 	 *  Dragon4 slow path digit generation.
88581 	 */
88582 
88583 	duk__dragon4_prepare(nc_ctx);  /* setup many variables in nc_ctx */
88584 
88585 	DUK_DDD(DUK_DDDPRINT("after prepare:"));
88586 	DUK__BI_PRINT("r", &nc_ctx->r);
88587 	DUK__BI_PRINT("s", &nc_ctx->s);
88588 	DUK__BI_PRINT("mp", &nc_ctx->mp);
88589 	DUK__BI_PRINT("mm", &nc_ctx->mm);
88590 
88591 	duk__dragon4_scale(nc_ctx);
88592 
88593 	DUK_DDD(DUK_DDDPRINT("after scale; k=%ld", (long) nc_ctx->k));
88594 	DUK__BI_PRINT("r", &nc_ctx->r);
88595 	DUK__BI_PRINT("s", &nc_ctx->s);
88596 	DUK__BI_PRINT("mp", &nc_ctx->mp);
88597 	DUK__BI_PRINT("mm", &nc_ctx->mm);
88598 
88599 	duk__dragon4_generate(nc_ctx);
88600 
88601 	/*
88602 	 *  Convert and push final string.
88603 	 */
88604 
88605  zero_skip:
88606 
88607 	if (flags & DUK_N2S_FLAG_FIXED_FORMAT) {
88608 		/* Perform fixed-format rounding. */
88609 		duk_small_int_t roundpos;
88610 		if (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {
88611 			/* 'roundpos' is relative to nc_ctx->k and increases to the right
88612 			 * (opposite of how 'k' changes).
88613 			 */
88614 			roundpos = -digits;  /* absolute position for digit considered for rounding */
88615 			roundpos = nc_ctx->k - roundpos;
88616 		} else {
88617 			roundpos = digits;
88618 		}
88619 		DUK_DDD(DUK_DDDPRINT("rounding: k=%ld, count=%ld, digits=%ld, roundpos=%ld",
88620 		                     (long) nc_ctx->k, (long) nc_ctx->count, (long) digits, (long) roundpos));
88621 		(void) duk__dragon4_fixed_format_round(nc_ctx, roundpos);
88622 
88623 		/* Note: 'count' is currently not adjusted by rounding (i.e. the
88624 		 * digits are not "chopped off".  That shouldn't matter because
88625 		 * the digit position (absolute or relative) is passed on to the
88626 		 * convert-and-push function.
88627 		 */
88628 	}
88629 
88630 	duk__dragon4_convert_and_push(nc_ctx, thr, radix, digits, flags, neg);
88631 }
88632 
88633 DUK_INTERNAL void duk_numconv_stringify(duk_hthread *thr, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags) {
88634 	duk_native_stack_check(thr);
88635 	duk__numconv_stringify_raw(thr, radix, digits, flags);
88636 }
88637 
88638 /*
88639  *  Exposed string-to-number API
88640  *
88641  *  Input: [ string ]
88642  *  Output: [ number ]
88643  *
88644  *  If number parsing fails, a NaN is pushed as the result.  If number parsing
88645  *  fails due to an internal error, an InternalError is thrown.
88646  */
88647 
88648 DUK_LOCAL DUK_NOINLINE void duk__numconv_parse_raw(duk_hthread *thr, duk_small_int_t radix, duk_small_uint_t flags) {
88649 	duk__numconv_stringify_ctx nc_ctx_alloc;  /* large context; around 2kB now */
88650 	duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;
88651 	duk_double_t res;
88652 	duk_hstring *h_str;
88653 	duk_int_t expt;
88654 	duk_bool_t expt_neg;
88655 	duk_small_int_t expt_adj;
88656 	duk_small_int_t neg;
88657 	duk_small_int_t dig;
88658 	duk_small_int_t dig_whole;
88659 	duk_small_int_t dig_lzero;
88660 	duk_small_int_t dig_frac;
88661 	duk_small_int_t dig_expt;
88662 	duk_small_int_t dig_prec;
88663 	const duk__exp_limits *explim;
88664 	const duk_uint8_t *p;
88665 	duk_small_int_t ch;
88666 
88667 	DUK_DDD(DUK_DDDPRINT("parse number: %!T, radix=%ld, flags=0x%08lx",
88668 	                     (duk_tval *) duk_get_tval(thr, -1),
88669 	                     (long) radix, (unsigned long) flags));
88670 
88671 	DUK_ASSERT(radix >= 2 && radix <= 36);
88672 	DUK_ASSERT(radix - 2 < (duk_small_int_t) sizeof(duk__str2num_digits_for_radix));
88673 
88674 	/*
88675 	 *  Preliminaries: trim, sign, Infinity check
88676 	 *
88677 	 *  We rely on the interned string having a NUL terminator, which will
88678 	 *  cause a parse failure wherever it is encountered.  As a result, we
88679 	 *  don't need separate pointer checks.
88680 	 *
88681 	 *  There is no special parsing for 'NaN' in the specification although
88682 	 *  'Infinity' (with an optional sign) is allowed in some contexts.
88683 	 *  Some contexts allow plus/minus sign, while others only allow the
88684 	 *  minus sign (like JSON.parse()).
88685 	 *
88686 	 *  Automatic hex number detection (leading '0x' or '0X') and octal
88687 	 *  number detection (leading '0' followed by at least one octal digit)
88688 	 *  is done here too.
88689 	 *
88690 	 *  Symbols are not explicitly rejected here (that's up to the caller).
88691 	 *  If a symbol were passed here, it should ultimately safely fail
88692 	 *  parsing due to a syntax error.
88693 	 */
88694 
88695 	if (flags & DUK_S2N_FLAG_TRIM_WHITE) {
88696 		/* Leading / trailing whitespace is sometimes accepted and
88697 		 * sometimes not.  After white space trimming, all valid input
88698 		 * characters are pure ASCII.
88699 		 */
88700 		duk_trim(thr, -1);
88701 	}
88702 	h_str = duk_require_hstring(thr, -1);
88703 	DUK_ASSERT(h_str != NULL);
88704 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_str);
88705 
88706 	neg = 0;
88707 	ch = *p;
88708 	if (ch == (duk_small_int_t) '+') {
88709 		if ((flags & DUK_S2N_FLAG_ALLOW_PLUS) == 0) {
88710 			DUK_DDD(DUK_DDDPRINT("parse failed: leading plus sign not allowed"));
88711 			goto parse_fail;
88712 		}
88713 		p++;
88714 	} else if (ch == (duk_small_int_t) '-') {
88715 		if ((flags & DUK_S2N_FLAG_ALLOW_MINUS) == 0) {
88716 			DUK_DDD(DUK_DDDPRINT("parse failed: leading minus sign not allowed"));
88717 			goto parse_fail;
88718 		}
88719 		p++;
88720 		neg = 1;
88721 	}
88722 
88723 	if ((flags & DUK_S2N_FLAG_ALLOW_INF) && DUK_STRNCMP((const char *) p, "Infinity", 8) == 0) {
88724 		/* Don't check for Infinity unless the context allows it.
88725 		 * 'Infinity' is a valid integer literal in e.g. base-36:
88726 		 *
88727 		 *   parseInt('Infinity', 36)
88728 		 *   1461559270678
88729 		 */
88730 
88731 		if ((flags & DUK_S2N_FLAG_ALLOW_GARBAGE) == 0 && p[8] != DUK_ASC_NUL) {
88732 			DUK_DDD(DUK_DDDPRINT("parse failed: trailing garbage after matching 'Infinity' not allowed"));
88733 			goto parse_fail;
88734 		} else {
88735 			res = DUK_DOUBLE_INFINITY;
88736 			goto negcheck_and_ret;
88737 		}
88738 	}
88739 	ch = *p;
88740 	if (ch == (duk_small_int_t) '0') {
88741 		duk_small_int_t detect_radix = 0;
88742 		ch = DUK_LOWERCASE_CHAR_ASCII(p[1]);  /* 'x' or 'X' -> 'x' */
88743 		if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT) && ch == DUK_ASC_LC_X) {
88744 			DUK_DDD(DUK_DDDPRINT("detected 0x/0X hex prefix, changing radix and preventing fractions and exponent"));
88745 			detect_radix = 16;
88746 #if 0
88747 		} else if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_LEGACY_OCT_INT) &&
88748 		           (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9')) {
88749 			DUK_DDD(DUK_DDDPRINT("detected 0n oct prefix, changing radix and preventing fractions and exponent"));
88750 			detect_radix = 8;
88751 
88752 			/* NOTE: if this legacy octal case is added back, it has
88753 			 * different flags and 'p' advance so this needs to be
88754 			 * reworked.
88755 			 */
88756 			flags |= DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO;  /* interpret e.g. '09' as '0', not NaN */
88757 			p += 1;
88758 #endif
88759 		} else if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT) && ch == DUK_ASC_LC_O) {
88760 			DUK_DDD(DUK_DDDPRINT("detected 0o oct prefix, changing radix and preventing fractions and exponent"));
88761 			detect_radix = 8;
88762 		} else if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT) && ch == DUK_ASC_LC_B) {
88763 			DUK_DDD(DUK_DDDPRINT("detected 0b bin prefix, changing radix and preventing fractions and exponent"));
88764 			detect_radix = 2;
88765 		}
88766 		if (detect_radix > 0) {
88767 			radix = detect_radix;
88768 			/* Clear empty as zero flag: interpret e.g. '0x' and '0xg' as a NaN (= parse error) */
88769 			flags &= ~(DUK_S2N_FLAG_ALLOW_EXP | DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
88770 			           DUK_S2N_FLAG_ALLOW_FRAC | DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
88771 			           DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO);
88772 			flags |= DUK_S2N_FLAG_ALLOW_LEADING_ZERO;  /* allow e.g. '0x0009' and '0b00010001' */
88773 			p += 2;
88774 		}
88775 	}
88776 
88777 	/*
88778 	 *  Scan number and setup for Dragon4.
88779 	 *
88780 	 *  The fast path case is detected during setup: an integer which
88781 	 *  can be converted without rounding, no net exponent.  The fast
88782 	 *  path could be implemented as a separate scan, but may not really
88783 	 *  be worth it: the multiplications for building 'f' are not
88784 	 *  expensive when 'f' is small.
88785 	 *
88786 	 *  The significand ('f') must contain enough bits of (apparent)
88787 	 *  accuracy, so that Dragon4 will generate enough binary output digits.
88788 	 *  For decimal numbers, this means generating a 20-digit significand,
88789 	 *  which should yield enough practical accuracy to parse IEEE doubles.
88790 	 *  In fact, the ECMAScript specification explicitly allows an
88791 	 *  implementation to treat digits beyond 20 as zeroes (and even
88792 	 *  to round the 20th digit upwards).  For non-decimal numbers, the
88793 	 *  appropriate number of digits has been precomputed for comparable
88794 	 *  accuracy.
88795 	 *
88796 	 *  Digit counts:
88797 	 *
88798 	 *    [ dig_lzero ]
88799 	 *      |
88800 	 *     .+-..---[ dig_prec ]----.
88801 	 *     |  ||                   |
88802 	 *     0000123.456789012345678901234567890e+123456
88803 	 *     |     | |                         |  |    |
88804 	 *     `--+--' `------[ dig_frac ]-------'  `-+--'
88805 	 *        |                                   |
88806 	 *    [ dig_whole ]                       [ dig_expt ]
88807 	 *
88808 	 *    dig_frac and dig_expt are -1 if not present
88809 	 *    dig_lzero is only computed for whole number part
88810 	 *
88811 	 *  Parsing state
88812 	 *
88813 	 *     Parsing whole part      dig_frac < 0 AND dig_expt < 0
88814 	 *     Parsing fraction part   dig_frac >= 0 AND dig_expt < 0
88815 	 *     Parsing exponent part   dig_expt >= 0   (dig_frac may be < 0 or >= 0)
88816 	 *
88817 	 *  Note: in case we hit an implementation limit (like exponent range),
88818 	 *  we should throw an error, NOT return NaN or Infinity.  Even with
88819 	 *  very large exponent (or significand) values the final result may be
88820 	 *  finite, so NaN/Infinity would be incorrect.
88821 	 */
88822 
88823 	duk__bi_set_small(&nc_ctx->f, 0);
88824 	dig_prec = 0;
88825 	dig_lzero = 0;
88826 	dig_whole = 0;
88827 	dig_frac = -1;
88828 	dig_expt = -1;
88829 	expt = 0;
88830 	expt_adj = 0;  /* essentially tracks digit position of lowest 'f' digit */
88831 	expt_neg = 0;
88832 	for (;;) {
88833 		ch = *p++;
88834 
88835 		DUK_DDD(DUK_DDDPRINT("parse digits: p=%p, ch='%c' (%ld), expt=%ld, expt_adj=%ld, "
88836 		                     "dig_whole=%ld, dig_frac=%ld, dig_expt=%ld, dig_lzero=%ld, dig_prec=%ld",
88837 		                     (const void *) p, (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : '?'), (long) ch,
88838 		                     (long) expt, (long) expt_adj, (long) dig_whole, (long) dig_frac,
88839 		                     (long) dig_expt, (long) dig_lzero, (long) dig_prec));
88840 		DUK__BI_PRINT("f", &nc_ctx->f);
88841 
88842 		/* Most common cases first. */
88843 		if (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9') {
88844 			dig = (duk_small_int_t) ch - '0' + 0;
88845 		} else if (ch == (duk_small_int_t) '.') {
88846 			/* A leading digit is not required in some cases, e.g. accept ".123".
88847 			 * In other cases (JSON.parse()) a leading digit is required.  This
88848 			 * is checked for after the loop.
88849 			 */
88850 			if (dig_frac >= 0 || dig_expt >= 0) {
88851 				if (flags & DUK_S2N_FLAG_ALLOW_GARBAGE) {
88852 					DUK_DDD(DUK_DDDPRINT("garbage termination (invalid period)"));
88853 					break;
88854 				} else {
88855 					DUK_DDD(DUK_DDDPRINT("parse failed: period not allowed"));
88856 					goto parse_fail;
88857 				}
88858 			}
88859 
88860 			if ((flags & DUK_S2N_FLAG_ALLOW_FRAC) == 0) {
88861 				/* Some contexts don't allow fractions at all; this can't be a
88862 				 * post-check because the state ('f' and expt) would be incorrect.
88863 				 */
88864 				if (flags & DUK_S2N_FLAG_ALLOW_GARBAGE) {
88865 					DUK_DDD(DUK_DDDPRINT("garbage termination (invalid first period)"));
88866 					break;
88867 				} else {
88868 					DUK_DDD(DUK_DDDPRINT("parse failed: fraction part not allowed"));
88869 				}
88870 			}
88871 
88872 			DUK_DDD(DUK_DDDPRINT("start fraction part"));
88873 			dig_frac = 0;
88874 			continue;
88875 		} else if (ch == (duk_small_int_t) 0) {
88876 			DUK_DDD(DUK_DDDPRINT("NUL termination"));
88877 			break;
88878 		} else if ((flags & DUK_S2N_FLAG_ALLOW_EXP) &&
88879 		           dig_expt < 0 && (ch == (duk_small_int_t) 'e' || ch == (duk_small_int_t) 'E')) {
88880 			/* Note: we don't parse back exponent notation for anything else
88881 			 * than radix 10, so this is not an ambiguous check (e.g. hex
88882 			 * exponent values may have 'e' either as a significand digit
88883 			 * or as an exponent separator).
88884 			 *
88885 			 * If the exponent separator occurs twice, 'e' will be interpreted
88886 			 * as a digit (= 14) and will be rejected as an invalid decimal
88887 			 * digit.
88888 			 */
88889 
88890 			DUK_DDD(DUK_DDDPRINT("start exponent part"));
88891 
88892 			/* Exponent without a sign or with a +/- sign is accepted
88893 			 * by all call sites (even JSON.parse()).
88894 			 */
88895 			ch = *p;
88896 			if (ch == (duk_small_int_t) '-') {
88897 				expt_neg = 1;
88898 				p++;
88899 			} else if (ch == (duk_small_int_t) '+') {
88900 				p++;
88901 			}
88902 			dig_expt = 0;
88903 			continue;
88904 		} else if (ch >= (duk_small_int_t) 'a' && ch <= (duk_small_int_t) 'z') {
88905 			dig = (duk_small_int_t) (ch - (duk_small_int_t) 'a' + 0x0a);
88906 		} else if (ch >= (duk_small_int_t) 'A' && ch <= (duk_small_int_t) 'Z') {
88907 			dig = (duk_small_int_t) (ch - (duk_small_int_t) 'A' + 0x0a);
88908 		} else {
88909 			dig = 255;  /* triggers garbage digit check below */
88910 		}
88911 		DUK_ASSERT((dig >= 0 && dig <= 35) || dig == 255);
88912 
88913 		if (dig >= radix) {
88914 			if (flags & DUK_S2N_FLAG_ALLOW_GARBAGE) {
88915 				DUK_DDD(DUK_DDDPRINT("garbage termination"));
88916 				break;
88917 			} else {
88918 				DUK_DDD(DUK_DDDPRINT("parse failed: trailing garbage or invalid digit"));
88919 				goto parse_fail;
88920 			}
88921 		}
88922 
88923 		if (dig_expt < 0) {
88924 			/* whole or fraction digit */
88925 
88926 			if (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {
88927 				/* significant from precision perspective */
88928 
88929 				duk_small_int_t f_zero = duk__bi_is_zero(&nc_ctx->f);
88930 				if (f_zero && dig == 0) {
88931 					/* Leading zero is not counted towards precision digits; not
88932 					 * in the integer part, nor in the fraction part.
88933 					 */
88934 					if (dig_frac < 0) {
88935 						dig_lzero++;
88936 					}
88937 				} else {
88938 					/* XXX: join these ops (multiply-accumulate), but only if
88939 					 * code footprint decreases.
88940 					 */
88941 					duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, (duk_uint32_t) radix);
88942 					duk__bi_add_small(&nc_ctx->f, &nc_ctx->t1, (duk_uint32_t) dig);
88943 					dig_prec++;
88944 				}
88945 			} else {
88946 				/* Ignore digits beyond a radix-specific limit, but note them
88947 				 * in expt_adj.
88948 				 */
88949 				expt_adj++;
88950 			}
88951 
88952 			if (dig_frac >= 0) {
88953 				dig_frac++;
88954 				expt_adj--;
88955 			} else {
88956 				dig_whole++;
88957 			}
88958 		} else {
88959 			/* exponent digit */
88960 
88961 			DUK_ASSERT(radix == 10);
88962 			expt = expt * radix + dig;
88963 			if (expt > DUK_S2N_MAX_EXPONENT) {
88964 				/* Impose a reasonable exponent limit, so that exp
88965 				 * doesn't need to get tracked using a bigint.
88966 				 */
88967 				DUK_DDD(DUK_DDDPRINT("parse failed: exponent too large"));
88968 				goto parse_explimit_error;
88969 			}
88970 			dig_expt++;
88971 		}
88972 	}
88973 
88974 	/* Leading zero. */
88975 
88976 	if (dig_lzero > 0 && dig_whole > 1) {
88977 		if ((flags & DUK_S2N_FLAG_ALLOW_LEADING_ZERO) == 0) {
88978 			DUK_DDD(DUK_DDDPRINT("parse failed: leading zeroes not allowed in integer part"));
88979 			goto parse_fail;
88980 		}
88981 	}
88982 
88983 	/* Validity checks for various fraction formats ("0.1", ".1", "1.", "."). */
88984 
88985 	if (dig_whole == 0) {
88986 		if (dig_frac == 0) {
88987 			/* "." is not accepted in any format */
88988 			DUK_DDD(DUK_DDDPRINT("parse failed: plain period without leading or trailing digits"));
88989 			goto parse_fail;
88990 		} else if (dig_frac > 0) {
88991 			/* ".123" */
88992 			if ((flags & DUK_S2N_FLAG_ALLOW_NAKED_FRAC) == 0) {
88993 				DUK_DDD(DUK_DDDPRINT("parse failed: fraction part not allowed without "
88994 				                     "leading integer digit(s)"));
88995 				goto parse_fail;
88996 			}
88997 		} else {
88998 			/* Empty ("") is allowed in some formats (e.g. Number(''), as zero,
88999 			 * but it must not have a leading +/- sign (GH-2019).  Note that
89000 			 * for Number(), h_str is already trimmed so we can check for zero
89001 			 * length and still get Number('  +  ') == NaN.
89002 			 */
89003 			if ((flags & DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO) == 0) {
89004 				DUK_DDD(DUK_DDDPRINT("parse failed: empty string not allowed (as zero)"));
89005 				goto parse_fail;
89006 			} else if (DUK_HSTRING_GET_BYTELEN(h_str) != 0) {
89007 				DUK_DDD(DUK_DDDPRINT("parse failed: no digits, but not empty (had a +/- sign)"));
89008 				goto parse_fail;
89009 			}
89010 		}
89011 	} else {
89012 		if (dig_frac == 0) {
89013 			/* "123." is allowed in some formats */
89014 			if ((flags & DUK_S2N_FLAG_ALLOW_EMPTY_FRAC) == 0) {
89015 				DUK_DDD(DUK_DDDPRINT("parse failed: empty fractions"));
89016 				goto parse_fail;
89017 			}
89018 		} else if (dig_frac > 0) {
89019 			/* "123.456" */
89020 			;
89021 		} else {
89022 			/* "123" */
89023 			;
89024 		}
89025 	}
89026 
89027 	/* Exponent without digits (e.g. "1e" or "1e+").  If trailing garbage is
89028 	 * allowed, ignore exponent part as garbage (= parse as "1", i.e. exp 0).
89029 	 */
89030 
89031 	if (dig_expt == 0) {
89032 		if ((flags & DUK_S2N_FLAG_ALLOW_GARBAGE) == 0) {
89033 			DUK_DDD(DUK_DDDPRINT("parse failed: empty exponent"));
89034 			goto parse_fail;
89035 		}
89036 		DUK_ASSERT(expt == 0);
89037 	}
89038 
89039 	if (expt_neg) {
89040 		expt = -expt;
89041 	}
89042 	DUK_DDD(DUK_DDDPRINT("expt=%ld, expt_adj=%ld, net exponent -> %ld",
89043 	                     (long) expt, (long) expt_adj, (long) (expt + expt_adj)));
89044 	expt += expt_adj;
89045 
89046 	/* Fast path check. */
89047 
89048 	if (nc_ctx->f.n <= 1 &&   /* 32-bit value */
89049 	    expt == 0    /* no net exponent */) {
89050 		/* Fast path is triggered for no exponent and also for balanced exponent
89051 		 * and fraction parts, e.g. for "1.23e2" == "123".  Remember to respect
89052 		 * zero sign.
89053 		 */
89054 
89055 		/* XXX: could accept numbers larger than 32 bits, e.g. up to 53 bits? */
89056 		DUK_DDD(DUK_DDDPRINT("fast path number parse"));
89057 		if (nc_ctx->f.n == 1) {
89058 			res = (double) nc_ctx->f.v[0];
89059 		} else {
89060 			res = 0.0;
89061 		}
89062 		goto negcheck_and_ret;
89063 	}
89064 
89065 	/* Significand ('f') padding. */
89066 
89067 	while (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {
89068 		/* Pad significand with "virtual" zero digits so that Dragon4 will
89069 		 * have enough (apparent) precision to work with.
89070 		 */
89071 		DUK_DDD(DUK_DDDPRINT("dig_prec=%ld, pad significand with zero", (long) dig_prec));
89072 		duk__bi_mul_small_copy(&nc_ctx->f, (duk_uint32_t) radix, &nc_ctx->t1);
89073 		DUK__BI_PRINT("f", &nc_ctx->f);
89074 		expt--;
89075 		dig_prec++;
89076 	}
89077 
89078 	DUK_DDD(DUK_DDDPRINT("final exponent: %ld", (long) expt));
89079 
89080 	/* Detect zero special case. */
89081 
89082 	if (nc_ctx->f.n == 0) {
89083 		/* This may happen even after the fast path check, if exponent is
89084 		 * not balanced (e.g. "0e1").  Remember to respect zero sign.
89085 		 */
89086 		DUK_DDD(DUK_DDDPRINT("significand is zero"));
89087 		res = 0.0;
89088 		goto negcheck_and_ret;
89089 	}
89090 
89091 
89092 	/* Quick reject of too large or too small exponents.  This check
89093 	 * would be incorrect for zero (e.g. "0e1000" is zero, not Infinity)
89094 	 * so zero check must be above.
89095 	 */
89096 
89097 	explim = &duk__str2num_exp_limits[radix - 2];
89098 	if (expt > explim->upper) {
89099 		DUK_DDD(DUK_DDDPRINT("exponent too large -> infinite"));
89100 		res = (duk_double_t) DUK_DOUBLE_INFINITY;
89101 		goto negcheck_and_ret;
89102 	} else if (expt < explim->lower) {
89103 		DUK_DDD(DUK_DDDPRINT("exponent too small -> zero"));
89104 		res = (duk_double_t) 0.0;
89105 		goto negcheck_and_ret;
89106 	}
89107 
89108 	nc_ctx->is_s2n = 1;
89109 	nc_ctx->e = expt;
89110 	nc_ctx->b = radix;
89111 	nc_ctx->B = 2;
89112 	nc_ctx->is_fixed = 1;
89113 	nc_ctx->abs_pos = 0;
89114 	nc_ctx->req_digits = 53 + 1;
89115 
89116 	DUK__BI_PRINT("f", &nc_ctx->f);
89117 	DUK_DDD(DUK_DDDPRINT("e=%ld", (long) nc_ctx->e));
89118 
89119 	/*
89120 	 *  Dragon4 slow path (binary) digit generation.
89121 	 *  An extra digit is generated for rounding.
89122 	 */
89123 
89124 	duk__dragon4_prepare(nc_ctx);  /* setup many variables in nc_ctx */
89125 
89126 	DUK_DDD(DUK_DDDPRINT("after prepare:"));
89127 	DUK__BI_PRINT("r", &nc_ctx->r);
89128 	DUK__BI_PRINT("s", &nc_ctx->s);
89129 	DUK__BI_PRINT("mp", &nc_ctx->mp);
89130 	DUK__BI_PRINT("mm", &nc_ctx->mm);
89131 
89132 	duk__dragon4_scale(nc_ctx);
89133 
89134 	DUK_DDD(DUK_DDDPRINT("after scale; k=%ld", (long) nc_ctx->k));
89135 	DUK__BI_PRINT("r", &nc_ctx->r);
89136 	DUK__BI_PRINT("s", &nc_ctx->s);
89137 	DUK__BI_PRINT("mp", &nc_ctx->mp);
89138 	DUK__BI_PRINT("mm", &nc_ctx->mm);
89139 
89140 	duk__dragon4_generate(nc_ctx);
89141 
89142 	DUK_ASSERT(nc_ctx->count == 53 + 1);
89143 
89144 	/*
89145 	 *  Convert binary digits into an IEEE double.  Need to handle
89146 	 *  denormals and rounding correctly.
89147 	 *
89148 	 *  Some call sites currently assume the result is always a
89149 	 *  non-fastint double.  If this is changed, check all call
89150 	 *  sites.
89151 	 */
89152 
89153 	duk__dragon4_ctx_to_double(nc_ctx, &res);
89154 	goto negcheck_and_ret;
89155 
89156  negcheck_and_ret:
89157 	if (neg) {
89158 		res = -res;
89159 	}
89160 	duk_pop(thr);
89161 	duk_push_number(thr, (double) res);
89162 	DUK_DDD(DUK_DDDPRINT("result: %!T", (duk_tval *) duk_get_tval(thr, -1)));
89163 	return;
89164 
89165  parse_fail:
89166 	DUK_DDD(DUK_DDDPRINT("parse failed"));
89167 	duk_pop(thr);
89168 	duk_push_nan(thr);
89169 	return;
89170 
89171  parse_explimit_error:
89172 	DUK_DDD(DUK_DDDPRINT("parse failed, internal error, can't return a value"));
89173 	DUK_ERROR_RANGE(thr, "exponent too large");
89174 	DUK_WO_NORETURN(return;);
89175 }
89176 
89177 DUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk_small_uint_t flags) {
89178 	duk_native_stack_check(thr);
89179 	duk__numconv_parse_raw(thr, radix, flags);
89180 }
89181 
89182 /* automatic undefs */
89183 #undef DUK__BI_MAX_PARTS
89184 #undef DUK__BI_PRINT
89185 #undef DUK__DIGITCHAR
89186 #undef DUK__DRAGON4_OUTPUT_PREINC
89187 #undef DUK__IEEE_DOUBLE_EXP_BIAS
89188 #undef DUK__IEEE_DOUBLE_EXP_MIN
89189 #undef DUK__MAX_FORMATTED_LENGTH
89190 #undef DUK__MAX_OUTPUT_DIGITS
89191 #undef DUK__NO_EXP
89192 #undef DUK__NUMCONV_CTX_BIGINTS_SIZE
89193 #undef DUK__NUMCONV_CTX_NUM_BIGINTS
89194 /*
89195  *  Regexp compilation.
89196  *
89197  *  See doc/regexp.rst for a discussion of the compilation approach and
89198  *  current limitations.
89199  *
89200  *  Regexp bytecode assumes jumps can be expressed with signed 32-bit
89201  *  integers.  Consequently the bytecode size must not exceed 0x7fffffffL.
89202  *  The implementation casts duk_size_t (buffer size) to duk_(u)int32_t
89203  *  in many places.  Although this could be changed, the bytecode format
89204  *  limit would still prevent regexps exceeding the signed 32-bit limit
89205  *  from working.
89206  *
89207  *  XXX: The implementation does not prevent bytecode from exceeding the
89208  *  maximum supported size.  This could be done by limiting the maximum
89209  *  input string size (assuming an upper bound can be computed for number
89210  *  of bytecode bytes emitted per input byte) or checking buffer maximum
89211  *  size when emitting bytecode (slower).
89212  */
89213 
89214 /* #include duk_internal.h -> already included */
89215 
89216 #if defined(DUK_USE_REGEXP_SUPPORT)
89217 
89218 /*
89219  *  Helper macros
89220  */
89221 
89222 #define DUK__RE_INITIAL_BUFSIZE 64
89223 
89224 #define DUK__RE_BUFLEN(re_ctx) \
89225 	DUK_BW_GET_SIZE(re_ctx->thr, &re_ctx->bw)
89226 
89227 /*
89228  *  Disjunction struct: result of parsing a disjunction
89229  */
89230 
89231 typedef struct {
89232 	/* Number of characters that the atom matches (e.g. 3 for 'abc'),
89233 	 * -1 if atom is complex and number of matched characters either
89234 	 * varies or is not known.
89235 	 */
89236 	duk_int32_t charlen;
89237 
89238 #if 0
89239 	/* These are not needed to implement quantifier capture handling,
89240 	 * but might be needed at some point.
89241 	 */
89242 
89243 	/* re_ctx->captures at start and end of atom parsing.
89244 	 * Since 'captures' indicates highest capture number emitted
89245 	 * so far in a DUK_REOP_SAVE, the captures numbers saved by
89246 	 * the atom are: ]start_captures,end_captures].
89247 	 */
89248 	duk_uint32_t start_captures;
89249 	duk_uint32_t end_captures;
89250 #endif
89251 } duk__re_disjunction_info;
89252 
89253 /*
89254  *  Encoding helpers
89255  *
89256  *  Some of the typing is bytecode based, e.g. slice sizes are unsigned 32-bit
89257  *  even though the buffer operations will use duk_size_t.
89258  */
89259 
89260 /* XXX: the insert helpers should ensure that the bytecode result is not
89261  * larger than expected (or at least assert for it).  Many things in the
89262  * bytecode, like skip offsets, won't work correctly if the bytecode is
89263  * larger than say 2G.
89264  */
89265 
89266 DUK_LOCAL duk_uint32_t duk__encode_i32(duk_int32_t x) {
89267 	if (x < 0) {
89268 		return ((duk_uint32_t) (-x)) * 2 + 1;
89269 	} else {
89270 		return ((duk_uint32_t) x) * 2;
89271 	}
89272 }
89273 
89274 /* XXX: return type should probably be duk_size_t, or explicit checks are needed for
89275  * maximum size.
89276  */
89277 DUK_LOCAL duk_uint32_t duk__insert_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t x) {
89278 	duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
89279 	duk_small_int_t len;
89280 
89281 	len = duk_unicode_encode_xutf8((duk_ucodepoint_t) x, buf);
89282 	DUK_ASSERT(len >= 0);
89283 	DUK_BW_INSERT_ENSURE_BYTES(re_ctx->thr, &re_ctx->bw, offset, buf, (duk_size_t) len);
89284 	return (duk_uint32_t) len;
89285 }
89286 
89287 DUK_LOCAL void duk__append_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t x) {
89288 	DUK_BW_WRITE_ENSURE_XUTF8(re_ctx->thr, &re_ctx->bw, x);
89289 }
89290 
89291 DUK_LOCAL void duk__append_7bit(duk_re_compiler_ctx *re_ctx, duk_uint32_t x) {
89292 #if defined(DUK_USE_PREFER_SIZE)
89293 	duk__append_u32(re_ctx, x);
89294 #else
89295 	DUK_ASSERT(x <= 0x7fU);
89296 	DUK_BW_WRITE_ENSURE_U8(re_ctx->thr, &re_ctx->bw, (duk_uint8_t) x);
89297 #endif
89298 }
89299 
89300 #if 0
89301 DUK_LOCAL void duk__append_2bytes(duk_re_compiler_ctx *re_ctx, duk_uint8_t x, duk_uint8_t y) {
89302 	DUK_BW_WRITE_ENSURE_U8_2(re_ctx->thr, &re_ctx->bw, x, y);
89303 }
89304 #endif
89305 
89306 DUK_LOCAL duk_uint32_t duk__insert_i32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t x) {
89307 	return duk__insert_u32(re_ctx, offset, duk__encode_i32(x));
89308 }
89309 
89310 DUK_LOCAL void duk__append_reop(duk_re_compiler_ctx *re_ctx, duk_uint32_t reop) {
89311 	DUK_ASSERT(reop <= 0x7fU);
89312 	(void) duk__append_7bit(re_ctx, reop);
89313 }
89314 
89315 #if 0  /* unused */
89316 DUK_LOCAL void duk__append_i32(duk_re_compiler_ctx *re_ctx, duk_int32_t x) {
89317 	duk__append_u32(re_ctx, duk__encode_i32(x));
89318 }
89319 #endif
89320 
89321 /* special helper for emitting u16 lists (used for character ranges for built-in char classes) */
89322 DUK_LOCAL void duk__append_u16_list(duk_re_compiler_ctx *re_ctx, const duk_uint16_t *values, duk_uint32_t count) {
89323 	/* Call sites don't need the result length so it's not accumulated. */
89324 	while (count-- > 0) {
89325 		duk__append_u32(re_ctx, (duk_uint32_t) (*values++));
89326 	}
89327 }
89328 
89329 DUK_LOCAL void duk__insert_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t data_offset, duk_uint32_t data_length) {
89330 	DUK_BW_INSERT_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, offset, data_offset, data_length);
89331 }
89332 
89333 DUK_LOCAL void duk__append_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) {
89334 	DUK_BW_WRITE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length);
89335 }
89336 
89337 DUK_LOCAL void duk__remove_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) {
89338 	DUK_BW_REMOVE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length);
89339 }
89340 
89341 /*
89342  *  Insert a jump offset at 'offset' to complete an instruction
89343  *  (the jump offset is always the last component of an instruction).
89344  *  The 'skip' argument must be computed relative to 'offset',
89345  *  -without- taking into account the skip field being inserted.
89346  *
89347  *       ... A B C ins X Y Z ...   (ins may be a JUMP, SPLIT1/SPLIT2, etc)
89348  *   =>  ... A B C ins SKIP X Y Z
89349  *
89350  *  Computing the final (adjusted) skip value, which is relative to the
89351  *  first byte of the next instruction, is a bit tricky because of the
89352  *  variable length UTF-8 encoding.  See doc/regexp.rst for discussion.
89353  */
89354 DUK_LOCAL duk_uint32_t duk__insert_jump_offset(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t skip) {
89355 #if 0
89356 	/* Iterative solution. */
89357 	if (skip < 0) {
89358 		duk_small_int_t len;
89359 		/* two encoding attempts suffices */
89360 		len = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip));
89361 		len = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip - (duk_int32_t) len));
89362 		DUK_ASSERT(duk_unicode_get_xutf8_length(duk__encode_i32(skip - (duk_int32_t) len)) == len);  /* no change */
89363 		skip -= (duk_int32_t) len;
89364 	}
89365 #endif
89366 
89367 #if defined(DUK_USE_PREFER_SIZE)
89368 	/* Closed form solution, this produces smallest code.
89369 	 * See re_neg_jump_offset (closed2).
89370 	 */
89371 	if (skip < 0) {
89372 		skip--;
89373 		if (skip < -0x3fL) {
89374 			skip--;
89375 		}
89376 		if (skip < -0x3ffL) {
89377 			skip--;
89378 		}
89379 		if (skip < -0x7fffL) {
89380 			skip--;
89381 		}
89382 		if (skip < -0xfffffL) {
89383 			skip--;
89384 		}
89385 		if (skip < -0x1ffffffL) {
89386 			skip--;
89387 		}
89388 		if (skip < -0x3fffffffL) {
89389 			skip--;
89390 		}
89391 	}
89392 #else  /* DUK_USE_PREFER_SIZE */
89393 	/* Closed form solution, this produces fastest code.
89394 	 * See re_neg_jump_offset (closed1).
89395 	 */
89396 	if (skip < 0) {
89397 		if (skip >= -0x3eL) {
89398 			skip -= 1;
89399 		} else if (skip >= -0x3fdL) {
89400 			skip -= 2;
89401 		} else if (skip >= -0x7ffcL) {
89402 			skip -= 3;
89403 		} else if (skip >= -0xffffbL) {
89404 			skip -= 4;
89405 		} else if (skip >= -0x1fffffaL) {
89406 			skip -= 5;
89407 		} else if (skip >= -0x3ffffff9L) {
89408 			skip -= 6;
89409 		} else {
89410 			skip -= 7;
89411 		}
89412 	}
89413 #endif  /* DUK_USE_PREFER_SIZE */
89414 
89415 	return duk__insert_i32(re_ctx, offset, skip);
89416 }
89417 
89418 DUK_LOCAL duk_uint32_t duk__append_jump_offset(duk_re_compiler_ctx *re_ctx, duk_int32_t skip) {
89419 	return (duk_uint32_t) duk__insert_jump_offset(re_ctx, (duk_uint32_t) DUK__RE_BUFLEN(re_ctx), skip);
89420 }
89421 
89422 /*
89423  *  duk_re_range_callback for generating character class ranges.
89424  *
89425  *  When ignoreCase is false, the range is simply emitted as is.  We don't,
89426  *  for instance, eliminate duplicates or overlapping ranges in a character
89427  *  class.
89428  *
89429  *  When ignoreCase is true but the 'direct' flag is set, the caller knows
89430  *  that the range canonicalizes to itself for case insensitive matching,
89431  *  so the range is emitted as is.  This is mainly useful for built-in ranges
89432  *  like \W.
89433  *
89434  *  Otherwise, when ignoreCase is true, the range needs to be normalized
89435  *  through canonicalization.  Unfortunately a canonicalized version of a
89436  *  continuous range is not necessarily continuous (e.g. [x-{] is continuous
89437  *  but [X-{] is not).  As a result, a single input range may expand to a lot
89438  *  of output ranges.  The current algorithm creates the canonicalized ranges
89439  *  footprint efficiently at the cost of compile time execution time; see
89440  *  doc/regexp.rst for discussion, and some more details below.
89441  *
89442  *  Note that the ctx->nranges is a context-wide temporary value.  This is OK
89443  *  because there cannot be multiple character classes being parsed
89444  *  simultaneously.
89445  *
89446  *  More detail on canonicalization:
89447  *
89448  *  Conceptually, a range is canonicalized by scanning the entire range,
89449  *  normalizing each codepoint by converting it to uppercase, and generating
89450  *  a set of result ranges.
89451  *
89452  *  Ideally a minimal set of output ranges would be emitted by merging all
89453  *  possible ranges even if they're emitted out of sequence.  Because the
89454  *  input string is also case normalized during matching, some codepoints
89455  *  never occur at runtime; these "don't care" codepoints can be included or
89456  *  excluded from ranges when merging/optimizing ranges.
89457  *
89458  *  The current algorithm does not do optimal range merging.  Rather, output
89459  *  codepoints are generated in sequence, and when the output codepoints are
89460  *  continuous (CP, CP+1, CP+2, ...), they are merged locally into as large a
89461  *  range as possible.  A small canonicalization bitmap is used to reduce
89462  *  actual codepoint canonicalizations which are quite slow at present.  The
89463  *  bitmap provides a "codepoint block is continuous with respect to
89464  *  canonicalization" for N-codepoint blocks.  This allows blocks to be
89465  *  skipped quickly.
89466  *
89467  *  There are a number of shortcomings and future work here:
89468  *
89469  *    - Individual codepoint normalizations are slow because they involve
89470  *      walking bit-packed rules without a lookup index.
89471  *
89472  *    - The conceptual algorithm needs to canonicalize every codepoint in the
89473  *      input range to figure out the output range(s).  Even with the small
89474  *      canonicalization bitmap the algorithm runs quite slowly for worst case
89475  *      inputs.  There are many data structure alternatives to improve this.
89476  *
89477  *    - While the current algorithm generates maximal output ranges when the
89478  *      output codepoints are emitted linearly, output ranges are not sorted or
89479  *      merged otherwise.  In the worst case a lot of ranges are emitted when
89480  *      most of the ranges could be merged.  In this process one could take
89481  *      advantage of "don't care" codepoints, which are never matched against at
89482  *      runtime due to canonicalization of input codepoints before comparison,
89483  *      to merge otherwise discontinuous output ranges.
89484  *
89485  *    - The runtime data structure is just a linear list of ranges to match
89486  *      against.  This can be quite slow if there are a lot of output ranges.
89487  *      There are various ways to make matching against the ranges faster,
89488  *      e.g. sorting the ranges and using a binary search; skip lists; tree
89489  *      based representations; full or approximate codepoint bitmaps, etc.
89490  *
89491  *    - Only BMP is supported, codepoints above BMP are assumed to canonicalize
89492  *      to themselves.  For now this is one place where we don't want to
89493  *      support chars outside the BMP, because the exhaustive search would be
89494  *      massively larger.  It would be possible to support non-BMP with a
89495  *      different algorithm, or perhaps doing case normalization only at match
89496  *      time.
89497  */
89498 
89499 DUK_LOCAL void duk__regexp_emit_range(duk_re_compiler_ctx *re_ctx, duk_codepoint_t r1, duk_codepoint_t r2) {
89500 	DUK_ASSERT(r2 >= r1);
89501 	duk__append_u32(re_ctx, (duk_uint32_t) r1);
89502 	duk__append_u32(re_ctx, (duk_uint32_t) r2);
89503 	re_ctx->nranges++;
89504 }
89505 
89506 #if defined(DUK_USE_REGEXP_CANON_BITMAP)
89507 /* Find next canonicalization discontinuity (conservative estimate) starting
89508  * from 'start', not exceeding 'end'.  If continuity is fine up to 'end'
89509  * inclusive, returns end.  Minimum possible return value is start.
89510  */
89511 DUK_LOCAL duk_codepoint_t duk__re_canon_next_discontinuity(duk_codepoint_t start, duk_codepoint_t end) {
89512 	duk_uint_t start_blk;
89513 	duk_uint_t end_blk;
89514 	duk_uint_t blk;
89515 	duk_uint_t offset;
89516 	duk_uint8_t mask;
89517 
89518 	/* Inclusive block range. */
89519 	DUK_ASSERT(start >= 0);
89520 	DUK_ASSERT(end >= 0);
89521 	DUK_ASSERT(end >= start);
89522 	start_blk = (duk_uint_t) (start >> DUK_CANON_BITMAP_BLKSHIFT);
89523 	end_blk = (duk_uint_t) (end >> DUK_CANON_BITMAP_BLKSHIFT);
89524 
89525 	for (blk = start_blk; blk <= end_blk; blk++) {
89526 		offset = blk >> 3;
89527 		mask = 1U << (blk & 0x07);
89528 		if (offset >= sizeof(duk_unicode_re_canon_bitmap)) {
89529 			/* Reached non-BMP range which is assumed continuous. */
89530 			return end;
89531 		}
89532 		DUK_ASSERT(offset < sizeof(duk_unicode_re_canon_bitmap));
89533 		if ((duk_unicode_re_canon_bitmap[offset] & mask) == 0) {
89534 			/* Block is discontinuous, continuity is guaranteed
89535 			 * only up to end of previous block (+1 for exclusive
89536 			 * return value => start of current block).  Start
89537 			 * block requires special handling.
89538 			 */
89539 			if (blk > start_blk) {
89540 				return (duk_codepoint_t) (blk << DUK_CANON_BITMAP_BLKSHIFT);
89541 			} else {
89542 				return start;
89543 			}
89544 		}
89545 	}
89546 	DUK_ASSERT(blk == end_blk + 1);  /* Reached end block which is continuous. */
89547 	return end;
89548 }
89549 #else  /* DUK_USE_REGEXP_CANON_BITMAP */
89550 DUK_LOCAL duk_codepoint_t duk__re_canon_next_discontinuity(duk_codepoint_t start, duk_codepoint_t end) {
89551 	DUK_ASSERT(start >= 0);
89552 	DUK_ASSERT(end >= 0);
89553 	DUK_ASSERT(end >= start);
89554 	if (start >= 0x10000) {
89555 		/* Even without the bitmap, treat non-BMP as continuous. */
89556 		return end;
89557 	}
89558 	return start;
89559 }
89560 #endif  /* DUK_USE_REGEXP_CANON_BITMAP */
89561 
89562 DUK_LOCAL void duk__regexp_generate_ranges(void *userdata, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct) {
89563 	duk_re_compiler_ctx *re_ctx = (duk_re_compiler_ctx *) userdata;
89564 	duk_codepoint_t r_start;
89565 	duk_codepoint_t r_end;
89566 	duk_codepoint_t i;
89567 	duk_codepoint_t t;
89568 	duk_codepoint_t r_disc;
89569 
89570 	DUK_DD(DUK_DDPRINT("duk__regexp_generate_ranges(): re_ctx=%p, range=[%ld,%ld] direct=%ld",
89571 	                   (void *) re_ctx, (long) r1, (long) r2, (long) direct));
89572 
89573 	DUK_ASSERT(r2 >= r1);  /* SyntaxError for out of order range. */
89574 
89575 	if (direct || (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) == 0) {
89576 		DUK_DD(DUK_DDPRINT("direct or not case sensitive, emit range: [%ld,%ld]", (long) r1, (long) r2));
89577 		duk__regexp_emit_range(re_ctx, r1, r2);
89578 		return;
89579 	}
89580 
89581 	DUK_DD(DUK_DDPRINT("case sensitive, process range: [%ld,%ld]", (long) r1, (long) r2));
89582 
89583 	r_start = duk_unicode_re_canonicalize_char(re_ctx->thr, r1);
89584 	r_end = r_start;
89585 
89586 	for (i = r1 + 1; i <= r2;) {
89587 		/* Input codepoint space processed up to i-1, and
89588 		 * current range in r_{start,end} is up-to-date
89589 		 * (inclusive) and may either break or continue.
89590 		 */
89591 		r_disc = duk__re_canon_next_discontinuity(i, r2);
89592 		DUK_ASSERT(r_disc >= i);
89593 		DUK_ASSERT(r_disc <= r2);
89594 
89595 		r_end += r_disc - i;  /* May be zero. */
89596 		t = duk_unicode_re_canonicalize_char(re_ctx->thr, r_disc);
89597 		if (t == r_end + 1) {
89598 			/* Not actually a discontinuity, continue range
89599 			 * to r_disc and recheck.
89600 			 */
89601 			r_end = t;
89602 		} else {
89603 			duk__regexp_emit_range(re_ctx, r_start, r_end);
89604 			r_start = t;
89605 			r_end = t;
89606 		}
89607 		i = r_disc + 1;  /* Guarantees progress. */
89608 	}
89609 	duk__regexp_emit_range(re_ctx, r_start, r_end);
89610 
89611 #if 0  /* Exhaustive search, very slow. */
89612 	r_start = duk_unicode_re_canonicalize_char(re_ctx->thr, r1);
89613 	r_end = r_start;
89614 	for (i = r1 + 1; i <= r2; i++) {
89615 		t = duk_unicode_re_canonicalize_char(re_ctx->thr, i);
89616 		if (t == r_end + 1) {
89617 			r_end = t;
89618 		} else {
89619 			DUK_DD(DUK_DDPRINT("canonicalized, emit range: [%ld,%ld]", (long) r_start, (long) r_end));
89620 			duk__append_u32(re_ctx, (duk_uint32_t) r_start);
89621 			duk__append_u32(re_ctx, (duk_uint32_t) r_end);
89622 			re_ctx->nranges++;
89623 			r_start = t;
89624 			r_end = t;
89625 		}
89626 	}
89627 	DUK_DD(DUK_DDPRINT("canonicalized, emit range: [%ld,%ld]", (long) r_start, (long) r_end));
89628 	duk__append_u32(re_ctx, (duk_uint32_t) r_start);
89629 	duk__append_u32(re_ctx, (duk_uint32_t) r_end);
89630 	re_ctx->nranges++;
89631 #endif
89632 }
89633 
89634 /*
89635  *  Parse regexp Disjunction.  Most of regexp compilation happens here.
89636  *
89637  *  Handles Disjunction, Alternative, and Term productions directly without
89638  *  recursion.  The only constructs requiring recursion are positive/negative
89639  *  lookaheads, capturing parentheses, and non-capturing parentheses.
89640  *
89641  *  The function determines whether the entire disjunction is a 'simple atom'
89642  *  (see doc/regexp.rst discussion on 'simple quantifiers') and if so,
89643  *  returns the atom character length which is needed by the caller to keep
89644  *  track of its own atom character length.  A disjunction with more than one
89645  *  alternative is never considered a simple atom (although in some cases
89646  *  that might be the case).
89647  *
89648  *  Return value: simple atom character length or < 0 if not a simple atom.
89649  *  Appends the bytecode for the disjunction matcher to the end of the temp
89650  *  buffer.
89651  *
89652  *  Regexp top level structure is:
89653  *
89654  *    Disjunction = Term*
89655  *                | Term* | Disjunction
89656  *
89657  *    Term = Assertion
89658  *         | Atom
89659  *         | Atom Quantifier
89660  *
89661  *  An empty Term sequence is a valid disjunction alternative (e.g. /|||c||/).
89662  *
89663  *  Notes:
89664  *
89665  *    * Tracking of the 'simple-ness' of the current atom vs. the entire
89666  *      disjunction are separate matters.  For instance, the disjunction
89667  *      may be complex, but individual atoms may be simple.  Furthermore,
89668  *      simple quantifiers are used whenever possible, even if the
89669  *      disjunction as a whole is complex.
89670  *
89671  *    * The estimate of whether an atom is simple is conservative now,
89672  *      and it would be possible to expand it.  For instance, captures
89673  *      cause the disjunction to be marked complex, even though captures
89674  *      -can- be handled by simple quantifiers with some minor modifications.
89675  *
89676  *    * Disjunction 'tainting' as 'complex' is handled at the end of the
89677  *      main for loop collectively for atoms.  Assertions, quantifiers,
89678  *      and '|' tokens need to taint the result manually if necessary.
89679  *      Assertions cannot add to result char length, only atoms (and
89680  *      quantifiers) can; currently quantifiers will taint the result
89681  *      as complex though.
89682  */
89683 
89684 DUK_LOCAL const duk_uint16_t * const duk__re_range_lookup1[3] = {
89685 	duk_unicode_re_ranges_digit,
89686 	duk_unicode_re_ranges_white,
89687 	duk_unicode_re_ranges_wordchar
89688 };
89689 DUK_LOCAL const duk_uint8_t duk__re_range_lookup2[3] = {
89690 	sizeof(duk_unicode_re_ranges_digit) / (2 * sizeof(duk_uint16_t)),
89691 	sizeof(duk_unicode_re_ranges_white) / (2 * sizeof(duk_uint16_t)),
89692 	sizeof(duk_unicode_re_ranges_wordchar) / (2 * sizeof(duk_uint16_t))
89693 };
89694 
89695 DUK_LOCAL void duk__append_range_atom_matcher(duk_re_compiler_ctx *re_ctx, duk_small_uint_t re_op, const duk_uint16_t *ranges, duk_small_uint_t count) {
89696 #if 0
89697 	DUK_ASSERT(re_op <= 0x7fUL);
89698 	DUK_ASSERT(count <= 0x7fUL);
89699 	duk__append_2bytes(re_ctx, (duk_uint8_t) re_op, (duk_uint8_t) count);
89700 #endif
89701 	duk__append_reop(re_ctx, re_op);
89702 	duk__append_7bit(re_ctx, count);
89703 	duk__append_u16_list(re_ctx, ranges, count * 2);
89704 }
89705 
89706 DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t expect_eof, duk__re_disjunction_info *out_atom_info) {
89707 	duk_int32_t atom_start_offset = -1;                   /* negative -> no atom matched on previous round */
89708 	duk_int32_t atom_char_length = 0;                     /* negative -> complex atom */
89709 	duk_uint32_t atom_start_captures = re_ctx->captures;  /* value of re_ctx->captures at start of atom */
89710 	duk_int32_t unpatched_disjunction_split = -1;
89711 	duk_int32_t unpatched_disjunction_jump = -1;
89712 	duk_uint32_t entry_offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
89713 	duk_int32_t res_charlen = 0;  /* -1 if disjunction is complex, char length if simple */
89714 	duk__re_disjunction_info tmp_disj;
89715 
89716 	DUK_ASSERT(out_atom_info != NULL);
89717 
89718 	duk_native_stack_check(re_ctx->thr);
89719 	if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
89720 		DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT);
89721 		DUK_WO_NORETURN(return;);
89722 	}
89723 	re_ctx->recursion_depth++;
89724 
89725 #if 0
89726 	out_atom_info->start_captures = re_ctx->captures;
89727 #endif
89728 
89729 	for (;;) {
89730 		/* atom_char_length, atom_start_offset, atom_start_offset reflect the
89731 		 * atom matched on the previous loop.  If a quantifier is encountered
89732 		 * on this loop, these are needed to handle the quantifier correctly.
89733 		 * new_atom_char_length etc are for the atom parsed on this round;
89734 		 * they're written to atom_char_length etc at the end of the round.
89735 		 */
89736 		duk_int32_t new_atom_char_length;   /* char length of the atom parsed in this loop */
89737 		duk_int32_t new_atom_start_offset;  /* bytecode start offset of the atom parsed in this loop
89738 		                                     * (allows quantifiers to copy the atom bytecode)
89739 		                                     */
89740 		duk_uint32_t new_atom_start_captures;  /* re_ctx->captures at the start of the atom parsed in this loop */
89741 
89742 		duk_lexer_parse_re_token(&re_ctx->lex, &re_ctx->curr_token);
89743 
89744 		DUK_DD(DUK_DDPRINT("re token: %ld (num=%ld, char=%c)",
89745 		                   (long) re_ctx->curr_token.t,
89746 		                   (long) re_ctx->curr_token.num,
89747 		                   (re_ctx->curr_token.num >= 0x20 && re_ctx->curr_token.num <= 0x7e) ?
89748 		                   (int) re_ctx->curr_token.num : (int) '?'));
89749 
89750 		/* set by atom case clauses */
89751 		new_atom_start_offset = -1;
89752 		new_atom_char_length = -1;
89753 		new_atom_start_captures = re_ctx->captures;
89754 
89755 		switch (re_ctx->curr_token.t) {
89756 		case DUK_RETOK_DISJUNCTION: {
89757 			/*
89758 			 *  The handling here is a bit tricky.  If a previous '|' has been processed,
89759 			 *  we have a pending split1 and a pending jump (for a previous match).  These
89760 			 *  need to be back-patched carefully.  See docs for a detailed example.
89761 			 */
89762 
89763 			/* patch pending jump and split */
89764 			if (unpatched_disjunction_jump >= 0) {
89765 				duk_uint32_t offset;
89766 
89767 				DUK_ASSERT(unpatched_disjunction_split >= 0);
89768 				offset = (duk_uint32_t) unpatched_disjunction_jump;
89769 				offset += duk__insert_jump_offset(re_ctx,
89770 				                                  offset,
89771 				                                  (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
89772 				/* offset is now target of the pending split (right after jump) */
89773 				duk__insert_jump_offset(re_ctx,
89774 				                        (duk_uint32_t) unpatched_disjunction_split,
89775 				                        (duk_int32_t) offset - unpatched_disjunction_split);
89776 			}
89777 
89778 			/* add a new pending split to the beginning of the entire disjunction */
89779 			(void) duk__insert_u32(re_ctx,
89780 			                       entry_offset,
89781 			                       DUK_REOP_SPLIT1);   /* prefer direct execution */
89782 			unpatched_disjunction_split = (duk_int32_t) (entry_offset + 1);   /* +1 for opcode */
89783 
89784 			/* add a new pending match jump for latest finished alternative */
89785 			duk__append_reop(re_ctx, DUK_REOP_JUMP);
89786 			unpatched_disjunction_jump = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
89787 
89788 			/* 'taint' result as complex */
89789 			res_charlen = -1;
89790 			break;
89791 		}
89792 		case DUK_RETOK_QUANTIFIER: {
89793 			if (atom_start_offset < 0) {
89794 				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_INVALID_QUANTIFIER_NO_ATOM);
89795 				DUK_WO_NORETURN(return;);
89796 			}
89797 			if (re_ctx->curr_token.qmin > re_ctx->curr_token.qmax) {
89798 				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_INVALID_QUANTIFIER_VALUES);
89799 				DUK_WO_NORETURN(return;);
89800 			}
89801 			if (atom_char_length >= 0) {
89802 				/*
89803 				 *  Simple atom
89804 				 *
89805 				 *  If atom_char_length is zero, we'll have unbounded execution time for e.g.
89806 				 *  /()*x/.exec('x').  We can't just skip the match because it might have some
89807 				 *  side effects (for instance, if we allowed captures in simple atoms, the
89808 				 *  capture needs to happen).  The simple solution below is to force the
89809 				 *  quantifier to match at most once, since the additional matches have no effect.
89810 				 *
89811 				 *  With a simple atom there can be no capture groups, so no captures need
89812 				 *  to be reset.
89813 				 */
89814 				duk_int32_t atom_code_length;
89815 				duk_uint32_t offset;
89816 				duk_uint32_t qmin, qmax;
89817 
89818 				qmin = re_ctx->curr_token.qmin;
89819 				qmax = re_ctx->curr_token.qmax;
89820 				if (atom_char_length == 0) {
89821 					/* qmin and qmax will be 0 or 1 */
89822 					if (qmin > 1) {
89823 						qmin = 1;
89824 					}
89825 					if (qmax > 1) {
89826 						qmax = 1;
89827 					}
89828 				}
89829 
89830 				duk__append_reop(re_ctx, DUK_REOP_MATCH);   /* complete 'sub atom' */
89831 				atom_code_length = (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (duk_size_t) atom_start_offset);
89832 
89833 				offset = (duk_uint32_t) atom_start_offset;
89834 				if (re_ctx->curr_token.greedy) {
89835 					offset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQGREEDY);
89836 					offset += duk__insert_u32(re_ctx, offset, qmin);
89837 					offset += duk__insert_u32(re_ctx, offset, qmax);
89838 					offset += duk__insert_u32(re_ctx, offset, (duk_uint32_t) atom_char_length);
89839 					offset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);
89840 				} else {
89841 					offset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQMINIMAL);
89842 					offset += duk__insert_u32(re_ctx, offset, qmin);
89843 					offset += duk__insert_u32(re_ctx, offset, qmax);
89844 					offset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);
89845 				}
89846 				DUK_UNREF(offset);  /* silence scan-build warning */
89847 			} else {
89848 				/*
89849 				 *  Complex atom
89850 				 *
89851 				 *  The original code is used as a template, and removed at the end
89852 				 *  (this differs from the handling of simple quantifiers).
89853 				 *
89854 				 *  NOTE: there is no current solution for empty atoms in complex
89855 				 *  quantifiers.  This would need some sort of a 'progress' instruction.
89856 				 *
89857 				 *  XXX: impose limit on maximum result size, i.e. atom_code_len * atom_copies?
89858 				 */
89859 				duk_int32_t atom_code_length;
89860 				duk_uint32_t atom_copies;
89861 				duk_uint32_t tmp_qmin, tmp_qmax;
89862 
89863 				/* pre-check how many atom copies we're willing to make (atom_copies not needed below) */
89864 				atom_copies = (re_ctx->curr_token.qmax == DUK_RE_QUANTIFIER_INFINITE) ?
89865 				              re_ctx->curr_token.qmin : re_ctx->curr_token.qmax;
89866 				if (atom_copies > DUK_RE_MAX_ATOM_COPIES) {
89867 					DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_QUANTIFIER_TOO_MANY_COPIES);
89868 					DUK_WO_NORETURN(return;);
89869 				}
89870 
89871 				/* wipe the capture range made by the atom (if any) */
89872 				DUK_ASSERT(atom_start_captures <= re_ctx->captures);
89873 				if (atom_start_captures != re_ctx->captures) {
89874 					DUK_ASSERT(atom_start_captures < re_ctx->captures);
89875 					DUK_DDD(DUK_DDDPRINT("must wipe ]atom_start_captures,re_ctx->captures]: ]%ld,%ld]",
89876 					                     (long) atom_start_captures, (long) re_ctx->captures));
89877 
89878 					/* insert (DUK_REOP_WIPERANGE, start, count) in reverse order so the order ends up right */
89879 					duk__insert_u32(re_ctx, (duk_uint32_t) atom_start_offset, (re_ctx->captures - atom_start_captures) * 2U);
89880 					duk__insert_u32(re_ctx, (duk_uint32_t) atom_start_offset, (atom_start_captures + 1) * 2);
89881 					duk__insert_u32(re_ctx, (duk_uint32_t) atom_start_offset, DUK_REOP_WIPERANGE);
89882 				} else {
89883 					DUK_DDD(DUK_DDDPRINT("no need to wipe captures: atom_start_captures == re_ctx->captures == %ld",
89884 					                     (long) atom_start_captures));
89885 				}
89886 
89887 				atom_code_length = (duk_int32_t) DUK__RE_BUFLEN(re_ctx) - atom_start_offset;
89888 
89889 				/* insert the required matches (qmin) by copying the atom */
89890 				tmp_qmin = re_ctx->curr_token.qmin;
89891 				tmp_qmax = re_ctx->curr_token.qmax;
89892 				while (tmp_qmin > 0) {
89893 					duk__append_slice(re_ctx, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
89894 					tmp_qmin--;
89895 					if (tmp_qmax != DUK_RE_QUANTIFIER_INFINITE) {
89896 						tmp_qmax--;
89897 					}
89898 				}
89899 				DUK_ASSERT(tmp_qmin == 0);
89900 
89901 				/* insert code for matching the remainder - infinite or finite */
89902 				if (tmp_qmax == DUK_RE_QUANTIFIER_INFINITE) {
89903 					/* reuse last emitted atom for remaining 'infinite' quantifier */
89904 
89905 					if (re_ctx->curr_token.qmin == 0) {
89906 						/* Special case: original qmin was zero so there is nothing
89907 						 * to repeat.  Emit an atom copy but jump over it here.
89908 						 */
89909 						duk__append_reop(re_ctx, DUK_REOP_JUMP);
89910 						duk__append_jump_offset(re_ctx, atom_code_length);
89911 						duk__append_slice(re_ctx, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
89912 					}
89913 					if (re_ctx->curr_token.greedy) {
89914 						duk__append_reop(re_ctx, DUK_REOP_SPLIT2);   /* prefer jump */
89915 					} else {
89916 						duk__append_reop(re_ctx, DUK_REOP_SPLIT1);   /* prefer direct */
89917 					}
89918 					duk__append_jump_offset(re_ctx, -atom_code_length - 1);  /* -1 for opcode */
89919 				} else {
89920 					/*
89921 					 *  The remaining matches are emitted as sequence of SPLITs and atom
89922 					 *  copies; the SPLITs skip the remaining copies and match the sequel.
89923 					 *  This sequence needs to be emitted starting from the last copy
89924 					 *  because the SPLITs are variable length due to the variable length
89925 					 *  skip offset.  This causes a lot of memory copying now.
89926 					 *
89927 					 *  Example structure (greedy, match maximum # atoms):
89928 					 *
89929 					 *      SPLIT1 LSEQ
89930 					 *      (atom)
89931 					 *      SPLIT1 LSEQ    ; <- the byte length of this instruction is needed
89932 					 *      (atom)         ; to encode the above SPLIT1 correctly
89933 					 *      ...
89934 					 *   LSEQ:
89935 					 */
89936 					duk_uint32_t offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
89937 					while (tmp_qmax > 0) {
89938 						duk__insert_slice(re_ctx, offset, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
89939 						if (re_ctx->curr_token.greedy) {
89940 							duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT1);   /* prefer direct */
89941 						} else {
89942 							duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT2);   /* prefer jump */
89943 						}
89944 						duk__insert_jump_offset(re_ctx,
89945 						                        offset + 1,   /* +1 for opcode */
89946 						                        (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));
89947 						tmp_qmax--;
89948 					}
89949 				}
89950 
89951 				/* remove the original 'template' atom */
89952 				duk__remove_slice(re_ctx, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
89953 			}
89954 
89955 			/* 'taint' result as complex */
89956 			res_charlen = -1;
89957 			break;
89958 		}
89959 		case DUK_RETOK_ASSERT_START: {
89960 			duk__append_reop(re_ctx, DUK_REOP_ASSERT_START);
89961 			break;
89962 		}
89963 		case DUK_RETOK_ASSERT_END: {
89964 			duk__append_reop(re_ctx, DUK_REOP_ASSERT_END);
89965 			break;
89966 		}
89967 		case DUK_RETOK_ASSERT_WORD_BOUNDARY: {
89968 			duk__append_reop(re_ctx, DUK_REOP_ASSERT_WORD_BOUNDARY);
89969 			break;
89970 		}
89971 		case DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY: {
89972 			duk__append_reop(re_ctx, DUK_REOP_ASSERT_NOT_WORD_BOUNDARY);
89973 			break;
89974 		}
89975 		case DUK_RETOK_ASSERT_START_POS_LOOKAHEAD:
89976 		case DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD: {
89977 			duk_uint32_t offset;
89978 			duk_uint32_t opcode = (re_ctx->curr_token.t == DUK_RETOK_ASSERT_START_POS_LOOKAHEAD) ?
89979 			                      DUK_REOP_LOOKPOS : DUK_REOP_LOOKNEG;
89980 
89981 			offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
89982 			duk__parse_disjunction(re_ctx, 0, &tmp_disj);
89983 			duk__append_reop(re_ctx, DUK_REOP_MATCH);
89984 
89985 			(void) duk__insert_u32(re_ctx, offset, opcode);
89986 			(void) duk__insert_jump_offset(re_ctx,
89987 			                               offset + 1,   /* +1 for opcode */
89988 			                               (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));
89989 
89990 			/* 'taint' result as complex -- this is conservative,
89991 			 * as lookaheads do not backtrack.
89992 			 */
89993 			res_charlen = -1;
89994 			break;
89995 		}
89996 		case DUK_RETOK_ATOM_PERIOD: {
89997 			new_atom_char_length = 1;
89998 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
89999 			duk__append_reop(re_ctx, DUK_REOP_PERIOD);
90000 			break;
90001 		}
90002 		case DUK_RETOK_ATOM_CHAR: {
90003 			/* Note: successive characters could be joined into string matches
90004 			 * but this is not trivial (consider e.g. '/xyz+/); see docs for
90005 			 * more discussion.
90006 			 *
90007 			 * No support for \u{H+} yet.  While only BMP Unicode escapes are
90008 			 * supported for RegExps at present, 'ch' may still be a non-BMP
90009 			 * codepoint if it is decoded straight from source text UTF-8.
90010 			 * There's no non-BMP support yet so this is handled simply by
90011 			 * matching the non-BMP character (which is custom behavior).
90012 			 */
90013 			duk_uint32_t ch;
90014 
90015 			new_atom_char_length = 1;
90016 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
90017 			duk__append_reop(re_ctx, DUK_REOP_CHAR);
90018 			ch = re_ctx->curr_token.num;
90019 			if (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {
90020 				ch = (duk_uint32_t) duk_unicode_re_canonicalize_char(re_ctx->thr, (duk_codepoint_t) ch);
90021 			}
90022 			duk__append_u32(re_ctx, ch);
90023 			break;
90024 		}
90025 		case DUK_RETOK_ATOM_DIGIT:
90026 		case DUK_RETOK_ATOM_NOT_DIGIT:
90027 		case DUK_RETOK_ATOM_WHITE:
90028 		case DUK_RETOK_ATOM_NOT_WHITE:
90029 		case DUK_RETOK_ATOM_WORD_CHAR:
90030 		case DUK_RETOK_ATOM_NOT_WORD_CHAR: {
90031 			duk_small_uint_t re_op;
90032 			duk_small_uint_t idx;
90033 
90034 			new_atom_char_length = 1;
90035 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
90036 
90037 			DUK_ASSERT((DUK_RETOK_ATOM_DIGIT & 0x01) != 0);
90038 			DUK_ASSERT((DUK_RETOK_ATOM_WHITE & 0x01) != 0);
90039 			DUK_ASSERT((DUK_RETOK_ATOM_WORD_CHAR & 0x01) != 0);
90040 			DUK_ASSERT((DUK_RETOK_ATOM_NOT_DIGIT & 0x01) == 0);
90041 			DUK_ASSERT((DUK_RETOK_ATOM_NOT_WHITE & 0x01) == 0);
90042 			DUK_ASSERT((DUK_RETOK_ATOM_NOT_WORD_CHAR & 0x01) == 0);
90043 			re_op = (re_ctx->curr_token.t & 0x01) ? DUK_REOP_RANGES : DUK_REOP_INVRANGES;
90044 
90045 			DUK_ASSERT(DUK_RETOK_ATOM_WHITE == DUK_RETOK_ATOM_DIGIT + 2);
90046 			DUK_ASSERT(DUK_RETOK_ATOM_WORD_CHAR == DUK_RETOK_ATOM_DIGIT + 4);
90047 			idx = (duk_small_uint_t) ((re_ctx->curr_token.t - DUK_RETOK_ATOM_DIGIT) >> 1U);
90048 			DUK_ASSERT(idx <= 2U);  /* Assume continuous token numbers; also checks negative underflow. */
90049 
90050 			duk__append_range_atom_matcher(re_ctx, re_op, duk__re_range_lookup1[idx], duk__re_range_lookup2[idx]);
90051 			break;
90052 		}
90053 		case DUK_RETOK_ATOM_BACKREFERENCE: {
90054 			duk_uint32_t backref = (duk_uint32_t) re_ctx->curr_token.num;
90055 			if (backref > re_ctx->highest_backref) {
90056 				re_ctx->highest_backref = backref;
90057 			}
90058 			new_atom_char_length = -1;   /* mark as complex */
90059 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
90060 			duk__append_reop(re_ctx, DUK_REOP_BACKREFERENCE);
90061 			duk__append_u32(re_ctx, backref);
90062 			break;
90063 		}
90064 		case DUK_RETOK_ATOM_START_CAPTURE_GROUP: {
90065 			duk_uint32_t cap;
90066 
90067 			new_atom_char_length = -1;   /* mark as complex (capture handling) */
90068 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
90069 			cap = ++re_ctx->captures;
90070 			duk__append_reop(re_ctx, DUK_REOP_SAVE);
90071 			duk__append_u32(re_ctx, cap * 2);
90072 			duk__parse_disjunction(re_ctx, 0, &tmp_disj);  /* retval (sub-atom char length) unused, tainted as complex above */
90073 			duk__append_reop(re_ctx, DUK_REOP_SAVE);
90074 			duk__append_u32(re_ctx, cap * 2 + 1);
90075 			break;
90076 		}
90077 		case DUK_RETOK_ATOM_START_NONCAPTURE_GROUP: {
90078 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
90079 			duk__parse_disjunction(re_ctx, 0, &tmp_disj);
90080 			new_atom_char_length = tmp_disj.charlen;
90081 			break;
90082 		}
90083 		case DUK_RETOK_ATOM_START_CHARCLASS:
90084 		case DUK_RETOK_ATOM_START_CHARCLASS_INVERTED: {
90085 			/*
90086 			 *  Range parsing is done with a special lexer function which calls
90087 			 *  us for every range parsed.  This is different from how rest of
90088 			 *  the parsing works, but avoids a heavy, arbitrary size intermediate
90089 			 *  value type to hold the ranges.
90090 			 *
90091 			 *  Another complication is the handling of character ranges when
90092 			 *  case insensitive matching is used (see docs for discussion).
90093 			 *  The range handler callback given to the lexer takes care of this
90094 			 *  as well.
90095 			 *
90096 			 *  Note that duplicate ranges are not eliminated when parsing character
90097 			 *  classes, so that canonicalization of
90098 			 *
90099 			 *    [0-9a-fA-Fx-{]
90100 			 *
90101 			 *  creates the result (note the duplicate ranges):
90102 			 *
90103 			 *    [0-9A-FA-FX-Z{-{]
90104 			 *
90105 			 *  where [x-{] is split as a result of canonicalization.  The duplicate
90106 			 *  ranges are not a semantics issue: they work correctly.
90107 			 */
90108 
90109 			duk_uint32_t offset;
90110 
90111 			DUK_DD(DUK_DDPRINT("character class"));
90112 
90113 			/* insert ranges instruction, range count patched in later */
90114 			new_atom_char_length = 1;
90115 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
90116 			duk__append_reop(re_ctx,
90117 			                 (re_ctx->curr_token.t == DUK_RETOK_ATOM_START_CHARCLASS) ?
90118 			                 DUK_REOP_RANGES : DUK_REOP_INVRANGES);
90119 			offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);    /* patch in range count later */
90120 
90121 			/* parse ranges until character class ends */
90122 			re_ctx->nranges = 0;    /* note: ctx-wide temporary */
90123 			duk_lexer_parse_re_ranges(&re_ctx->lex, duk__regexp_generate_ranges, (void *) re_ctx);
90124 
90125 			/* insert range count */
90126 			duk__insert_u32(re_ctx, offset, re_ctx->nranges);
90127 			break;
90128 		}
90129 		case DUK_RETOK_ATOM_END_GROUP: {
90130 			if (expect_eof) {
90131 				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_CLOSING_PAREN);
90132 				DUK_WO_NORETURN(return;);
90133 			}
90134 			goto done;
90135 		}
90136 		case DUK_RETOK_EOF: {
90137 			if (!expect_eof) {
90138 				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_END_OF_PATTERN);
90139 				DUK_WO_NORETURN(return;);
90140 			}
90141 			goto done;
90142 		}
90143 		default: {
90144 			DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_REGEXP_TOKEN);
90145 			DUK_WO_NORETURN(return;);
90146 		}
90147 		}
90148 
90149 		/* a complex (new) atom taints the result */
90150 		if (new_atom_start_offset >= 0) {
90151 			if (new_atom_char_length < 0) {
90152 				res_charlen = -1;
90153 			} else if (res_charlen >= 0) {
90154 				/* only advance if not tainted */
90155 				res_charlen += new_atom_char_length;
90156 			}
90157 		}
90158 
90159 		/* record previous atom info in case next token is a quantifier */
90160 		atom_start_offset = new_atom_start_offset;
90161 		atom_char_length = new_atom_char_length;
90162 		atom_start_captures = new_atom_start_captures;
90163 	}
90164 
90165  done:
90166 
90167 	/* finish up pending jump and split for last alternative */
90168 	if (unpatched_disjunction_jump >= 0) {
90169 		duk_uint32_t offset;
90170 
90171 		DUK_ASSERT(unpatched_disjunction_split >= 0);
90172 		offset = (duk_uint32_t) unpatched_disjunction_jump;
90173 		offset += duk__insert_jump_offset(re_ctx,
90174 		                                  offset,
90175 		                                  (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
90176 		/* offset is now target of the pending split (right after jump) */
90177 		duk__insert_jump_offset(re_ctx,
90178 		                        (duk_uint32_t) unpatched_disjunction_split,
90179 		                        (duk_int32_t) offset - unpatched_disjunction_split);
90180 	}
90181 
90182 #if 0
90183 	out_atom_info->end_captures = re_ctx->captures;
90184 #endif
90185 	out_atom_info->charlen = res_charlen;
90186 	DUK_DDD(DUK_DDDPRINT("parse disjunction finished: charlen=%ld",
90187 	                     (long) out_atom_info->charlen));
90188 
90189 	re_ctx->recursion_depth--;
90190 }
90191 
90192 /*
90193  *  Flags parsing (see E5 Section 15.10.4.1).
90194  */
90195 
90196 DUK_LOCAL duk_uint32_t duk__parse_regexp_flags(duk_hthread *thr, duk_hstring *h) {
90197 	const duk_uint8_t *p;
90198 	const duk_uint8_t *p_end;
90199 	duk_uint32_t flags = 0;
90200 
90201 	p = DUK_HSTRING_GET_DATA(h);
90202 	p_end = p + DUK_HSTRING_GET_BYTELEN(h);
90203 
90204 	/* Note: can be safely scanned as bytes (undecoded) */
90205 
90206 	while (p < p_end) {
90207 		duk_uint8_t c = *p++;
90208 		switch (c) {
90209 		case (duk_uint8_t) 'g': {
90210 			if (flags & DUK_RE_FLAG_GLOBAL) {
90211 				goto flags_error;
90212 			}
90213 			flags |= DUK_RE_FLAG_GLOBAL;
90214 			break;
90215 		}
90216 		case (duk_uint8_t) 'i': {
90217 			if (flags & DUK_RE_FLAG_IGNORE_CASE) {
90218 				goto flags_error;
90219 			}
90220 			flags |= DUK_RE_FLAG_IGNORE_CASE;
90221 			break;
90222 		}
90223 		case (duk_uint8_t) 'm': {
90224 			if (flags & DUK_RE_FLAG_MULTILINE) {
90225 				goto flags_error;
90226 			}
90227 			flags |= DUK_RE_FLAG_MULTILINE;
90228 			break;
90229 		}
90230 		default: {
90231 			goto flags_error;
90232 		}
90233 		}
90234 	}
90235 
90236 	return flags;
90237 
90238  flags_error:
90239 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_REGEXP_FLAGS);
90240 	DUK_WO_NORETURN(return 0U;);
90241 }
90242 
90243 /*
90244  *  Create escaped RegExp source (E5 Section 15.10.3).
90245  *
90246  *  The current approach is to special case the empty RegExp
90247  *  ('' -> '(?:)') and otherwise replace unescaped '/' characters
90248  *  with '\/' regardless of where they occur in the regexp.
90249  *
90250  *  Note that normalization does not seem to be necessary for
90251  *  RegExp literals (e.g. '/foo/') because to be acceptable as
90252  *  a RegExp literal, the text between forward slashes must
90253  *  already match the escaping requirements (e.g. must not contain
90254  *  unescaped forward slashes or be empty).  Escaping IS needed
90255  *  for expressions like 'new Regexp("...", "")' however.
90256  *  Currently, we re-escape in either case.
90257  *
90258  *  Also note that we process the source here in UTF-8 encoded
90259  *  form.  This is correct, because any non-ASCII characters are
90260  *  passed through without change.
90261  */
90262 
90263 DUK_LOCAL void duk__create_escaped_source(duk_hthread *thr, int idx_pattern) {
90264 	duk_hstring *h;
90265 	const duk_uint8_t *p;
90266 	duk_bufwriter_ctx bw_alloc;
90267 	duk_bufwriter_ctx *bw;
90268 	duk_uint8_t *q;
90269 	duk_size_t i, n;
90270 	duk_uint_fast8_t c_prev, c;
90271 
90272 	h = duk_known_hstring(thr, idx_pattern);
90273 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
90274 	n = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
90275 
90276 	if (n == 0) {
90277 		duk_push_literal(thr, "(?:)");
90278 		return;
90279 	}
90280 
90281 	bw = &bw_alloc;
90282 	DUK_BW_INIT_PUSHBUF(thr, bw, n);
90283 	q = DUK_BW_GET_PTR(thr, bw);
90284 
90285 	c_prev = (duk_uint_fast8_t) 0;
90286 
90287 	for (i = 0; i < n; i++) {
90288 		c = p[i];
90289 
90290 		q = DUK_BW_ENSURE_RAW(thr, bw, 2, q);
90291 
90292 		if (c == (duk_uint_fast8_t) '/' && c_prev != (duk_uint_fast8_t) '\\') {
90293 			/* Unescaped '/' ANYWHERE in the regexp (in disjunction,
90294 			 * inside a character class, ...) => same escape works.
90295 			 */
90296 			*q++ = DUK_ASC_BACKSLASH;
90297 		}
90298 		*q++ = (duk_uint8_t) c;
90299 
90300 		c_prev = c;
90301 	}
90302 
90303 	DUK_BW_SETPTR_AND_COMPACT(thr, bw, q);
90304 	(void) duk_buffer_to_string(thr, -1);  /* Safe if input is safe. */
90305 
90306 	/* [ ... escaped_source ] */
90307 }
90308 
90309 /*
90310  *  Exposed regexp compilation primitive.
90311  *
90312  *  Sets up a regexp compilation context, and calls duk__parse_disjunction() to do the
90313  *  actual parsing.  Handles generation of the compiled regexp header and the
90314  *  "boilerplate" capture of the matching substring (save 0 and 1).  Also does some
90315  *  global level regexp checks after recursive compilation has finished.
90316  *
90317  *  An escaped version of the regexp source, suitable for use as a RegExp instance
90318  *  'source' property (see E5 Section 15.10.3), is also left on the stack.
90319  *
90320  *  Input stack:  [ pattern flags ]
90321  *  Output stack: [ bytecode escaped_source ]  (both as strings)
90322  */
90323 
90324 DUK_INTERNAL void duk_regexp_compile(duk_hthread *thr) {
90325 	duk_re_compiler_ctx re_ctx;
90326 	duk_lexer_point lex_point;
90327 	duk_hstring *h_pattern;
90328 	duk_hstring *h_flags;
90329 	duk__re_disjunction_info ign_disj;
90330 
90331 	DUK_ASSERT(thr != NULL);
90332 
90333 	/*
90334 	 *  Args validation
90335 	 */
90336 
90337 	/* TypeError if fails */
90338 	h_pattern = duk_require_hstring_notsymbol(thr, -2);
90339 	h_flags = duk_require_hstring_notsymbol(thr, -1);
90340 
90341 	/*
90342 	 *  Create normalized 'source' property (E5 Section 15.10.3).
90343 	 */
90344 
90345 	/* [ ... pattern flags ] */
90346 
90347 	duk__create_escaped_source(thr, -2);
90348 
90349 	/* [ ... pattern flags escaped_source ] */
90350 
90351 	/*
90352 	 *  Init compilation context
90353 	 */
90354 
90355 	/* [ ... pattern flags escaped_source buffer ] */
90356 
90357 	duk_memzero(&re_ctx, sizeof(re_ctx));
90358 	DUK_LEXER_INITCTX(&re_ctx.lex);  /* duplicate zeroing, expect for (possible) NULL inits */
90359 	re_ctx.thr = thr;
90360 	re_ctx.lex.thr = thr;
90361 	re_ctx.lex.input = DUK_HSTRING_GET_DATA(h_pattern);
90362 	re_ctx.lex.input_length = DUK_HSTRING_GET_BYTELEN(h_pattern);
90363 	re_ctx.lex.token_limit = DUK_RE_COMPILE_TOKEN_LIMIT;
90364 	re_ctx.recursion_limit = DUK_USE_REGEXP_COMPILER_RECLIMIT;
90365 	re_ctx.re_flags = duk__parse_regexp_flags(thr, h_flags);
90366 
90367 	DUK_BW_INIT_PUSHBUF(thr, &re_ctx.bw, DUK__RE_INITIAL_BUFSIZE);
90368 
90369 	DUK_DD(DUK_DDPRINT("regexp compiler ctx initialized, flags=0x%08lx, recursion_limit=%ld",
90370 	                   (unsigned long) re_ctx.re_flags, (long) re_ctx.recursion_limit));
90371 
90372 	/*
90373 	 *  Init lexer
90374 	 */
90375 
90376 	lex_point.offset = 0;  /* expensive init, just want to fill window */
90377 	lex_point.line = 1;
90378 	DUK_LEXER_SETPOINT(&re_ctx.lex, &lex_point);
90379 
90380 	/*
90381 	 *  Compilation
90382 	 */
90383 
90384 	DUK_DD(DUK_DDPRINT("starting regexp compilation"));
90385 
90386 	duk__append_reop(&re_ctx, DUK_REOP_SAVE);
90387 	duk__append_7bit(&re_ctx, 0);
90388 	duk__parse_disjunction(&re_ctx, 1 /*expect_eof*/, &ign_disj);
90389 	duk__append_reop(&re_ctx, DUK_REOP_SAVE);
90390 	duk__append_7bit(&re_ctx, 1);
90391 	duk__append_reop(&re_ctx, DUK_REOP_MATCH);
90392 
90393 	/*
90394 	 *  Check for invalid backreferences; note that it is NOT an error
90395 	 *  to back-reference a capture group which has not yet been introduced
90396 	 *  in the pattern (as in /\1(foo)/); in fact, the backreference will
90397 	 *  always match!  It IS an error to back-reference a capture group
90398 	 *  which will never be introduced in the pattern.  Thus, we can check
90399 	 *  for such references only after parsing is complete.
90400 	 */
90401 
90402 	if (re_ctx.highest_backref > re_ctx.captures) {
90403 		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_BACKREFS);
90404 		DUK_WO_NORETURN(return;);
90405 	}
90406 
90407 	/*
90408 	 *  Emit compiled regexp header: flags, ncaptures
90409 	 *  (insertion order inverted on purpose)
90410 	 */
90411 
90412 	duk__insert_u32(&re_ctx, 0, (re_ctx.captures + 1) * 2);
90413 	duk__insert_u32(&re_ctx, 0, re_ctx.re_flags);
90414 
90415 	/* [ ... pattern flags escaped_source buffer ] */
90416 
90417 	DUK_BW_COMPACT(thr, &re_ctx.bw);
90418 	(void) duk_buffer_to_string(thr, -1);  /* Safe because flags is at most 7 bit. */
90419 
90420 	/* [ ... pattern flags escaped_source bytecode ] */
90421 
90422 	/*
90423 	 *  Finalize stack
90424 	 */
90425 
90426 	duk_remove(thr, -4);     /* -> [ ... flags escaped_source bytecode ] */
90427 	duk_remove(thr, -3);     /* -> [ ... escaped_source bytecode ] */
90428 
90429 	DUK_DD(DUK_DDPRINT("regexp compilation successful, bytecode: %!T, escaped source: %!T",
90430 	                   (duk_tval *) duk_get_tval(thr, -1), (duk_tval *) duk_get_tval(thr, -2)));
90431 }
90432 
90433 /*
90434  *  Create a RegExp instance (E5 Section 15.10.7).
90435  *
90436  *  Note: the output stack left by duk_regexp_compile() is directly compatible
90437  *  with the input here.
90438  *
90439  *  Input stack:  [ escaped_source bytecode ]  (both as strings)
90440  *  Output stack: [ RegExp ]
90441  */
90442 
90443 DUK_INTERNAL void duk_regexp_create_instance(duk_hthread *thr) {
90444 	duk_hobject *h;
90445 
90446 	/* [ ... escaped_source bytecode ] */
90447 
90448 	duk_push_object(thr);
90449 	h = duk_known_hobject(thr, -1);
90450 	duk_insert(thr, -3);
90451 
90452 	/* [ ... regexp_object escaped_source bytecode ] */
90453 
90454 	DUK_HOBJECT_SET_CLASS_NUMBER(h, DUK_HOBJECT_CLASS_REGEXP);
90455 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[DUK_BIDX_REGEXP_PROTOTYPE]);
90456 
90457 	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_BYTECODE, DUK_PROPDESC_FLAGS_NONE);
90458 
90459 	/* [ ... regexp_object escaped_source ] */
90460 
90461 	/* In ES2015 .source, and the .global, .multiline, etc flags are
90462 	 * inherited getters.  Store the escaped source as an internal
90463 	 * property for the getter.
90464 	 */
90465 
90466 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_SOURCE, DUK_PROPDESC_FLAGS_NONE);
90467 
90468 	/* [ ... regexp_object ] */
90469 
90470 	duk_push_int(thr, 0);
90471 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LAST_INDEX, DUK_PROPDESC_FLAGS_W);
90472 
90473 	/* [ ... regexp_object ] */
90474 }
90475 
90476 #else  /* DUK_USE_REGEXP_SUPPORT */
90477 
90478 /* regexp support disabled */
90479 
90480 #endif  /* DUK_USE_REGEXP_SUPPORT */
90481 
90482 /* automatic undefs */
90483 #undef DUK__RE_BUFLEN
90484 #undef DUK__RE_INITIAL_BUFSIZE
90485 /*
90486  *  Regexp executor.
90487  *
90488  *  Safety: the ECMAScript executor should prevent user from reading and
90489  *  replacing regexp bytecode.  Even so, the executor must validate all
90490  *  memory accesses etc.  When an invalid access is detected (e.g. a 'save'
90491  *  opcode to invalid, unallocated index) it should fail with an internal
90492  *  error but not cause a segmentation fault.
90493  *
90494  *  Notes:
90495  *
90496  *    - Backtrack counts are limited to unsigned 32 bits but should
90497  *      technically be duk_size_t for strings longer than 4G chars.
90498  *      This also requires a regexp bytecode change.
90499  */
90500 
90501 /* #include duk_internal.h -> already included */
90502 
90503 #if defined(DUK_USE_REGEXP_SUPPORT)
90504 
90505 /*
90506  *  Helpers for UTF-8 handling
90507  *
90508  *  For bytecode readers the duk_uint32_t and duk_int32_t types are correct
90509  *  because they're used for more than just codepoints.
90510  */
90511 
90512 DUK_LOCAL duk_uint32_t duk__bc_get_u32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc) {
90513 	return (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);
90514 }
90515 
90516 DUK_LOCAL duk_int32_t duk__bc_get_i32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc) {
90517 	duk_uint32_t t;
90518 
90519 	/* signed integer encoding needed to work with UTF-8 */
90520 	t = (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);
90521 	if (t & 1) {
90522 		return -((duk_int32_t) (t >> 1));
90523 	} else {
90524 		return (duk_int32_t) (t >> 1);
90525 	}
90526 }
90527 
90528 DUK_LOCAL const duk_uint8_t *duk__utf8_backtrack(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end, duk_uint_fast32_t count) {
90529 	const duk_uint8_t *p;
90530 
90531 	/* Note: allow backtracking from p == ptr_end */
90532 	p = *ptr;
90533 	if (p < ptr_start || p > ptr_end) {
90534 		goto fail;
90535 	}
90536 
90537 	while (count > 0) {
90538 		for (;;) {
90539 			p--;
90540 			if (p < ptr_start) {
90541 				goto fail;
90542 			}
90543 			if ((*p & 0xc0) != 0x80) {
90544 				/* utf-8 continuation bytes have the form 10xx xxxx */
90545 				break;
90546 			}
90547 		}
90548 		count--;
90549 	}
90550 	*ptr = p;
90551 	return p;
90552 
90553  fail:
90554 	DUK_ERROR_INTERNAL(thr);
90555 	DUK_WO_NORETURN(return NULL;);
90556 }
90557 
90558 DUK_LOCAL const duk_uint8_t *duk__utf8_advance(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end, duk_uint_fast32_t count) {
90559 	const duk_uint8_t *p;
90560 
90561 	p = *ptr;
90562 	if (p < ptr_start || p >= ptr_end) {
90563 		goto fail;
90564 	}
90565 
90566 	while (count > 0) {
90567 		for (;;) {
90568 			p++;
90569 
90570 			/* Note: if encoding ends by hitting end of input, we don't check that
90571 			 * the encoding is valid, we just assume it is.
90572 			 */
90573 			if (p >= ptr_end || ((*p & 0xc0) != 0x80)) {
90574 				/* utf-8 continuation bytes have the form 10xx xxxx */
90575 				break;
90576 			}
90577 		}
90578 		count--;
90579 	}
90580 
90581 	*ptr = p;
90582 	return p;
90583 
90584  fail:
90585 	DUK_ERROR_INTERNAL(thr);
90586 	DUK_WO_NORETURN(return NULL;);
90587 }
90588 
90589 /*
90590  *  Helpers for dealing with the input string
90591  */
90592 
90593 /* Get a (possibly canonicalized) input character from current sp.  The input
90594  * itself is never modified, and captures always record non-canonicalized
90595  * characters even in case-insensitive matching.  Return <0 if out of input.
90596  */
90597 DUK_LOCAL duk_codepoint_t duk__inp_get_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **sp) {
90598 	duk_codepoint_t res;
90599 
90600 	if (*sp >= re_ctx->input_end) {
90601 		return -1;
90602 	}
90603 	res = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, sp, re_ctx->input, re_ctx->input_end);
90604 	if (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {
90605 		res = duk_unicode_re_canonicalize_char(re_ctx->thr, res);
90606 	}
90607 	return res;
90608 }
90609 
90610 DUK_LOCAL const duk_uint8_t *duk__inp_backtrack(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **sp, duk_uint_fast32_t count) {
90611 	return duk__utf8_backtrack(re_ctx->thr, sp, re_ctx->input, re_ctx->input_end, count);
90612 }
90613 
90614 /* Backtrack utf-8 input and return a (possibly canonicalized) input character. */
90615 DUK_LOCAL duk_codepoint_t duk__inp_get_prev_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t *sp) {
90616 	/* note: caller 'sp' is intentionally not updated here */
90617 	(void) duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) 1);
90618 	return duk__inp_get_cp(re_ctx, &sp);
90619 }
90620 
90621 /*
90622  *  Regexp recursive matching function.
90623  *
90624  *  Returns 'sp' on successful match (points to character after last matched one),
90625  *  NULL otherwise.
90626  *
90627  *  The C recursion depth limit check is only performed in this function, this
90628  *  suffices because the function is present in all true recursion required by
90629  *  regexp execution.
90630  */
90631 
90632 DUK_LOCAL const duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t *pc, const duk_uint8_t *sp) {
90633 	duk_native_stack_check(re_ctx->thr);
90634 	if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
90635 		DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT);
90636 		DUK_WO_NORETURN(return NULL;);
90637 	}
90638 	re_ctx->recursion_depth++;
90639 
90640 	for (;;) {
90641 		duk_small_int_t op;
90642 
90643 		if (re_ctx->steps_count >= re_ctx->steps_limit) {
90644 			DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT);
90645 			DUK_WO_NORETURN(return NULL;);
90646 		}
90647 		re_ctx->steps_count++;
90648 
90649 		/* Opcodes are at most 7 bits now so they encode to one byte.  If this
90650 		 * were not the case or 'pc' is invalid here (due to a bug etc) we'll
90651 		 * still fail safely through the switch default case.
90652 		 */
90653 		DUK_ASSERT(pc[0] <= 0x7fU);
90654 #if 0
90655 		op = (duk_small_int_t) duk__bc_get_u32(re_ctx, &pc);
90656 #endif
90657 		op = *pc++;
90658 
90659 		DUK_DDD(DUK_DDDPRINT("match: rec=%ld, steps=%ld, pc (after op)=%ld, sp=%ld, op=%ld",
90660 		                     (long) re_ctx->recursion_depth,
90661 		                     (long) re_ctx->steps_count,
90662 		                     (long) (pc - re_ctx->bytecode),
90663 		                     (long) (sp - re_ctx->input),
90664 		                     (long) op));
90665 
90666 		switch (op) {
90667 		case DUK_REOP_MATCH: {
90668 			goto match;
90669 		}
90670 		case DUK_REOP_CHAR: {
90671 			/*
90672 			 *  Byte-based matching would be possible for case-sensitive
90673 			 *  matching but not for case-insensitive matching.  So, we
90674 			 *  match by decoding the input and bytecode character normally.
90675 			 *
90676 			 *  Bytecode characters are assumed to be already canonicalized.
90677 			 *  Input characters are canonicalized automatically by
90678 			 *  duk__inp_get_cp() if necessary.
90679 			 *
90680 			 *  There is no opcode for matching multiple characters.  The
90681 			 *  regexp compiler has trouble joining strings efficiently
90682 			 *  during compilation.  See doc/regexp.rst for more discussion.
90683 			 */
90684 			duk_codepoint_t c1, c2;
90685 
90686 			c1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
90687 			DUK_ASSERT(!(re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) ||
90688 			           c1 == duk_unicode_re_canonicalize_char(re_ctx->thr, c1));  /* canonicalized by compiler */
90689 			c2 = duk__inp_get_cp(re_ctx, &sp);
90690 			/* No need to check for c2 < 0 (end of input): because c1 >= 0, it
90691 			 * will fail the match below automatically and cause goto fail.
90692 			 */
90693 #if 0
90694 			if (c2 < 0) {
90695 				goto fail;
90696 			}
90697 #endif
90698 			DUK_ASSERT(c1 >= 0);
90699 
90700 			DUK_DDD(DUK_DDDPRINT("char match, c1=%ld, c2=%ld", (long) c1, (long) c2));
90701 			if (c1 != c2) {
90702 				goto fail;
90703 			}
90704 			break;
90705 		}
90706 		case DUK_REOP_PERIOD: {
90707 			duk_codepoint_t c;
90708 
90709 			c = duk__inp_get_cp(re_ctx, &sp);
90710 			if (c < 0 || duk_unicode_is_line_terminator(c)) {
90711 				/* E5 Sections 15.10.2.8, 7.3 */
90712 				goto fail;
90713 			}
90714 			break;
90715 		}
90716 		case DUK_REOP_RANGES:
90717 		case DUK_REOP_INVRANGES: {
90718 			duk_uint32_t n;
90719 			duk_codepoint_t c;
90720 			duk_small_int_t match;
90721 
90722 			n = duk__bc_get_u32(re_ctx, &pc);
90723 			c = duk__inp_get_cp(re_ctx, &sp);
90724 			if (c < 0) {
90725 				goto fail;
90726 			}
90727 
90728 			match = 0;
90729 			while (n) {
90730 				duk_codepoint_t r1, r2;
90731 				r1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
90732 				r2 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
90733 				DUK_DDD(DUK_DDDPRINT("matching ranges/invranges, n=%ld, r1=%ld, r2=%ld, c=%ld",
90734 				                     (long) n, (long) r1, (long) r2, (long) c));
90735 				if (c >= r1 && c <= r2) {
90736 					/* Note: don't bail out early, we must read all the ranges from
90737 					 * bytecode.  Another option is to skip them efficiently after
90738 					 * breaking out of here.  Prefer smallest code.
90739 					 */
90740 					match = 1;
90741 				}
90742 				n--;
90743 			}
90744 
90745 			if (op == DUK_REOP_RANGES) {
90746 				if (!match) {
90747 					goto fail;
90748 				}
90749 			} else {
90750 				DUK_ASSERT(op == DUK_REOP_INVRANGES);
90751 				if (match) {
90752 					goto fail;
90753 				}
90754 			}
90755 			break;
90756 		}
90757 		case DUK_REOP_ASSERT_START: {
90758 			duk_codepoint_t c;
90759 
90760 			if (sp <= re_ctx->input) {
90761 				break;
90762 			}
90763 			if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
90764 				goto fail;
90765 			}
90766 			c = duk__inp_get_prev_cp(re_ctx, sp);
90767 			if (duk_unicode_is_line_terminator(c)) {
90768 				/* E5 Sections 15.10.2.8, 7.3 */
90769 				break;
90770 			}
90771 			goto fail;
90772 		}
90773 		case DUK_REOP_ASSERT_END: {
90774 			duk_codepoint_t c;
90775 			const duk_uint8_t *tmp_sp;
90776 
90777 			tmp_sp = sp;
90778 			c = duk__inp_get_cp(re_ctx, &tmp_sp);
90779 			if (c < 0) {
90780 				break;
90781 			}
90782 			if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
90783 				goto fail;
90784 			}
90785 			if (duk_unicode_is_line_terminator(c)) {
90786 				/* E5 Sections 15.10.2.8, 7.3 */
90787 				break;
90788 			}
90789 			goto fail;
90790 		}
90791 		case DUK_REOP_ASSERT_WORD_BOUNDARY:
90792 		case DUK_REOP_ASSERT_NOT_WORD_BOUNDARY: {
90793 			/*
90794 			 *  E5 Section 15.10.2.6.  The previous and current character
90795 			 *  should -not- be canonicalized as they are now.  However,
90796 			 *  canonicalization does not affect the result of IsWordChar()
90797 			 *  (which depends on Unicode characters never canonicalizing
90798 			 *  into ASCII characters) so this does not matter.
90799 			 */
90800 			duk_small_int_t w1, w2;
90801 
90802 			if (sp <= re_ctx->input) {
90803 				w1 = 0;  /* not a wordchar */
90804 			} else {
90805 				duk_codepoint_t c;
90806 				c = duk__inp_get_prev_cp(re_ctx, sp);
90807 				w1 = duk_unicode_re_is_wordchar(c);
90808 			}
90809 			if (sp >= re_ctx->input_end) {
90810 				w2 = 0;  /* not a wordchar */
90811 			} else {
90812 				const duk_uint8_t *tmp_sp = sp;  /* dummy so sp won't get updated */
90813 				duk_codepoint_t c;
90814 				c = duk__inp_get_cp(re_ctx, &tmp_sp);
90815 				w2 = duk_unicode_re_is_wordchar(c);
90816 			}
90817 
90818 			if (op == DUK_REOP_ASSERT_WORD_BOUNDARY) {
90819 				if (w1 == w2) {
90820 					goto fail;
90821 				}
90822 			} else {
90823 				DUK_ASSERT(op == DUK_REOP_ASSERT_NOT_WORD_BOUNDARY);
90824 				if (w1 != w2) {
90825 					goto fail;
90826 				}
90827 			}
90828 			break;
90829 		}
90830 		case DUK_REOP_JUMP: {
90831 			duk_int32_t skip;
90832 
90833 			skip = duk__bc_get_i32(re_ctx, &pc);
90834 			pc += skip;
90835 			break;
90836 		}
90837 		case DUK_REOP_SPLIT1: {
90838 			/* split1: prefer direct execution (no jump) */
90839 			const duk_uint8_t *sub_sp;
90840 			duk_int32_t skip;
90841 
90842 			skip = duk__bc_get_i32(re_ctx, &pc);
90843 			sub_sp = duk__match_regexp(re_ctx, pc, sp);
90844 			if (sub_sp) {
90845 				sp = sub_sp;
90846 				goto match;
90847 			}
90848 			pc += skip;
90849 			break;
90850 		}
90851 		case DUK_REOP_SPLIT2: {
90852 			/* split2: prefer jump execution (not direct) */
90853 			const duk_uint8_t *sub_sp;
90854 			duk_int32_t skip;
90855 
90856 			skip = duk__bc_get_i32(re_ctx, &pc);
90857 			sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
90858 			if (sub_sp) {
90859 				sp = sub_sp;
90860 				goto match;
90861 			}
90862 			break;
90863 		}
90864 		case DUK_REOP_SQMINIMAL: {
90865 			duk_uint32_t q, qmin, qmax;
90866 			duk_int32_t skip;
90867 			const duk_uint8_t *sub_sp;
90868 
90869 			qmin = duk__bc_get_u32(re_ctx, &pc);
90870 			qmax = duk__bc_get_u32(re_ctx, &pc);
90871 			skip = duk__bc_get_i32(re_ctx, &pc);
90872 			DUK_DDD(DUK_DDDPRINT("minimal quantifier, qmin=%lu, qmax=%lu, skip=%ld",
90873 			                     (unsigned long) qmin, (unsigned long) qmax, (long) skip));
90874 
90875 			q = 0;
90876 			while (q <= qmax) {
90877 				if (q >= qmin) {
90878 					sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
90879 					if (sub_sp) {
90880 						sp = sub_sp;
90881 						goto match;
90882 					}
90883 				}
90884 				sub_sp = duk__match_regexp(re_ctx, pc, sp);
90885 				if (!sub_sp) {
90886 					break;
90887 				}
90888 				sp = sub_sp;
90889 				q++;
90890 			}
90891 			goto fail;
90892 		}
90893 		case DUK_REOP_SQGREEDY: {
90894 			duk_uint32_t q, qmin, qmax, atomlen;
90895 			duk_int32_t skip;
90896 			const duk_uint8_t *sub_sp;
90897 
90898 			qmin = duk__bc_get_u32(re_ctx, &pc);
90899 			qmax = duk__bc_get_u32(re_ctx, &pc);
90900 			atomlen = duk__bc_get_u32(re_ctx, &pc);
90901 			skip = duk__bc_get_i32(re_ctx, &pc);
90902 			DUK_DDD(DUK_DDDPRINT("greedy quantifier, qmin=%lu, qmax=%lu, atomlen=%lu, skip=%ld",
90903 			                     (unsigned long) qmin, (unsigned long) qmax, (unsigned long) atomlen, (long) skip));
90904 
90905 			q = 0;
90906 			while (q < qmax) {
90907 				sub_sp = duk__match_regexp(re_ctx, pc, sp);
90908 				if (!sub_sp) {
90909 					break;
90910 				}
90911 				sp = sub_sp;
90912 				q++;
90913 			}
90914 			while (q >= qmin) {
90915 				sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
90916 				if (sub_sp) {
90917 					sp = sub_sp;
90918 					goto match;
90919 				}
90920 				if (q == qmin) {
90921 					break;
90922 				}
90923 
90924 				/* Note: if atom were to contain e.g. captures, we would need to
90925 				 * re-match the atom to get correct captures.  Simply quantifiers
90926 				 * do not allow captures in their atom now, so this is not an issue.
90927 				 */
90928 
90929 				DUK_DDD(DUK_DDDPRINT("greedy quantifier, backtrack %ld characters (atomlen)",
90930 				                     (long) atomlen));
90931 				sp = duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) atomlen);
90932 				q--;
90933 			}
90934 			goto fail;
90935 		}
90936 		case DUK_REOP_SAVE: {
90937 			duk_uint32_t idx;
90938 			const duk_uint8_t *old;
90939 			const duk_uint8_t *sub_sp;
90940 
90941 			idx = duk__bc_get_u32(re_ctx, &pc);
90942 			if (idx >= re_ctx->nsaved) {
90943 				/* idx is unsigned, < 0 check is not necessary */
90944 				DUK_D(DUK_DPRINT("internal error, regexp save index insane: idx=%ld", (long) idx));
90945 				goto internal_error;
90946 			}
90947 			old = re_ctx->saved[idx];
90948 			re_ctx->saved[idx] = sp;
90949 			sub_sp = duk__match_regexp(re_ctx, pc, sp);
90950 			if (sub_sp) {
90951 				sp = sub_sp;
90952 				goto match;
90953 			}
90954 			re_ctx->saved[idx] = old;
90955 			goto fail;
90956 		}
90957 		case DUK_REOP_WIPERANGE: {
90958 			/* Wipe capture range and save old values for backtracking.
90959 			 *
90960 			 * XXX: this typically happens with a relatively small idx_count.
90961 			 * It might be useful to handle cases where the count is small
90962 			 * (say <= 8) by saving the values in stack instead.  This would
90963 			 * reduce memory churn and improve performance, at the cost of a
90964 			 * slightly higher code footprint.
90965 			 */
90966 			duk_uint32_t idx_start, idx_count;
90967 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
90968 			duk_uint32_t idx_end, idx;
90969 #endif
90970 			duk_uint8_t **range_save;
90971 			const duk_uint8_t *sub_sp;
90972 
90973 			idx_start = duk__bc_get_u32(re_ctx, &pc);
90974 			idx_count = duk__bc_get_u32(re_ctx, &pc);
90975 			DUK_DDD(DUK_DDDPRINT("wipe saved range: start=%ld, count=%ld -> [%ld,%ld] (captures [%ld,%ld])",
90976 			                     (long) idx_start, (long) idx_count,
90977 			                     (long) idx_start, (long) (idx_start + idx_count - 1),
90978 			                     (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
90979 			if (idx_start + idx_count > re_ctx->nsaved || idx_count == 0) {
90980 				/* idx is unsigned, < 0 check is not necessary */
90981 				DUK_D(DUK_DPRINT("internal error, regexp wipe indices insane: idx_start=%ld, idx_count=%ld",
90982 				                 (long) idx_start, (long) idx_count));
90983 				goto internal_error;
90984 			}
90985 			DUK_ASSERT(idx_count > 0);
90986 
90987 			duk_require_stack(re_ctx->thr, 1);
90988 			range_save = (duk_uint8_t **) duk_push_fixed_buffer_nozero(re_ctx->thr,
90989 			                                                           sizeof(duk_uint8_t *) * idx_count);
90990 			DUK_ASSERT(range_save != NULL);
90991 			duk_memcpy(range_save, re_ctx->saved + idx_start, sizeof(duk_uint8_t *) * idx_count);
90992 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
90993 			idx_end = idx_start + idx_count;
90994 			for (idx = idx_start; idx < idx_end; idx++) {
90995 				re_ctx->saved[idx] = NULL;
90996 			}
90997 #else
90998 			duk_memzero((void *) (re_ctx->saved + idx_start), sizeof(duk_uint8_t *) * idx_count);
90999 #endif
91000 
91001 			sub_sp = duk__match_regexp(re_ctx, pc, sp);
91002 			if (sub_sp) {
91003 				/* match: keep wiped/resaved values */
91004 				DUK_DDD(DUK_DDDPRINT("match: keep wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
91005 				                     (long) idx_start, (long) (idx_start + idx_count - 1),
91006 			                             (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
91007 				duk_pop_unsafe(re_ctx->thr);
91008 				sp = sub_sp;
91009 				goto match;
91010 			}
91011 
91012 			/* fail: restore saves */
91013 			DUK_DDD(DUK_DDDPRINT("fail: restore wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
91014 			                     (long) idx_start, (long) (idx_start + idx_count - 1),
91015 			                     (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
91016 			duk_memcpy((void *) (re_ctx->saved + idx_start),
91017 			           (const void *) range_save,
91018 			           sizeof(duk_uint8_t *) * idx_count);
91019 			duk_pop_unsafe(re_ctx->thr);
91020 			goto fail;
91021 		}
91022 		case DUK_REOP_LOOKPOS:
91023 		case DUK_REOP_LOOKNEG: {
91024 			/*
91025 			 *  Needs a save of multiple saved[] entries depending on what range
91026 			 *  may be overwritten.  Because the regexp parser does no such analysis,
91027 			 *  we currently save the entire saved array here.  Lookaheads are thus
91028 			 *  a bit expensive.  Note that the saved array is not needed for just
91029 			 *  the lookahead sub-match, but for the matching of the entire sequel.
91030 			 *
91031 			 *  The temporary save buffer is pushed on to the valstack to handle
91032 			 *  errors correctly.  Each lookahead causes a C recursion and pushes
91033 			 *  more stuff on the value stack.  If the C recursion limit is less
91034 			 *  than the value stack slack, there is no need to check the stack.
91035 			 *  We do so regardless, just in case.
91036 			 */
91037 
91038 			duk_int32_t skip;
91039 			duk_uint8_t **full_save;
91040 			const duk_uint8_t *sub_sp;
91041 
91042 			DUK_ASSERT(re_ctx->nsaved > 0);
91043 
91044 			duk_require_stack(re_ctx->thr, 1);
91045 			full_save = (duk_uint8_t **) duk_push_fixed_buffer_nozero(re_ctx->thr,
91046 			                                                          sizeof(duk_uint8_t *) * re_ctx->nsaved);
91047 			DUK_ASSERT(full_save != NULL);
91048 			duk_memcpy(full_save, re_ctx->saved, sizeof(duk_uint8_t *) * re_ctx->nsaved);
91049 
91050 			skip = duk__bc_get_i32(re_ctx, &pc);
91051 			sub_sp = duk__match_regexp(re_ctx, pc, sp);
91052 			if (op == DUK_REOP_LOOKPOS) {
91053 				if (!sub_sp) {
91054 					goto lookahead_fail;
91055 				}
91056 			} else {
91057 				if (sub_sp) {
91058 					goto lookahead_fail;
91059 				}
91060 			}
91061 			sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
91062 			if (sub_sp) {
91063 				/* match: keep saves */
91064 				duk_pop_unsafe(re_ctx->thr);
91065 				sp = sub_sp;
91066 				goto match;
91067 			}
91068 
91069 			/* fall through */
91070 
91071 		 lookahead_fail:
91072 			/* fail: restore saves */
91073 			duk_memcpy((void *) re_ctx->saved,
91074 			           (const void *) full_save,
91075 			           sizeof(duk_uint8_t *) * re_ctx->nsaved);
91076 			duk_pop_unsafe(re_ctx->thr);
91077 			goto fail;
91078 		}
91079 		case DUK_REOP_BACKREFERENCE: {
91080 			/*
91081 			 *  Byte matching for back-references would be OK in case-
91082 			 *  sensitive matching.  In case-insensitive matching we need
91083 			 *  to canonicalize characters, so back-reference matching needs
91084 			 *  to be done with codepoints instead.  So, we just decode
91085 			 *  everything normally here, too.
91086 			 *
91087 			 *  Note: back-reference index which is 0 or higher than
91088 			 *  NCapturingParens (= number of capturing parens in the
91089 			 *  -entire- regexp) is a compile time error.  However, a
91090 			 *  backreference referring to a valid capture which has
91091 			 *  not matched anything always succeeds!  See E5 Section
91092 			 *  15.10.2.9, step 5, sub-step 3.
91093 			 */
91094 			duk_uint32_t idx;
91095 			const duk_uint8_t *p;
91096 
91097 			idx = duk__bc_get_u32(re_ctx, &pc);
91098 			idx = idx << 1;  /* backref n -> saved indices [n*2, n*2+1] */
91099 			if (idx < 2 || idx + 1 >= re_ctx->nsaved) {
91100 				/* regexp compiler should catch these */
91101 				DUK_D(DUK_DPRINT("internal error, backreference index insane"));
91102 				goto internal_error;
91103 			}
91104 			if (!re_ctx->saved[idx] || !re_ctx->saved[idx+1]) {
91105 				/* capture is 'undefined', always matches! */
91106 				DUK_DDD(DUK_DDDPRINT("backreference: saved[%ld,%ld] not complete, always match",
91107 				                     (long) idx, (long) (idx + 1)));
91108 				break;
91109 			}
91110 			DUK_DDD(DUK_DDDPRINT("backreference: match saved[%ld,%ld]", (long) idx, (long) (idx + 1)));
91111 
91112 			p = re_ctx->saved[idx];
91113 			while (p < re_ctx->saved[idx+1]) {
91114 				duk_codepoint_t c1, c2;
91115 
91116 				/* Note: not necessary to check p against re_ctx->input_end:
91117 				 * the memory access is checked by duk__inp_get_cp(), while
91118 				 * valid compiled regexps cannot write a saved[] entry
91119 				 * which points to outside the string.
91120 				 */
91121 				c1 = duk__inp_get_cp(re_ctx, &p);
91122 				DUK_ASSERT(c1 >= 0);
91123 				c2 = duk__inp_get_cp(re_ctx, &sp);
91124 				/* No need for an explicit c2 < 0 check: because c1 >= 0,
91125 				 * the comparison will always fail if c2 < 0.
91126 				 */
91127 #if 0
91128 				if (c2 < 0) {
91129 					goto fail;
91130 				}
91131 #endif
91132 				if (c1 != c2) {
91133 					goto fail;
91134 				}
91135 			}
91136 			break;
91137 		}
91138 		default: {
91139 			DUK_D(DUK_DPRINT("internal error, regexp opcode error: %ld", (long) op));
91140 			goto internal_error;
91141 		}
91142 		}
91143 	}
91144 
91145  match:
91146 	re_ctx->recursion_depth--;
91147 	return sp;
91148 
91149  fail:
91150 	re_ctx->recursion_depth--;
91151 	return NULL;
91152 
91153  internal_error:
91154 	DUK_ERROR_INTERNAL(re_ctx->thr);
91155 	DUK_WO_NORETURN(return NULL;);
91156 }
91157 
91158 /*
91159  *  Exposed matcher function which provides the semantics of RegExp.prototype.exec().
91160  *
91161  *  RegExp.prototype.test() has the same semantics as exec() but does not return the
91162  *  result object (which contains the matching string and capture groups).  Currently
91163  *  there is no separate test() helper, so a temporary result object is created and
91164  *  discarded if test() is needed.  This is intentional, to save code space.
91165  *
91166  *  Input stack:  [ ... re_obj input ]
91167  *  Output stack: [ ... result ]
91168  */
91169 
91170 DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_global) {
91171 	duk_re_matcher_ctx re_ctx;
91172 	duk_hobject *h_regexp;
91173 	duk_hstring *h_bytecode;
91174 	duk_hstring *h_input;
91175 	duk_uint8_t *p_buf;
91176 	const duk_uint8_t *pc;
91177 	const duk_uint8_t *sp;
91178 	duk_small_int_t match = 0;
91179 	duk_small_int_t global;
91180 	duk_uint_fast32_t i;
91181 	double d;
91182 	duk_uint32_t char_offset;
91183 
91184 	DUK_ASSERT(thr != NULL);
91185 
91186 	DUK_DD(DUK_DDPRINT("regexp match: regexp=%!T, input=%!T",
91187 	                   (duk_tval *) duk_get_tval(thr, -2),
91188 	                   (duk_tval *) duk_get_tval(thr, -1)));
91189 
91190 	/*
91191 	 *  Regexp instance check, bytecode check, input coercion.
91192 	 *
91193 	 *  See E5 Section 15.10.6.
91194 	 */
91195 
91196 	/* TypeError if wrong; class check, see E5 Section 15.10.6 */
91197 	h_regexp = duk_require_hobject_with_class(thr, -2, DUK_HOBJECT_CLASS_REGEXP);
91198 	DUK_ASSERT(h_regexp != NULL);
91199 	DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_regexp) == DUK_HOBJECT_CLASS_REGEXP);
91200 	DUK_UNREF(h_regexp);
91201 
91202 	h_input = duk_to_hstring(thr, -1);
91203 	DUK_ASSERT(h_input != NULL);
91204 
91205 	duk_xget_owndataprop_stridx_short(thr, -2, DUK_STRIDX_INT_BYTECODE);  /* [ ... re_obj input ] -> [ ... re_obj input bc ] */
91206 	h_bytecode = duk_require_hstring(thr, -1);  /* no regexp instance should exist without a non-configurable bytecode property */
91207 	DUK_ASSERT(h_bytecode != NULL);
91208 
91209 	/*
91210 	 *  Basic context initialization.
91211 	 *
91212 	 *  Some init values are read from the bytecode header
91213 	 *  whose format is (UTF-8 codepoints):
91214 	 *
91215 	 *    uint   flags
91216 	 *    uint   nsaved (even, 2n+2 where n = num captures)
91217 	 */
91218 
91219 	/* [ ... re_obj input bc ] */
91220 
91221 	duk_memzero(&re_ctx, sizeof(re_ctx));
91222 
91223 	re_ctx.thr = thr;
91224 	re_ctx.input = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
91225 	re_ctx.input_end = re_ctx.input + DUK_HSTRING_GET_BYTELEN(h_input);
91226 	re_ctx.bytecode = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_bytecode);
91227 	re_ctx.bytecode_end = re_ctx.bytecode + DUK_HSTRING_GET_BYTELEN(h_bytecode);
91228 	re_ctx.saved = NULL;
91229 	re_ctx.recursion_limit = DUK_USE_REGEXP_EXECUTOR_RECLIMIT;
91230 	re_ctx.steps_limit = DUK_RE_EXECUTE_STEPS_LIMIT;
91231 
91232 	/* read header */
91233 	pc = re_ctx.bytecode;
91234 	re_ctx.re_flags = duk__bc_get_u32(&re_ctx, &pc);
91235 	re_ctx.nsaved = duk__bc_get_u32(&re_ctx, &pc);
91236 	re_ctx.bytecode = pc;
91237 
91238 	DUK_ASSERT(DUK_RE_FLAG_GLOBAL < 0x10000UL);  /* must fit into duk_small_int_t */
91239 	global = (duk_small_int_t) (force_global | (duk_small_int_t) (re_ctx.re_flags & DUK_RE_FLAG_GLOBAL));
91240 
91241 	DUK_ASSERT(re_ctx.nsaved >= 2);
91242 	DUK_ASSERT((re_ctx.nsaved % 2) == 0);
91243 
91244 	p_buf = (duk_uint8_t *) duk_push_fixed_buffer(thr, sizeof(duk_uint8_t *) * re_ctx.nsaved);  /* rely on zeroing */
91245 	DUK_UNREF(p_buf);
91246 	re_ctx.saved = (const duk_uint8_t **) duk_get_buffer(thr, -1, NULL);
91247 	DUK_ASSERT(re_ctx.saved != NULL);
91248 
91249 	/* [ ... re_obj input bc saved_buf ] */
91250 
91251 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
91252 	for (i = 0; i < re_ctx.nsaved; i++) {
91253 		re_ctx.saved[i] = (duk_uint8_t *) NULL;
91254 	}
91255 #elif defined(DUK_USE_ZERO_BUFFER_DATA)
91256 	/* buffer is automatically zeroed */
91257 #else
91258 	duk_memzero((void *) p_buf, sizeof(duk_uint8_t *) * re_ctx.nsaved);
91259 #endif
91260 
91261 	DUK_DDD(DUK_DDDPRINT("regexp ctx initialized, flags=0x%08lx, nsaved=%ld, recursion_limit=%ld, steps_limit=%ld",
91262 	                     (unsigned long) re_ctx.re_flags, (long) re_ctx.nsaved, (long) re_ctx.recursion_limit,
91263 	                     (long) re_ctx.steps_limit));
91264 
91265 	/*
91266 	 *  Get starting character offset for match, and initialize 'sp' based on it.
91267 	 *
91268 	 *  Note: lastIndex is non-configurable so it must be present (we check the
91269 	 *  internal class of the object above, so we know it is).  User code can set
91270 	 *  its value to an arbitrary (garbage) value though; E5 requires that lastIndex
91271 	 *  be coerced to a number before using.  The code below works even if the
91272 	 *  property is missing: the value will then be coerced to zero.
91273 	 *
91274 	 *  Note: lastIndex may be outside Uint32 range even after ToInteger() coercion.
91275 	 *  For instance, ToInteger(+Infinity) = +Infinity.  We track the match offset
91276 	 *  as an integer, but pre-check it to be inside the 32-bit range before the loop.
91277 	 *  If not, the check in E5 Section 15.10.6.2, step 9.a applies.
91278 	 */
91279 
91280 	/* XXX: lastIndex handling produces a lot of asm */
91281 
91282 	/* [ ... re_obj input bc saved_buf ] */
91283 
91284 	duk_get_prop_stridx_short(thr, -4, DUK_STRIDX_LAST_INDEX);  /* -> [ ... re_obj input bc saved_buf lastIndex ] */
91285 	(void) duk_to_int(thr, -1);  /* ToInteger(lastIndex) */
91286 	d = duk_get_number(thr, -1);  /* integer, but may be +/- Infinite, +/- zero (not NaN, though) */
91287 	duk_pop_nodecref_unsafe(thr);
91288 
91289 	if (global) {
91290 		if (d < 0.0 || d > (double) DUK_HSTRING_GET_CHARLEN(h_input)) {
91291 			/* match fail */
91292 			char_offset = 0;   /* not really necessary */
91293 			DUK_ASSERT(match == 0);
91294 			goto match_over;
91295 		}
91296 		char_offset = (duk_uint32_t) d;
91297 	} else {
91298 		/* lastIndex must be ignored for non-global regexps, but get the
91299 		 * value for (theoretical) side effects.  No side effects can
91300 		 * really occur, because lastIndex is a normal property and is
91301 		 * always non-configurable for RegExp instances.
91302 		 */
91303 		char_offset = (duk_uint32_t) 0;
91304 	}
91305 
91306 	DUK_ASSERT(char_offset <= DUK_HSTRING_GET_CHARLEN(h_input));
91307 	sp = re_ctx.input + duk_heap_strcache_offset_char2byte(thr, h_input, char_offset);
91308 
91309 	/*
91310 	 *  Match loop.
91311 	 *
91312 	 *  Try matching at different offsets until match found or input exhausted.
91313 	 */
91314 
91315 	/* [ ... re_obj input bc saved_buf ] */
91316 
91317 	DUK_ASSERT(match == 0);
91318 
91319 	for (;;) {
91320 		/* char offset in [0, h_input->clen] (both ends inclusive), checked before entry */
91321 		DUK_ASSERT_DISABLE(char_offset >= 0);
91322 		DUK_ASSERT(char_offset <= DUK_HSTRING_GET_CHARLEN(h_input));
91323 
91324 		/* Note: re_ctx.steps is intentionally not reset, it applies to the entire unanchored match */
91325 		DUK_ASSERT(re_ctx.recursion_depth == 0);
91326 
91327 		DUK_DDD(DUK_DDDPRINT("attempt match at char offset %ld; %p [%p,%p]",
91328 		                     (long) char_offset, (const void *) sp,
91329 		                     (const void *) re_ctx.input, (const void *) re_ctx.input_end));
91330 
91331 		/*
91332 		 *  Note:
91333 		 *
91334 		 *    - duk__match_regexp() is required not to longjmp() in ordinary "non-match"
91335 		 *      conditions; a longjmp() will terminate the entire matching process.
91336 		 *
91337 		 *    - Clearing saved[] is not necessary because backtracking does it
91338 		 *
91339 		 *    - Backtracking also rewinds re_ctx.recursion back to zero, unless an
91340 		 *      internal/limit error occurs (which causes a longjmp())
91341 		 *
91342 		 *    - If we supported anchored matches, we would break out here
91343 		 *      unconditionally; however, ECMAScript regexps don't have anchored
91344 		 *      matches.  It might make sense to implement a fast bail-out if
91345 		 *      the regexp begins with '^' and sp is not 0: currently we'll just
91346 		 *      run through the entire input string, trivially failing the match
91347 		 *      at every non-zero offset.
91348 		 */
91349 
91350 		if (duk__match_regexp(&re_ctx, re_ctx.bytecode, sp) != NULL) {
91351 			DUK_DDD(DUK_DDDPRINT("match at offset %ld", (long) char_offset));
91352 			match = 1;
91353 			break;
91354 		}
91355 
91356 		/* advance by one character (code point) and one char_offset */
91357 		char_offset++;
91358 		if (char_offset > DUK_HSTRING_GET_CHARLEN(h_input)) {
91359 			/*
91360 			 *  Note:
91361 			 *
91362 			 *    - Intentionally attempt (empty) match at char_offset == k_input->clen
91363 			 *
91364 			 *    - Negative char_offsets have been eliminated and char_offset is duk_uint32_t
91365 			 *      -> no need or use for a negative check
91366 			 */
91367 
91368 			DUK_DDD(DUK_DDDPRINT("no match after trying all sp offsets"));
91369 			break;
91370 		}
91371 
91372 		/* avoid calling at end of input, will DUK_ERROR (above check suffices to avoid this) */
91373 		(void) duk__utf8_advance(thr, &sp, re_ctx.input, re_ctx.input_end, (duk_uint_fast32_t) 1);
91374 	}
91375 
91376  match_over:
91377 
91378 	/*
91379 	 *  Matching complete, create result array or return a 'null'.  Update lastIndex
91380 	 *  if necessary.  See E5 Section 15.10.6.2.
91381 	 *
91382 	 *  Because lastIndex is a character (not byte) offset, we need the character
91383 	 *  length of the match which we conveniently get as a side effect of interning
91384 	 *  the matching substring (0th index of result array).
91385 	 *
91386 	 *  saved[0]         start pointer (~ byte offset) of current match
91387 	 *  saved[1]         end pointer (~ byte offset) of current match (exclusive)
91388 	 *  char_offset      start character offset of current match (-> .index of result)
91389 	 *  char_end_offset  end character offset (computed below)
91390 	 */
91391 
91392 	/* [ ... re_obj input bc saved_buf ] */
91393 
91394 	if (match) {
91395 #if defined(DUK_USE_ASSERTIONS)
91396 		duk_hobject *h_res;
91397 #endif
91398 		duk_uint32_t char_end_offset = 0;
91399 
91400 		DUK_DDD(DUK_DDDPRINT("regexp matches at char_offset %ld", (long) char_offset));
91401 
91402 		DUK_ASSERT(re_ctx.nsaved >= 2);        /* must have start and end */
91403 		DUK_ASSERT((re_ctx.nsaved % 2) == 0);  /* and even number */
91404 
91405 		/* XXX: Array size is known before and (2 * re_ctx.nsaved) but not taken
91406 		 * advantage of now.  The array is not compacted either, as regexp match
91407 		 * objects are usually short lived.
91408 		 */
91409 
91410 		duk_push_array(thr);
91411 
91412 #if defined(DUK_USE_ASSERTIONS)
91413 		h_res = duk_require_hobject(thr, -1);
91414 		DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h_res));
91415 		DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(h_res));
91416 		DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_res) == DUK_HOBJECT_CLASS_ARRAY);
91417 #endif
91418 
91419 		/* [ ... re_obj input bc saved_buf res_obj ] */
91420 
91421 		duk_push_u32(thr, char_offset);
91422 		duk_xdef_prop_stridx_short_wec(thr, -2, DUK_STRIDX_INDEX);
91423 
91424 		duk_dup_m4(thr);
91425 		duk_xdef_prop_stridx_short_wec(thr, -2, DUK_STRIDX_INPUT);
91426 
91427 		for (i = 0; i < re_ctx.nsaved; i += 2) {
91428 			/* Captures which are undefined have NULL pointers and are returned
91429 			 * as 'undefined'.  The same is done when saved[] pointers are insane
91430 			 * (this should, of course, never happen in practice).
91431 			 */
91432 			duk_push_uarridx(thr, (duk_uarridx_t) (i / 2));
91433 
91434 			if (re_ctx.saved[i] && re_ctx.saved[i + 1] && re_ctx.saved[i + 1] >= re_ctx.saved[i]) {
91435 				duk_push_lstring(thr,
91436 				                 (const char *) re_ctx.saved[i],
91437 				                 (duk_size_t) (re_ctx.saved[i + 1] - re_ctx.saved[i]));
91438 				if (i == 0) {
91439 					/* Assumes that saved[0] and saved[1] are always
91440 					 * set by regexp bytecode (if not, char_end_offset
91441 					 * will be zero).  Also assumes clen reflects the
91442 					 * correct char length.
91443 					 */
91444 					char_end_offset = char_offset + (duk_uint32_t) duk_get_length(thr, -1);  /* add charlen */
91445 				}
91446 			} else {
91447 				duk_push_undefined(thr);
91448 			}
91449 
91450 			/* [ ... re_obj input bc saved_buf res_obj idx val ] */
91451 			duk_def_prop(thr, -3, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_SET_WEC);
91452 		}
91453 
91454 		/* [ ... re_obj input bc saved_buf res_obj ] */
91455 
91456 		/* NB: 'length' property is automatically updated by the array setup loop */
91457 
91458 		if (global) {
91459 			/* global regexp: lastIndex updated on match */
91460 			duk_push_u32(thr, char_end_offset);
91461 			duk_put_prop_stridx_short(thr, -6, DUK_STRIDX_LAST_INDEX);
91462 		} else {
91463 			/* non-global regexp: lastIndex never updated on match */
91464 			;
91465 		}
91466 	} else {
91467 		/*
91468 		 *  No match, E5 Section 15.10.6.2, step 9.a.i - 9.a.ii apply, regardless
91469 		 *  of 'global' flag of the RegExp.  In particular, if lastIndex is invalid
91470 		 *  initially, it is reset to zero.
91471 		 */
91472 
91473 		DUK_DDD(DUK_DDDPRINT("regexp does not match"));
91474 
91475 		duk_push_null(thr);
91476 
91477 		/* [ ... re_obj input bc saved_buf res_obj ] */
91478 
91479 		duk_push_int(thr, 0);
91480 		duk_put_prop_stridx_short(thr, -6, DUK_STRIDX_LAST_INDEX);
91481 	}
91482 
91483 	/* [ ... re_obj input bc saved_buf res_obj ] */
91484 
91485 	duk_insert(thr, -5);
91486 
91487 	/* [ ... res_obj re_obj input bc saved_buf ] */
91488 
91489 	duk_pop_n_unsafe(thr, 4);
91490 
91491 	/* [ ... res_obj ] */
91492 
91493 	/* XXX: these last tricks are unnecessary if the function is made
91494 	 * a genuine native function.
91495 	 */
91496 }
91497 
91498 DUK_INTERNAL void duk_regexp_match(duk_hthread *thr) {
91499 	duk__regexp_match_helper(thr, 0 /*force_global*/);
91500 }
91501 
91502 /* This variant is needed by String.prototype.split(); it needs to perform
91503  * global-style matching on a cloned RegExp which is potentially non-global.
91504  */
91505 DUK_INTERNAL void duk_regexp_match_force_global(duk_hthread *thr) {
91506 	duk__regexp_match_helper(thr, 1 /*force_global*/);
91507 }
91508 
91509 #else  /* DUK_USE_REGEXP_SUPPORT */
91510 
91511 /* regexp support disabled */
91512 
91513 #endif  /* DUK_USE_REGEXP_SUPPORT */
91514 /*
91515  *  Self tests to ensure execution environment is sane.  Intended to catch
91516  *  compiler/platform problems which cannot be detected at compile time.
91517  */
91518 
91519 /* #include duk_internal.h -> already included */
91520 
91521 #if defined(DUK_USE_SELF_TESTS)
91522 
91523 /*
91524  *  Unions and structs for self tests
91525  */
91526 
91527 typedef union {
91528 	double d;
91529 	duk_uint8_t x[8];
91530 } duk__test_double_union;
91531 
91532 /* Self test failed.  Expects a local variable 'error_count' to exist. */
91533 #define DUK__FAILED(msg)  do { \
91534 		DUK_D(DUK_DPRINT("self test failed: " #msg " at " DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO))); \
91535 		error_count++; \
91536 	} while (0)
91537 
91538 #define DUK__DBLUNION_CMP_TRUE(a,b)  do { \
91539 		if (duk_memcmp((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) != 0) { \
91540 			DUK__FAILED("double union compares false (expected true)"); \
91541 		} \
91542 	} while (0)
91543 
91544 #define DUK__DBLUNION_CMP_FALSE(a,b)  do { \
91545 		if (duk_memcmp((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) == 0) { \
91546 			DUK__FAILED("double union compares true (expected false)"); \
91547 		} \
91548 	} while (0)
91549 
91550 typedef union {
91551 	duk_uint32_t i;
91552 	duk_uint8_t x[8];
91553 } duk__test_u32_union;
91554 
91555 #if defined(DUK_USE_INTEGER_LE)
91556 #define DUK__U32_INIT(u, a, b, c, d) do { \
91557 		(u)->x[0] = (d); (u)->x[1] = (c); (u)->x[2] = (b); (u)->x[3] = (a); \
91558 	} while (0)
91559 #elif defined(DUK_USE_INTEGER_ME)
91560 #error integer mixed endian not supported now
91561 #elif defined(DUK_USE_INTEGER_BE)
91562 #define DUK__U32_INIT(u, a, b, c, d) do { \
91563 		(u)->x[0] = (a); (u)->x[1] = (b); (u)->x[2] = (c); (u)->x[3] = (d); \
91564 	} while (0)
91565 #else
91566 #error unknown integer endianness
91567 #endif
91568 
91569 #if defined(DUK_USE_DOUBLE_LE)
91570 #define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) do { \
91571 		(u)->x[0] = (h); (u)->x[1] = (g); (u)->x[2] = (f); (u)->x[3] = (e); \
91572 		(u)->x[4] = (d); (u)->x[5] = (c); (u)->x[6] = (b); (u)->x[7] = (a); \
91573 	} while (0)
91574 #define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \
91575 	((u)->x[0] == (h) && (u)->x[1] == (g) && (u)->x[2] == (f) && (u)->x[3] == (e) && \
91576 	 (u)->x[4] == (d) && (u)->x[5] == (c) && (u)->x[6] == (b) && (u)->x[7] == (a))
91577 #elif defined(DUK_USE_DOUBLE_ME)
91578 #define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) do { \
91579 		(u)->x[0] = (d); (u)->x[1] = (c); (u)->x[2] = (b); (u)->x[3] = (a); \
91580 		(u)->x[4] = (h); (u)->x[5] = (g); (u)->x[6] = (f); (u)->x[7] = (e); \
91581 	} while (0)
91582 #define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \
91583 	((u)->x[0] == (d) && (u)->x[1] == (c) && (u)->x[2] == (b) && (u)->x[3] == (a) && \
91584 	 (u)->x[4] == (h) && (u)->x[5] == (g) && (u)->x[6] == (f) && (u)->x[7] == (e))
91585 #elif defined(DUK_USE_DOUBLE_BE)
91586 #define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) do { \
91587 		(u)->x[0] = (a); (u)->x[1] = (b); (u)->x[2] = (c); (u)->x[3] = (d); \
91588 		(u)->x[4] = (e); (u)->x[5] = (f); (u)->x[6] = (g); (u)->x[7] = (h); \
91589 	} while (0)
91590 #define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \
91591 	((u)->x[0] == (a) && (u)->x[1] == (b) && (u)->x[2] == (c) && (u)->x[3] == (d) && \
91592 	 (u)->x[4] == (e) && (u)->x[5] == (f) && (u)->x[6] == (g) && (u)->x[7] == (h))
91593 #else
91594 #error unknown double endianness
91595 #endif
91596 
91597 /*
91598  *  Various sanity checks for typing
91599  */
91600 
91601 DUK_LOCAL duk_uint_t duk__selftest_types(void) {
91602 	duk_uint_t error_count = 0;
91603 
91604 	if (!(sizeof(duk_int8_t) == 1 &&
91605 	      sizeof(duk_uint8_t) == 1 &&
91606 	      sizeof(duk_int16_t) == 2 &&
91607 	      sizeof(duk_uint16_t) == 2 &&
91608 	      sizeof(duk_int32_t) == 4 &&
91609 	      sizeof(duk_uint32_t) == 4)) {
91610 		DUK__FAILED("duk_(u)int{8,16,32}_t size");
91611 	}
91612 #if defined(DUK_USE_64BIT_OPS)
91613 	if (!(sizeof(duk_int64_t) == 8 &&
91614 	      sizeof(duk_uint64_t) == 8)) {
91615 		DUK__FAILED("duk_(u)int64_t size");
91616 	}
91617 #endif
91618 
91619 	if (!(sizeof(duk_size_t) >= sizeof(duk_uint_t))) {
91620 		/* Some internal code now assumes that all duk_uint_t values
91621 		 * can be expressed with a duk_size_t.
91622 		 */
91623 		DUK__FAILED("duk_size_t is smaller than duk_uint_t");
91624 	}
91625 	if (!(sizeof(duk_int_t) >= 4)) {
91626 		DUK__FAILED("duk_int_t is not 32 bits");
91627 	}
91628 
91629 	return error_count;
91630 }
91631 
91632 /*
91633  *  Packed tval sanity
91634  */
91635 
91636 DUK_LOCAL duk_uint_t duk__selftest_packed_tval(void) {
91637 	duk_uint_t error_count = 0;
91638 
91639 #if defined(DUK_USE_PACKED_TVAL)
91640 	if (sizeof(void *) > 4) {
91641 		DUK__FAILED("packed duk_tval in use but sizeof(void *) > 4");
91642 	}
91643 #endif
91644 
91645 	return error_count;
91646 }
91647 
91648 /*
91649  *  Two's complement arithmetic.
91650  */
91651 
91652 DUK_LOCAL duk_uint_t duk__selftest_twos_complement(void) {
91653 	duk_uint_t error_count = 0;
91654 	volatile int test;
91655 	test = -1;
91656 
91657 	/* Note that byte order doesn't affect this test: all bytes in
91658 	 * 'test' will be 0xFF for two's complement.
91659 	 */
91660 	if (((volatile duk_uint8_t *) &test)[0] != (duk_uint8_t) 0xff) {
91661 		DUK__FAILED("two's complement arithmetic");
91662 	}
91663 
91664 	return error_count;
91665 }
91666 
91667 /*
91668  *  Byte order.  Important to self check, because on some exotic platforms
91669  *  there is no actual detection but rather assumption based on platform
91670  *  defines.
91671  */
91672 
91673 DUK_LOCAL duk_uint_t duk__selftest_byte_order(void) {
91674 	duk_uint_t error_count = 0;
91675 	duk__test_u32_union u1;
91676 	duk__test_double_union u2;
91677 
91678 	/*
91679 	 *  >>> struct.pack('>d', 102030405060).encode('hex')
91680 	 *  '4237c17c6dc40000'
91681 	 */
91682 
91683 	DUK__U32_INIT(&u1, 0xde, 0xad, 0xbe, 0xef);
91684 	DUK__DOUBLE_INIT(&u2, 0x42, 0x37, 0xc1, 0x7c, 0x6d, 0xc4, 0x00, 0x00);
91685 
91686 	if (u1.i != (duk_uint32_t) 0xdeadbeefUL) {
91687 		DUK__FAILED("duk_uint32_t byte order");
91688 	}
91689 
91690 	if (!duk_double_equals(u2.d, 102030405060.0)) {
91691 		DUK__FAILED("double byte order");
91692 	}
91693 
91694 	return error_count;
91695 }
91696 
91697 /*
91698  *  DUK_BSWAP macros
91699  */
91700 
91701 DUK_LOCAL duk_uint_t duk__selftest_bswap_macros(void) {
91702 	duk_uint_t error_count = 0;
91703 	volatile duk_uint32_t x32_input, x32_output;
91704 	duk_uint32_t x32;
91705 	volatile duk_uint16_t x16_input, x16_output;
91706 	duk_uint16_t x16;
91707 	duk_double_union du;
91708 	duk_double_t du_diff;
91709 #if defined(DUK_BSWAP64)
91710 	volatile duk_uint64_t x64_input, x64_output;
91711 	duk_uint64_t x64;
91712 #endif
91713 
91714 	/* Cover both compile time and runtime bswap operations, as these
91715 	 * may have different bugs.
91716 	 */
91717 
91718 	x16_input = 0xbeefUL;
91719 	x16 = x16_input;
91720 	x16 = DUK_BSWAP16(x16);
91721 	x16_output = x16;
91722 	if (x16_output != (duk_uint16_t) 0xefbeUL) {
91723 		DUK__FAILED("DUK_BSWAP16");
91724 	}
91725 
91726 	x16 = 0xbeefUL;
91727 	x16 = DUK_BSWAP16(x16);
91728 	if (x16 != (duk_uint16_t) 0xefbeUL) {
91729 		DUK__FAILED("DUK_BSWAP16");
91730 	}
91731 
91732 	x32_input = 0xdeadbeefUL;
91733 	x32 = x32_input;
91734 	x32 = DUK_BSWAP32(x32);
91735 	x32_output = x32;
91736 	if (x32_output != (duk_uint32_t) 0xefbeaddeUL) {
91737 		DUK__FAILED("DUK_BSWAP32");
91738 	}
91739 
91740 	x32 = 0xdeadbeefUL;
91741 	x32 = DUK_BSWAP32(x32);
91742 	if (x32 != (duk_uint32_t) 0xefbeaddeUL) {
91743 		DUK__FAILED("DUK_BSWAP32");
91744 	}
91745 
91746 #if defined(DUK_BSWAP64)
91747 	x64_input = DUK_U64_CONSTANT(0x8899aabbccddeeff);
91748 	x64 = x64_input;
91749 	x64 = DUK_BSWAP64(x64);
91750 	x64_output = x64;
91751 	if (x64_output != (duk_uint64_t) DUK_U64_CONSTANT(0xffeeddccbbaa9988)) {
91752 		DUK__FAILED("DUK_BSWAP64");
91753 	}
91754 
91755 	x64 = DUK_U64_CONSTANT(0x8899aabbccddeeff);
91756 	x64 = DUK_BSWAP64(x64);
91757 	if (x64 != (duk_uint64_t) DUK_U64_CONSTANT(0xffeeddccbbaa9988)) {
91758 		DUK__FAILED("DUK_BSWAP64");
91759 	}
91760 #endif
91761 
91762 	/* >>> struct.unpack('>d', '4000112233445566'.decode('hex'))
91763 	 * (2.008366013071895,)
91764 	 */
91765 
91766 	du.uc[0] = 0x40; du.uc[1] = 0x00; du.uc[2] = 0x11; du.uc[3] = 0x22;
91767 	du.uc[4] = 0x33; du.uc[5] = 0x44; du.uc[6] = 0x55; du.uc[7] = 0x66;
91768 	DUK_DBLUNION_DOUBLE_NTOH(&du);
91769 	du_diff = du.d - 2.008366013071895;
91770 #if 0
91771 	DUK_D(DUK_DPRINT("du_diff: %lg\n", (double) du_diff));
91772 #endif
91773 	if (du_diff > 1e-15) {
91774 		/* Allow very small lenience because some compilers won't parse
91775 		 * exact IEEE double constants (happened in matrix testing with
91776 		 * Linux gcc-4.8 -m32 at least).
91777 		 */
91778 #if 0
91779 		DUK_D(DUK_DPRINT("Result of DUK_DBLUNION_DOUBLE_NTOH: %02x %02x %02x %02x %02x %02x %02x %02x\n",
91780 		            (unsigned int) du.uc[0], (unsigned int) du.uc[1],
91781 		            (unsigned int) du.uc[2], (unsigned int) du.uc[3],
91782 		            (unsigned int) du.uc[4], (unsigned int) du.uc[5],
91783 		            (unsigned int) du.uc[6], (unsigned int) du.uc[7]));
91784 #endif
91785 		DUK__FAILED("DUK_DBLUNION_DOUBLE_NTOH");
91786 	}
91787 
91788 	return error_count;
91789 }
91790 
91791 /*
91792  *  Basic double / byte union memory layout.
91793  */
91794 
91795 DUK_LOCAL duk_uint_t duk__selftest_double_union_size(void) {
91796 	duk_uint_t error_count = 0;
91797 
91798 	if (sizeof(duk__test_double_union) != 8) {
91799 		DUK__FAILED("invalid union size");
91800 	}
91801 
91802 	return error_count;
91803 }
91804 
91805 /*
91806  *  Union aliasing, see misc/clang_aliasing.c.
91807  */
91808 
91809 DUK_LOCAL duk_uint_t duk__selftest_double_aliasing(void) {
91810 	/* This testcase fails when Emscripten-generated code runs on Firefox.
91811 	 * It's not an issue because the failure should only affect packed
91812 	 * duk_tval representation, which is not used with Emscripten.
91813 	 */
91814 #if defined(DUK_USE_PACKED_TVAL)
91815 	duk_uint_t error_count = 0;
91816 	duk__test_double_union a, b;
91817 
91818 	/* Test signaling NaN and alias assignment in all endianness combinations.
91819 	 */
91820 
91821 	/* little endian */
91822 	a.x[0] = 0x11; a.x[1] = 0x22; a.x[2] = 0x33; a.x[3] = 0x44;
91823 	a.x[4] = 0x00; a.x[5] = 0x00; a.x[6] = 0xf1; a.x[7] = 0xff;
91824 	b = a;
91825 	DUK__DBLUNION_CMP_TRUE(&a, &b);
91826 
91827 	/* big endian */
91828 	a.x[0] = 0xff; a.x[1] = 0xf1; a.x[2] = 0x00; a.x[3] = 0x00;
91829 	a.x[4] = 0x44; a.x[5] = 0x33; a.x[6] = 0x22; a.x[7] = 0x11;
91830 	b = a;
91831 	DUK__DBLUNION_CMP_TRUE(&a, &b);
91832 
91833 	/* mixed endian */
91834 	a.x[0] = 0x00; a.x[1] = 0x00; a.x[2] = 0xf1; a.x[3] = 0xff;
91835 	a.x[4] = 0x11; a.x[5] = 0x22; a.x[6] = 0x33; a.x[7] = 0x44;
91836 	b = a;
91837 	DUK__DBLUNION_CMP_TRUE(&a, &b);
91838 
91839 	return error_count;
91840 #else
91841 	DUK_D(DUK_DPRINT("skip double aliasing self test when duk_tval is not packed"));
91842 	return 0;
91843 #endif
91844 }
91845 
91846 /*
91847  *  Zero sign, see misc/tcc_zerosign2.c.
91848  */
91849 
91850 DUK_LOCAL duk_uint_t duk__selftest_double_zero_sign(void) {
91851 	duk_uint_t error_count = 0;
91852 	duk__test_double_union a, b;
91853 
91854 	a.d = 0.0;
91855 	b.d = -a.d;
91856 	DUK__DBLUNION_CMP_FALSE(&a, &b);
91857 
91858 	return error_count;
91859 }
91860 
91861 /*
91862  *  Rounding mode: Duktape assumes round-to-nearest, check that this is true.
91863  *  If we had C99 fenv.h we could check that fegetround() == FE_TONEAREST,
91864  *  but we don't want to rely on that header; and even if we did, it's good
91865  *  to ensure the rounding actually works.
91866  */
91867 
91868 DUK_LOCAL duk_uint_t duk__selftest_double_rounding(void) {
91869 	duk_uint_t error_count = 0;
91870 	duk__test_double_union a, b, c;
91871 
91872 #if 0
91873 	/* Include <fenv.h> and test manually; these trigger failures: */
91874 	fesetround(FE_UPWARD);
91875 	fesetround(FE_DOWNWARD);
91876 	fesetround(FE_TOWARDZERO);
91877 
91878 	/* This is the default and passes. */
91879 	fesetround(FE_TONEAREST);
91880 #endif
91881 
91882 	/* Rounding tests check that none of the other modes (round to
91883 	 * +Inf, round to -Inf, round to zero) can be active:
91884 	 * http://www.gnu.org/software/libc/manual/html_node/Rounding.html
91885 	 */
91886 
91887 	/* 1.0 + 2^(-53): result is midway between 1.0 and 1.0 + ulp.
91888 	 * Round to nearest: 1.0
91889 	 * Round to +Inf:    1.0 + ulp
91890 	 * Round to -Inf:    1.0
91891 	 * Round to zero:    1.0
91892 	 * => Correct result eliminates round to +Inf.
91893 	 */
91894 	DUK__DOUBLE_INIT(&a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
91895 	DUK__DOUBLE_INIT(&b, 0x3c, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
91896 	duk_memset((void *) &c, 0, sizeof(c));
91897 	c.d = a.d + b.d;
91898 	if (!DUK__DOUBLE_COMPARE(&c, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)) {
91899 		DUK_D(DUK_DPRINT("broken result (native endiannesss): %02x %02x %02x %02x %02x %02x %02x %02x",
91900 		                 (unsigned int) c.x[0], (unsigned int) c.x[1],
91901 		                 (unsigned int) c.x[2], (unsigned int) c.x[3],
91902 		                 (unsigned int) c.x[4], (unsigned int) c.x[5],
91903 		                 (unsigned int) c.x[6], (unsigned int) c.x[7]));
91904 		DUK__FAILED("invalid result from 1.0 + 0.5ulp");
91905 	}
91906 
91907 	/* (1.0 + ulp) + 2^(-53): result is midway between 1.0 + ulp and 1.0 + 2*ulp.
91908 	 * Round to nearest: 1.0 + 2*ulp (round to even mantissa)
91909 	 * Round to +Inf:    1.0 + 2*ulp
91910 	 * Round to -Inf:    1.0 + ulp
91911 	 * Round to zero:    1.0 + ulp
91912 	 * => Correct result eliminates round to -Inf and round to zero.
91913 	 */
91914 	DUK__DOUBLE_INIT(&a, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01);
91915 	DUK__DOUBLE_INIT(&b, 0x3c, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
91916 	duk_memset((void *) &c, 0, sizeof(c));
91917 	c.d = a.d + b.d;
91918 	if (!DUK__DOUBLE_COMPARE(&c, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02)) {
91919 		DUK_D(DUK_DPRINT("broken result (native endiannesss): %02x %02x %02x %02x %02x %02x %02x %02x",
91920 		                 (unsigned int) c.x[0], (unsigned int) c.x[1],
91921 		                 (unsigned int) c.x[2], (unsigned int) c.x[3],
91922 		                 (unsigned int) c.x[4], (unsigned int) c.x[5],
91923 		                 (unsigned int) c.x[6], (unsigned int) c.x[7]));
91924 		DUK__FAILED("invalid result from (1.0 + ulp) + 0.5ulp");
91925 	}
91926 
91927 	/* Could do negative number testing too, but the tests above should
91928 	 * differentiate between IEEE 754 rounding modes.
91929 	 */
91930 	return error_count;
91931 }
91932 
91933 /*
91934  *  fmod(): often a portability issue in embedded or bare platform targets.
91935  *  Check for at least minimally correct behavior.  Unlike some other math
91936  *  functions (like cos()) Duktape relies on fmod() internally too.
91937  */
91938 
91939 DUK_LOCAL duk_uint_t duk__selftest_fmod(void) {
91940 	duk_uint_t error_count = 0;
91941 	duk__test_double_union u1, u2;
91942 	volatile duk_double_t t1, t2, t3;
91943 
91944 	/* fmod() with integer argument and exponent 2^32 is used by e.g.
91945 	 * ToUint32() and some Duktape internals.
91946 	 */
91947 	u1.d = DUK_FMOD(10.0, 4294967296.0);
91948 	u2.d = 10.0;
91949 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
91950 
91951 	u1.d = DUK_FMOD(4294967306.0, 4294967296.0);
91952 	u2.d = 10.0;
91953 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
91954 
91955 	u1.d = DUK_FMOD(73014444042.0, 4294967296.0);
91956 	u2.d = 10.0;
91957 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
91958 
91959 	/* 52-bit integer split into two parts:
91960 	 * >>> 0x1fedcba9876543
91961 	 * 8987183256397123
91962 	 * >>> float(0x1fedcba9876543) / float(2**53)
91963 	 * 0.9977777777777778
91964 	 */
91965 	u1.d = DUK_FMOD(8987183256397123.0, 4294967296.0);
91966 	u2.d = (duk_double_t) 0xa9876543UL;
91967 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
91968 	t1 = 8987183256397123.0;
91969 	t2 = 4294967296.0;
91970 	t3 = t1 / t2;
91971 	u1.d = DUK_FLOOR(t3);
91972 	u2.d = (duk_double_t) 0x1fedcbUL;
91973 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
91974 
91975 	/* C99 behavior is for fmod() result sign to mathc argument sign. */
91976 	u1.d = DUK_FMOD(-10.0, 4294967296.0);
91977 	u2.d = -10.0;
91978 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
91979 
91980 	u1.d = DUK_FMOD(-4294967306.0, 4294967296.0);
91981 	u2.d = -10.0;
91982 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
91983 
91984 	u1.d = DUK_FMOD(-73014444042.0, 4294967296.0);
91985 	u2.d = -10.0;
91986 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
91987 
91988 	return error_count;
91989 }
91990 
91991 /*
91992  *  Struct size/alignment if platform requires it
91993  *
91994  *  There are some compiler specific struct padding pragmas etc in use, this
91995  *  selftest ensures they're correctly detected and used.
91996  */
91997 
91998 DUK_LOCAL duk_uint_t duk__selftest_struct_align(void) {
91999 	duk_uint_t error_count = 0;
92000 
92001 #if (DUK_USE_ALIGN_BY == 4)
92002 	if ((sizeof(duk_hbuffer_fixed) % 4) != 0) {
92003 		DUK__FAILED("sizeof(duk_hbuffer_fixed) not aligned to 4");
92004 	}
92005 #elif (DUK_USE_ALIGN_BY == 8)
92006 	if ((sizeof(duk_hbuffer_fixed) % 8) != 0) {
92007 		DUK__FAILED("sizeof(duk_hbuffer_fixed) not aligned to 8");
92008 	}
92009 #elif (DUK_USE_ALIGN_BY == 1)
92010 	/* no check */
92011 #else
92012 #error invalid DUK_USE_ALIGN_BY
92013 #endif
92014 	return error_count;
92015 }
92016 
92017 /*
92018  *  64-bit arithmetic
92019  *
92020  *  There are some platforms/compilers where 64-bit types are available
92021  *  but don't work correctly.  Test for known cases.
92022  */
92023 
92024 DUK_LOCAL duk_uint_t duk__selftest_64bit_arithmetic(void) {
92025 	duk_uint_t error_count = 0;
92026 #if defined(DUK_USE_64BIT_OPS)
92027 	volatile duk_int64_t i;
92028 	volatile duk_double_t d;
92029 
92030 	/* Catch a double-to-int64 cast issue encountered in practice. */
92031 	d = 2147483648.0;
92032 	i = (duk_int64_t) d;
92033 	if (i != DUK_I64_CONSTANT(0x80000000)) {
92034 		DUK__FAILED("casting 2147483648.0 to duk_int64_t failed");
92035 	}
92036 #else
92037 	/* nop */
92038 #endif
92039 	return error_count;
92040 }
92041 
92042 /*
92043  *  Casting
92044  */
92045 
92046 DUK_LOCAL duk_uint_t duk__selftest_cast_double_to_small_uint(void) {
92047 	/*
92048 	 *  https://github.com/svaarala/duktape/issues/127#issuecomment-77863473
92049 	 */
92050 
92051 	duk_uint_t error_count = 0;
92052 
92053 	duk_double_t d1, d2;
92054 	duk_small_uint_t u;
92055 
92056 	duk_double_t d1v, d2v;
92057 	duk_small_uint_t uv;
92058 
92059 	/* Test without volatiles */
92060 
92061 	d1 = 1.0;
92062 	u = (duk_small_uint_t) d1;
92063 	d2 = (duk_double_t) u;
92064 
92065 	if (!(duk_double_equals(d1, 1.0) && u == 1 && duk_double_equals(d2, 1.0) && duk_double_equals(d1, d2))) {
92066 		DUK__FAILED("double to duk_small_uint_t cast failed");
92067 	}
92068 
92069 	/* Same test with volatiles */
92070 
92071 	d1v = 1.0;
92072 	uv = (duk_small_uint_t) d1v;
92073 	d2v = (duk_double_t) uv;
92074 
92075 	if (!(duk_double_equals(d1v, 1.0) && uv == 1 && duk_double_equals(d2v, 1.0) && duk_double_equals(d1v, d2v))) {
92076 		DUK__FAILED("double to duk_small_uint_t cast failed");
92077 	}
92078 
92079 	return error_count;
92080 }
92081 
92082 DUK_LOCAL duk_uint_t duk__selftest_cast_double_to_uint32(void) {
92083 	/*
92084 	 *  This test fails on an exotic ARM target; double-to-uint
92085 	 *  cast is incorrectly clamped to -signed- int highest value.
92086 	 *
92087 	 *  https://github.com/svaarala/duktape/issues/336
92088 	 */
92089 
92090 	duk_uint_t error_count = 0;
92091 	duk_double_t dv;
92092 	duk_uint32_t uv;
92093 
92094 	dv = 3735928559.0;  /* 0xdeadbeef in decimal */
92095 	uv = (duk_uint32_t) dv;
92096 
92097 	if (uv != 0xdeadbeefUL) {
92098 		DUK__FAILED("double to duk_uint32_t cast failed");
92099 	}
92100 
92101 	return error_count;
92102 }
92103 
92104 /*
92105  *  Minimal test of user supplied allocation functions
92106  *
92107  *    - Basic alloc + realloc + free cycle
92108  *
92109  *    - Realloc to significantly larger size to (hopefully) trigger a
92110  *      relocation and check that relocation copying works
92111  */
92112 
92113 DUK_LOCAL duk_uint_t duk__selftest_alloc_funcs(duk_alloc_function alloc_func,
92114                                                duk_realloc_function realloc_func,
92115                                                duk_free_function free_func,
92116                                                void *udata) {
92117 	duk_uint_t error_count = 0;
92118 	void *ptr;
92119 	void *new_ptr;
92120 	duk_small_int_t i, j;
92121 	unsigned char x;
92122 
92123 	if (alloc_func == NULL || realloc_func == NULL || free_func == NULL) {
92124 		return 0;
92125 	}
92126 
92127 	for (i = 1; i <= 256; i++) {
92128 		ptr = alloc_func(udata, (duk_size_t) i);
92129 		if (ptr == NULL) {
92130 			DUK_D(DUK_DPRINT("alloc failed, ignore"));
92131 			continue;  /* alloc failed, ignore */
92132 		}
92133 		for (j = 0; j < i; j++) {
92134 			((unsigned char *) ptr)[j] = (unsigned char) (0x80 + j);
92135 		}
92136 		new_ptr = realloc_func(udata, ptr, 1024);
92137 		if (new_ptr == NULL) {
92138 			DUK_D(DUK_DPRINT("realloc failed, ignore"));
92139 			free_func(udata, ptr);
92140 			continue;  /* realloc failed, ignore */
92141 		}
92142 		ptr = new_ptr;
92143 		for (j = 0; j < i; j++) {
92144 			x = ((unsigned char *) ptr)[j];
92145 			if (x != (unsigned char) (0x80 + j)) {
92146 				DUK_D(DUK_DPRINT("byte at index %ld doesn't match after realloc: %02lx",
92147 				                 (long) j, (unsigned long) x));
92148 				DUK__FAILED("byte compare after realloc");
92149 				break;
92150 			}
92151 		}
92152 		free_func(udata, ptr);
92153 	}
92154 
92155 	return error_count;
92156 }
92157 
92158 /*
92159  *  Self test main
92160  */
92161 
92162 DUK_INTERNAL duk_uint_t duk_selftest_run_tests(duk_alloc_function alloc_func,
92163                                                duk_realloc_function realloc_func,
92164                                                duk_free_function free_func,
92165                                                void *udata) {
92166 	duk_uint_t error_count = 0;
92167 
92168 	DUK_D(DUK_DPRINT("self test starting"));
92169 
92170 	error_count += duk__selftest_types();
92171 	error_count += duk__selftest_packed_tval();
92172 	error_count += duk__selftest_twos_complement();
92173 	error_count += duk__selftest_byte_order();
92174 	error_count += duk__selftest_bswap_macros();
92175 	error_count += duk__selftest_double_union_size();
92176 	error_count += duk__selftest_double_aliasing();
92177 	error_count += duk__selftest_double_zero_sign();
92178 	error_count += duk__selftest_double_rounding();
92179 	error_count += duk__selftest_fmod();
92180 	error_count += duk__selftest_struct_align();
92181 	error_count += duk__selftest_64bit_arithmetic();
92182 	error_count += duk__selftest_cast_double_to_small_uint();
92183 	error_count += duk__selftest_cast_double_to_uint32();
92184 	error_count += duk__selftest_alloc_funcs(alloc_func, realloc_func, free_func, udata);
92185 
92186 	DUK_D(DUK_DPRINT("self test complete, total error count: %ld", (long) error_count));
92187 
92188 	return error_count;
92189 }
92190 
92191 #endif  /* DUK_USE_SELF_TESTS */
92192 
92193 /* automatic undefs */
92194 #undef DUK__DBLUNION_CMP_FALSE
92195 #undef DUK__DBLUNION_CMP_TRUE
92196 #undef DUK__DOUBLE_COMPARE
92197 #undef DUK__DOUBLE_INIT
92198 #undef DUK__FAILED
92199 #undef DUK__U32_INIT
92200 /* #include duk_internal.h -> already included */
92201 
92202 #if defined(DUK_USE_FASTINT)
92203 
92204 /*
92205  *  Manually optimized double-to-fastint downgrade check.
92206  *
92207  *  This check has a large impact on performance, especially for fastint
92208  *  slow paths, so must be changed carefully.  The code should probably be
92209  *  optimized for the case where the result does not fit into a fastint,
92210  *  to minimize the penalty for "slow path code" dealing with fractions etc.
92211  *
92212  *  At least on one tested soft float ARM platform double-to-int64 coercion
92213  *  is very slow (and sometimes produces incorrect results, see self tests).
92214  *  This algorithm combines a fastint compatibility check and extracting the
92215  *  integer value from an IEEE double for setting the tagged fastint.  For
92216  *  other platforms a more naive approach might be better.
92217  *
92218  *  See doc/fastint.rst for details.
92219  */
92220 
92221 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_tval_set_number_chkfast_fast(duk_tval *tv, duk_double_t x) {
92222 	duk_double_union du;
92223 	duk_int64_t i;
92224 	duk_small_int_t expt;
92225 	duk_small_int_t shift;
92226 
92227 	/* XXX: optimize for packed duk_tval directly? */
92228 
92229 	du.d = x;
92230 	i = (duk_int64_t) DUK_DBLUNION_GET_INT64(&du);
92231 	expt = (duk_small_int_t) ((i >> 52) & 0x07ff);
92232 	shift = expt - 1023;
92233 
92234 	if (shift >= 0 && shift <= 46) {  /* exponents 1023 to 1069 */
92235 		duk_int64_t t;
92236 
92237 		if (((DUK_I64_CONSTANT(0x000fffffffffffff) >> shift) & i) == 0) {
92238 			t = i | DUK_I64_CONSTANT(0x0010000000000000);  /* implicit leading one */
92239 			t = t & DUK_I64_CONSTANT(0x001fffffffffffff);
92240 			t = t >> (52 - shift);
92241 			if (i < 0) {
92242 				t = -t;
92243 			}
92244 			DUK_TVAL_SET_FASTINT(tv, t);
92245 			return;
92246 		}
92247 	} else if (shift == -1023) {  /* exponent 0 */
92248 		if (i >= 0 && (i & DUK_I64_CONSTANT(0x000fffffffffffff)) == 0) {
92249 			/* Note: reject negative zero. */
92250 			DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) 0);
92251 			return;
92252 		}
92253 	} else if (shift == 47) {  /* exponent 1070 */
92254 		if (i < 0 && (i & DUK_I64_CONSTANT(0x000fffffffffffff)) == 0) {
92255 			DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) DUK_FASTINT_MIN);
92256 			return;
92257 		}
92258 	}
92259 
92260 	DUK_TVAL_SET_DOUBLE(tv, x);
92261 	return;
92262 }
92263 
92264 DUK_INTERNAL DUK_NOINLINE void duk_tval_set_number_chkfast_slow(duk_tval *tv, duk_double_t x) {
92265 	duk_tval_set_number_chkfast_fast(tv, x);
92266 }
92267 
92268 /*
92269  *  Manually optimized number-to-double conversion
92270  */
92271 
92272 #if defined(DUK_USE_FASTINT) && defined(DUK_USE_PACKED_TVAL)
92273 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_packed(duk_tval *tv) {
92274 	duk_double_union du;
92275 	duk_uint64_t t;
92276 
92277 	t = (duk_uint64_t) DUK_DBLUNION_GET_UINT64(tv);
92278 	if ((t >> 48) != DUK_TAG_FASTINT) {
92279 		return tv->d;
92280 	} else if (t & DUK_U64_CONSTANT(0x0000800000000000)) {
92281 		t = (duk_uint64_t) (-((duk_int64_t) t));  /* avoid unary minus on unsigned */
92282 		t = t & DUK_U64_CONSTANT(0x0000ffffffffffff);  /* negative */
92283 		t |= DUK_U64_CONSTANT(0xc330000000000000);
92284 		DUK_DBLUNION_SET_UINT64(&du, t);
92285 		return du.d + 4503599627370496.0;  /* 1 << 52 */
92286 	} else if (t != 0) {
92287 		t &= DUK_U64_CONSTANT(0x0000ffffffffffff);  /* positive */
92288 		t |= DUK_U64_CONSTANT(0x4330000000000000);
92289 		DUK_DBLUNION_SET_UINT64(&du, t);
92290 		return du.d - 4503599627370496.0;  /* 1 << 52 */
92291 	} else {
92292 		return 0.0;  /* zero */
92293 	}
92294 }
92295 #endif  /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
92296 
92297 #if 0  /* unused */
92298 #if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
92299 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked(duk_tval *tv) {
92300 	duk_double_union du;
92301 	duk_uint64_t t;
92302 
92303 	DUK_ASSERT(tv->t == DUK_TAG_NUMBER || tv->t == DUK_TAG_FASTINT);
92304 
92305 	if (tv->t == DUK_TAG_FASTINT) {
92306 		if (tv->v.fi >= 0) {
92307 			t = DUK_U64_CONSTANT(0x4330000000000000) | (duk_uint64_t) tv->v.fi;
92308 			DUK_DBLUNION_SET_UINT64(&du, t);
92309 			return du.d - 4503599627370496.0;  /* 1 << 52 */
92310 		} else {
92311 			t = DUK_U64_CONSTANT(0xc330000000000000) | (duk_uint64_t) (-tv->v.fi);
92312 			DUK_DBLUNION_SET_UINT64(&du, t);
92313 			return du.d + 4503599627370496.0;  /* 1 << 52 */
92314 		}
92315 	} else {
92316 		return tv->v.d;
92317 	}
92318 }
92319 #endif  /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
92320 #endif  /* 0 */
92321 
92322 #if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
92323 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv) {
92324 	duk_double_union du;
92325 	duk_uint64_t t;
92326 
92327 	DUK_ASSERT(tv->t == DUK_TAG_FASTINT);
92328 
92329 	if (tv->v.fi >= 0) {
92330 		t = DUK_U64_CONSTANT(0x4330000000000000) | (duk_uint64_t) tv->v.fi;
92331 		DUK_DBLUNION_SET_UINT64(&du, t);
92332 		return du.d - 4503599627370496.0;  /* 1 << 52 */
92333 	} else {
92334 		t = DUK_U64_CONSTANT(0xc330000000000000) | (duk_uint64_t) (-tv->v.fi);
92335 		DUK_DBLUNION_SET_UINT64(&du, t);
92336 		return du.d + 4503599627370496.0;  /* 1 << 52 */
92337 	}
92338 }
92339 #endif  /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
92340 
92341 #endif  /* DUK_USE_FASTINT */
92342 
92343 /*
92344  *  Assertion helpers.
92345  */
92346 
92347 #if defined(DUK_USE_ASSERTIONS)
92348 DUK_INTERNAL void duk_tval_assert_valid(duk_tval *tv) {
92349 	DUK_ASSERT(tv != NULL);
92350 }
92351 #endif
92352 /*
92353  *  Unicode support tables automatically generated during build.
92354  */
92355 
92356 /* #include duk_internal.h -> already included */
92357 
92358 /*
92359  *  Unicode tables containing ranges of Unicode characters in a
92360  *  packed format.  These tables are used to match non-ASCII
92361  *  characters of complex productions by resorting to a linear
92362  *  range-by-range comparison.  This is very slow, but is expected
92363  *  to be very rare in practical ECMAScript source code, and thus
92364  *  compactness is most important.
92365  *
92366  *  The tables are matched using uni_range_match() and the format
92367  *  is described in tools/extract_chars.py.
92368  */
92369 
92370 #if defined(DUK_USE_SOURCE_NONBMP)
92371 /* IdentifierStart production with ASCII excluded */
92372 /* duk_unicode_ids_noa[] */
92373 /*
92374  *  Automatically generated by extract_chars.py, do not edit!
92375  */
92376 
92377 const duk_uint8_t duk_unicode_ids_noa[1116] = {
92378 249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,50,7,2,34,
92379 2,240,66,244,50,247,185,249,98,241,99,7,241,159,57,240,181,63,31,241,191,
92380 21,18,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,
92381 101,10,4,15,9,240,152,175,39,240,82,127,56,242,100,15,4,8,159,1,240,5,115,
92382 19,240,98,98,4,52,15,2,14,18,47,0,27,9,85,19,240,98,98,18,18,31,17,50,15,5,
92383 47,2,130,34,240,98,98,18,68,15,4,15,1,31,9,12,115,19,240,98,98,18,68,15,16,
92384 18,47,1,15,3,2,84,34,52,18,2,20,20,36,191,8,15,38,114,34,240,114,240,4,15,
92385 12,38,31,16,5,114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,
92386 6,41,47,10,86,240,36,240,130,130,3,111,44,242,2,29,111,44,18,2,66,240,130,
92387 2,146,26,3,66,15,7,63,18,15,49,114,241,79,13,79,101,241,191,6,15,2,85,52,4,
92388 24,37,205,15,3,241,98,6,3,241,178,255,224,63,35,54,32,35,63,25,35,63,17,35,
92389 54,32,35,62,47,41,35,63,51,241,127,0,240,47,70,53,79,254,21,227,240,18,240,
92390 166,243,180,168,194,63,0,240,47,0,240,47,0,194,47,1,242,79,21,5,15,53,244,
92391 152,67,241,34,6,243,107,240,255,35,240,227,76,241,197,240,175,40,240,122,
92392 242,95,68,15,79,241,255,3,111,41,240,238,27,241,207,12,241,79,27,43,241,67,
92393 136,241,179,47,27,50,82,20,6,251,15,50,255,224,8,53,63,22,53,55,32,32,32,
92394 47,15,63,37,38,32,66,38,67,53,92,98,38,246,96,224,240,44,245,112,80,57,32,
92395 68,112,32,32,35,42,51,100,80,240,63,25,255,233,107,241,242,241,242,247,87,
92396 52,29,241,98,6,3,242,136,15,2,240,122,98,98,98,98,98,98,98,111,66,15,254,
92397 12,146,240,184,132,52,95,70,114,47,74,35,111,27,47,78,240,63,11,242,127,0,
92398 255,224,244,255,240,0,138,143,60,255,240,4,14,47,2,255,227,127,243,95,30,
92399 63,253,79,0,177,240,111,31,240,47,15,63,64,241,152,63,87,63,37,52,242,42,
92400 34,35,47,7,240,255,36,240,15,34,243,5,64,33,207,12,191,7,240,191,13,143,31,
92401 240,224,240,36,41,180,47,25,240,146,39,240,111,7,64,79,34,32,65,52,48,32,
92402 240,162,58,130,213,53,53,166,38,47,27,43,159,99,240,255,255,0,26,150,223,7,
92403 95,33,255,240,0,255,143,254,6,3,245,175,24,109,70,2,146,194,66,2,18,18,245,
92404 207,19,255,224,93,240,79,48,63,38,241,171,246,100,47,119,241,111,10,127,10,
92405 207,73,69,53,53,50,241,91,47,10,47,3,33,46,61,241,79,107,243,127,37,255,
92406 223,13,79,33,242,31,16,239,14,111,22,191,14,63,20,87,36,241,207,142,240,79,
92407 20,95,20,95,24,159,36,248,239,254,2,154,240,107,127,138,83,2,241,194,20,3,
92408 240,123,240,122,240,255,51,240,50,27,240,107,240,175,56,242,135,31,50,15,1,
92409 50,34,240,223,28,240,212,240,223,21,114,240,207,13,242,107,240,107,240,62,
92410 240,47,96,243,159,41,242,62,242,62,241,79,254,13,15,13,176,159,6,248,207,7,
92411 223,37,243,223,29,241,47,9,240,207,20,240,240,207,19,64,223,32,240,3,240,
92412 112,32,241,95,2,47,9,244,102,32,35,46,41,143,31,241,135,49,63,6,38,33,36,
92413 64,240,64,212,249,15,37,240,67,240,96,241,47,32,240,97,32,250,175,31,241,
92414 179,241,111,32,240,96,242,223,27,224,243,159,11,253,127,28,246,111,48,241,
92415 16,249,39,63,23,240,32,32,240,224,191,24,128,240,112,207,30,240,80,241,79,
92416 41,255,152,47,21,240,48,242,63,14,246,38,33,47,22,240,112,240,181,33,47,16,
92417 240,0,255,224,59,240,63,254,0,31,254,40,207,88,245,255,3,251,79,254,155,15,
92418 254,50,31,254,236,95,254,19,159,255,0,16,173,255,225,43,143,15,246,63,14,
92419 240,79,32,240,35,241,31,5,111,3,255,225,164,243,15,114,243,182,15,52,207,
92420 50,18,15,14,255,240,0,110,169,255,225,229,255,240,1,64,31,254,1,31,35,47,3,
92421 57,255,224,126,255,231,248,245,182,196,136,159,255,0,6,90,244,82,243,114,
92422 19,3,19,50,178,2,98,243,18,51,114,98,240,194,50,66,4,98,255,224,70,63,9,47,
92423 9,47,15,47,9,47,15,47,9,47,15,47,9,47,15,47,9,39,255,232,40,241,219,111,2,
92424 15,254,6,95,28,255,228,8,251,95,45,243,72,15,254,58,131,47,11,33,32,48,41,
92425 35,32,32,112,80,32,32,34,33,32,48,32,32,32,32,33,32,51,38,35,35,32,41,47,1,
92426 98,36,47,1,255,240,0,3,143,255,0,149,201,241,191,254,242,124,252,227,255,
92427 240,0,87,79,0,255,240,0,194,63,254,177,63,254,17,0,
92428 };
92429 #else
92430 /* IdentifierStart production with ASCII and non-BMP excluded */
92431 /* duk_unicode_ids_noabmp[] */
92432 /*
92433  *  Automatically generated by extract_chars.py, do not edit!
92434  */
92435 
92436 const duk_uint8_t duk_unicode_ids_noabmp[625] = {
92437 249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,50,7,2,34,
92438 2,240,66,244,50,247,185,249,98,241,99,7,241,159,57,240,181,63,31,241,191,
92439 21,18,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,
92440 101,10,4,15,9,240,152,175,39,240,82,127,56,242,100,15,4,8,159,1,240,5,115,
92441 19,240,98,98,4,52,15,2,14,18,47,0,27,9,85,19,240,98,98,18,18,31,17,50,15,5,
92442 47,2,130,34,240,98,98,18,68,15,4,15,1,31,9,12,115,19,240,98,98,18,68,15,16,
92443 18,47,1,15,3,2,84,34,52,18,2,20,20,36,191,8,15,38,114,34,240,114,240,4,15,
92444 12,38,31,16,5,114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,
92445 6,41,47,10,86,240,36,240,130,130,3,111,44,242,2,29,111,44,18,2,66,240,130,
92446 2,146,26,3,66,15,7,63,18,15,49,114,241,79,13,79,101,241,191,6,15,2,85,52,4,
92447 24,37,205,15,3,241,98,6,3,241,178,255,224,63,35,54,32,35,63,25,35,63,17,35,
92448 54,32,35,62,47,41,35,63,51,241,127,0,240,47,70,53,79,254,21,227,240,18,240,
92449 166,243,180,168,194,63,0,240,47,0,240,47,0,194,47,1,242,79,21,5,15,53,244,
92450 152,67,241,34,6,243,107,240,255,35,240,227,76,241,197,240,175,40,240,122,
92451 242,95,68,15,79,241,255,3,111,41,240,238,27,241,207,12,241,79,27,43,241,67,
92452 136,241,179,47,27,50,82,20,6,251,15,50,255,224,8,53,63,22,53,55,32,32,32,
92453 47,15,63,37,38,32,66,38,67,53,92,98,38,246,96,224,240,44,245,112,80,57,32,
92454 68,112,32,32,35,42,51,100,80,240,63,25,255,233,107,241,242,241,242,247,87,
92455 52,29,241,98,6,3,242,136,15,2,240,122,98,98,98,98,98,98,98,111,66,15,254,
92456 12,146,240,184,132,52,95,70,114,47,74,35,111,27,47,78,240,63,11,242,127,0,
92457 255,224,244,255,240,0,138,143,60,255,240,4,14,47,2,255,227,127,243,95,30,
92458 63,253,79,0,177,240,111,31,240,47,15,63,64,241,152,63,87,63,37,52,242,42,
92459 34,35,47,7,240,255,36,240,15,34,243,5,64,33,207,12,191,7,240,191,13,143,31,
92460 240,224,240,36,41,180,47,25,240,146,39,240,111,7,64,79,34,32,65,52,48,32,
92461 240,162,58,130,213,53,53,166,38,47,27,43,159,99,240,255,255,0,26,150,223,7,
92462 95,33,255,240,0,255,143,254,6,3,245,175,24,109,70,2,146,194,66,2,18,18,245,
92463 207,19,255,224,93,240,79,48,63,38,241,171,246,100,47,119,241,111,10,127,10,
92464 207,73,69,53,53,50,0,
92465 };
92466 #endif
92467 
92468 #if defined(DUK_USE_SOURCE_NONBMP)
92469 /* IdentifierStart production with Letter and ASCII excluded */
92470 /* duk_unicode_ids_m_let_noa[] */
92471 /*
92472  *  Automatically generated by extract_chars.py, do not edit!
92473  */
92474 
92475 const duk_uint8_t duk_unicode_ids_m_let_noa[42] = {
92476 255,240,0,94,18,255,233,99,241,51,63,254,215,32,240,184,240,2,255,240,6,89,
92477 249,255,240,4,148,79,37,255,224,192,9,15,120,79,255,0,15,30,245,240,
92478 };
92479 #else
92480 /* IdentifierStart production with Letter, ASCII, and non-BMP excluded */
92481 /* duk_unicode_ids_m_let_noabmp[] */
92482 /*
92483  *  Automatically generated by extract_chars.py, do not edit!
92484  */
92485 
92486 const duk_uint8_t duk_unicode_ids_m_let_noabmp[24] = {
92487 255,240,0,94,18,255,233,99,241,51,63,254,215,32,240,184,240,2,255,240,6,89,
92488 249,0,
92489 };
92490 #endif
92491 
92492 #if defined(DUK_USE_SOURCE_NONBMP)
92493 /* IdentifierPart production with IdentifierStart and ASCII excluded */
92494 /* duk_unicode_idp_m_ids_noa[] */
92495 /*
92496  *  Automatically generated by extract_chars.py, do not edit!
92497  */
92498 
92499 const duk_uint8_t duk_unicode_idp_m_ids_noa[576] = {
92500 255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112,
92501 245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,160,240,163,40,
92502 34,36,241,210,246,158,47,17,242,130,47,2,38,177,57,240,50,242,160,38,49,50,
92503 160,177,57,240,0,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,
92504 240,97,57,181,34,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,
92505 9,240,36,242,182,34,35,129,193,57,240,50,242,160,38,34,35,129,193,57,240,
92506 35,242,145,38,34,35,160,177,57,240,65,243,128,85,32,39,121,49,242,240,54,
92507 215,41,244,144,56,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,
92508 245,111,4,41,211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,
92509 241,241,1,243,47,16,160,57,241,50,57,245,209,241,64,246,139,91,185,247,41,
92510 242,244,242,185,47,13,58,121,240,141,243,68,242,31,1,201,240,56,210,241,12,
92511 57,241,237,242,47,4,153,121,246,130,47,5,80,112,50,251,143,42,36,255,225,0,
92512 31,35,31,5,15,109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,
92513 31,255,0,100,121,159,55,5,159,18,31,66,31,254,0,64,64,80,240,148,244,161,
92514 242,79,2,185,127,2,234,240,231,240,188,241,227,242,29,240,25,192,185,242,
92515 29,208,145,57,241,50,242,64,34,49,97,32,241,180,97,253,231,33,57,255,240,3,
92516 225,128,255,225,213,240,15,2,240,4,31,10,47,178,159,23,15,254,27,16,253,64,
92517 248,116,255,224,25,159,254,68,178,33,99,241,162,80,249,113,255,225,49,57,
92518 159,254,16,10,250,18,242,126,241,25,240,19,241,250,242,121,114,241,109,41,
92519 97,241,224,210,242,45,147,73,244,75,112,249,43,105,115,242,145,38,49,50,
92520 160,177,54,68,251,47,2,169,80,244,63,4,217,252,118,56,240,209,244,79,1,240,
92521 25,244,60,153,244,94,89,254,78,249,121,253,150,54,64,240,233,241,166,35,
92522 144,170,242,15,0,255,224,137,114,127,2,159,42,240,98,223,108,84,2,18,98,9,
92523 159,34,66,18,73,159,254,3,211,255,240,3,165,217,247,132,242,214,240,185,
92524 255,226,233,2,242,120,63,255,0,59,254,31,255,0,3,186,68,89,115,111,16,63,
92525 134,47,254,71,223,34,255,224,244,242,117,242,41,15,0,15,8,66,239,254,68,70,
92526 47,1,54,33,36,255,118,169,255,224,150,223,254,76,166,245,246,105,255,240,
92527 192,105,175,224,0,
92528 };
92529 #else
92530 /* IdentifierPart production with IdentifierStart, ASCII, and non-BMP excluded */
92531 /* duk_unicode_idp_m_ids_noabmp[] */
92532 /*
92533  *  Automatically generated by extract_chars.py, do not edit!
92534  */
92535 
92536 const duk_uint8_t duk_unicode_idp_m_ids_noabmp[358] = {
92537 255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112,
92538 245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,160,240,163,40,
92539 34,36,241,210,246,158,47,17,242,130,47,2,38,177,57,240,50,242,160,38,49,50,
92540 160,177,57,240,0,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,
92541 240,97,57,181,34,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,
92542 9,240,36,242,182,34,35,129,193,57,240,50,242,160,38,34,35,129,193,57,240,
92543 35,242,145,38,34,35,160,177,57,240,65,243,128,85,32,39,121,49,242,240,54,
92544 215,41,244,144,56,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,
92545 245,111,4,41,211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,
92546 241,241,1,243,47,16,160,57,241,50,57,245,209,241,64,246,139,91,185,247,41,
92547 242,244,242,185,47,13,58,121,240,141,243,68,242,31,1,201,240,56,210,241,12,
92548 57,241,237,242,47,4,153,121,246,130,47,5,80,112,50,251,143,42,36,255,225,0,
92549 31,35,31,5,15,109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,
92550 31,255,0,100,121,159,55,5,159,18,31,66,31,254,0,64,64,80,240,148,244,161,
92551 242,79,2,185,127,2,234,240,231,240,188,241,227,242,29,240,25,192,185,242,
92552 29,208,145,57,241,50,242,64,34,49,97,32,241,180,97,253,231,33,57,255,240,3,
92553 225,128,255,225,213,240,15,2,240,4,31,10,47,178,159,23,0,
92554 };
92555 #endif
92556 
92557 /*
92558  *  Case conversion tables generated using tools/extract_caseconv.py.
92559  */
92560 
92561 /* duk_unicode_caseconv_uc[] */
92562 /* duk_unicode_caseconv_lc[] */
92563 
92564 /*
92565  *  Automatically generated by extract_caseconv.py, do not edit!
92566  */
92567 
92568 const duk_uint8_t duk_unicode_caseconv_uc[1411] = {
92569 152,3,128,3,0,184,7,192,6,192,112,35,242,199,224,64,74,192,49,32,128,162,
92570 128,108,65,1,189,129,254,131,3,173,3,136,6,7,98,7,34,68,15,12,14,140,72,30,
92571 104,28,112,32,67,0,65,4,0,138,0,128,4,1,88,65,76,83,8,104,14,72,43,16,253,
92572 28,189,6,39,240,39,224,24,114,12,16,132,16,248,0,248,64,129,241,1,241,128,
92573 195,228,3,229,2,7,204,7,206,4,15,160,15,164,6,31,96,31,104,16,62,224,63,
92574 116,8,125,200,127,32,32,251,176,254,208,33,247,129,255,128,67,239,67,253,
92575 64,135,223,7,254,129,15,216,15,220,2,31,208,31,216,4,63,192,63,208,8,133,
92576 192,133,128,129,38,129,37,177,162,195,2,192,5,229,160,2,20,9,170,220,4,232,
92577 40,127,160,255,144,154,136,4,4,4,0,192,9,152,9,144,48,19,160,19,145,0,41,
92578 96,41,69,192,94,128,94,65,128,193,128,193,2,1,161,1,160,6,3,104,3,102,8,7,
92579 56,7,52,64,14,248,14,240,144,31,144,31,130,128,68,96,68,66,64,145,192,145,
92580 130,129,184,129,184,2,3,217,3,216,24,8,194,8,192,68,18,44,18,40,216,38,16,
92581 38,8,112,77,16,77,6,3,192,35,192,18,199,168,71,168,24,15,168,143,172,132,
92582 44,104,44,103,6,89,2,89,0,200,179,176,179,172,21,50,13,50,1,122,104,26,104,
92583 1,212,228,116,228,65,233,204,233,204,143,211,189,83,188,130,167,127,167,
92584 126,11,79,35,79,32,10,158,94,158,88,85,61,173,61,160,97,192,107,64,107,1,0,
92585 226,128,226,3,1,198,1,196,6,3,228,3,226,8,10,0,6,152,16,31,192,31,184,34,
92586 199,50,199,32,65,128,196,0,195,130,1,185,1,184,4,4,205,79,84,8,0,192,143,0,
92587 142,193,1,52,128,203,2,45,39,16,199,5,253,0,11,80,57,192,15,240,23,128,19,
92588 16,4,144,23,240,5,48,24,0,36,48,25,32,25,16,25,80,31,96,25,144,25,128,25,
92589 160,35,208,25,224,34,0,26,128,26,112,27,240,31,112,29,208,24,224,31,48,31,
92590 16,37,2,198,240,37,18,198,208,37,34,199,0,37,48,24,16,37,64,24,96,37,144,
92591 24,240,37,176,25,0,37,202,122,176,38,0,25,48,38,26,122,192,38,48,25,64,38,
92592 90,120,208,38,128,25,112,38,178,198,32,38,202,122,208,39,18,198,224,39,32,
92593 25,208,39,80,25,240,39,210,198,64,40,42,124,80,40,122,123,16,40,128,26,224,
92594 40,144,36,64,40,192,36,80,41,32,27,112,41,218,123,32,41,234,123,0,52,80,57,
92595 144,55,112,55,96,58,192,56,96,60,32,58,48,60,192,56,192,61,0,57,32,61,16,
92596 57,128,61,80,58,96,61,96,58,0,61,112,60,240,63,0,57,160,63,16,58,16,63,32,
92597 63,144,63,48,55,240,63,80,57,80,76,240,76,1,200,0,65,33,200,16,65,65,200,
92598 32,65,225,200,80,66,33,200,96,66,161,200,112,70,33,200,138,100,161,215,154,
92599 119,209,215,210,198,49,216,234,124,97,233,177,230,1,251,224,57,145,254,81,
92600 254,194,20,226,19,34,24,66,24,50,198,18,198,2,198,80,35,162,198,96,35,226,
92601 207,50,207,42,120,202,120,186,121,74,124,74,124,58,124,42,181,58,123,60,
92602 192,27,240,2,152,2,152,10,76,5,120,0,156,3,225,0,37,1,134,1,200,96,115,32,
92603 97,0,96,32,118,24,29,40,24,64,24,8,44,60,10,106,10,164,61,45,0,36,1,152,
92604 143,75,192,10,128,97,3,211,16,2,184,24,80,244,204,0,178,6,20,61,53,0,32,
92605 129,95,15,168,64,116,160,98,99,234,88,29,40,24,152,24,0,250,166,7,74,6,38,
92606 6,2,62,173,129,210,129,137,129,161,15,192,67,225,0,115,35,240,48,248,72,28,
92607 200,252,20,62,20,7,50,63,7,15,133,129,204,143,194,67,225,128,115,35,240,
92608 176,248,104,28,200,252,52,62,28,7,50,63,15,15,135,129,204,143,196,67,225,0,
92609 115,35,241,48,248,72,28,200,252,84,62,20,7,50,63,23,15,133,129,204,143,198,
92610 67,225,128,115,35,241,176,248,104,28,200,252,116,62,28,7,50,63,31,15,135,
92611 129,204,143,200,67,229,0,115,35,242,48,249,72,28,200,252,148,62,84,7,50,63,
92612 39,15,149,129,204,143,202,67,229,128,115,35,242,176,249,104,28,200,252,180,
92613 62,92,7,50,63,47,15,151,129,204,143,204,67,229,0,115,35,243,48,249,72,28,
92614 200,252,212,62,84,7,50,63,55,15,149,129,204,143,206,67,229,128,115,35,243,
92615 176,249,104,28,200,252,244,62,92,7,50,63,63,15,151,129,204,143,208,67,237,
92616 0,115,35,244,48,251,72,28,200,253,20,62,212,7,50,63,71,15,181,129,204,143,
92617 210,67,237,128,115,35,244,176,251,104,28,200,253,52,62,220,7,50,63,79,15,
92618 183,129,204,143,212,67,237,0,115,35,245,48,251,72,28,200,253,84,62,212,7,
92619 50,63,87,15,181,129,204,143,214,67,237,128,115,35,245,176,251,104,28,200,
92620 253,116,62,220,7,50,63,95,15,183,129,204,143,217,67,247,64,115,35,246,112,
92621 28,136,28,200,253,164,7,12,7,50,63,109,1,200,129,161,15,219,224,114,32,104,
92622 64,115,35,247,144,28,136,28,200,254,20,63,148,7,50,63,135,1,203,129,204,
92623 143,226,64,113,32,115,35,248,208,28,184,26,16,254,62,7,46,6,132,7,50,63,
92624 153,1,203,129,204,143,233,96,115,32,97,0,96,3,250,120,28,200,24,64,24,8,
92625 254,180,7,50,6,132,63,175,129,204,129,132,1,161,15,241,96,116,160,97,0,96,
92626 3,252,120,29,40,24,64,24,8,255,36,7,66,6,38,63,205,1,210,129,161,15,243,
92627 224,116,160,97,0,104,67,254,80,255,208,28,200,255,156,7,82,7,50,63,233,1,
92628 199,129,204,143,251,64,117,32,104,67,254,248,29,72,26,16,28,200,255,228,7,
92629 82,7,51,246,1,0,35,0,35,125,128,192,8,192,9,63,96,80,2,48,2,103,216,30,0,
92630 140,0,140,0,147,246,9,128,35,0,35,0,38,125,130,192,10,96,10,159,96,208,2,
92631 152,2,167,216,156,10,136,10,141,246,41,2,162,2,154,253,138,192,168,128,167,
92632 127,98,208,42,112,42,55,216,188,10,136,10,122,
92633 };
92634 const duk_uint8_t duk_unicode_caseconv_lc[706] = {
92635 160,3,0,3,128,184,6,192,7,192,112,24,144,37,96,64,54,32,81,64,128,226,0,
92636 235,65,129,199,1,230,130,3,145,3,177,34,7,70,7,134,36,15,244,13,236,24,32,
92637 0,34,129,0,65,0,67,4,0,166,32,172,41,132,40,11,64,19,9,208,85,184,80,19,
92638 240,19,248,12,57,32,33,160,172,114,244,67,244,24,248,64,248,0,129,241,129,
92639 241,0,195,229,3,228,2,7,206,7,204,4,15,164,15,160,6,31,104,31,96,16,63,16,
92640 63,0,32,126,96,126,64,64,253,64,253,0,129,251,129,251,0,67,247,67,238,0,
92641 135,242,7,220,130,15,236,15,232,2,31,218,31,118,4,63,208,63,192,8,127,168,
92642 125,232,16,255,192,251,192,33,255,161,247,192,68,44,4,46,4,9,45,137,52,13,
92643 22,0,22,24,47,44,126,2,63,5,254,67,254,130,106,48,16,0,16,19,0,38,64,38,96,
92644 192,78,64,78,132,0,165,0,165,151,1,121,1,122,6,3,4,3,6,8,6,128,6,132,24,13,
92645 152,13,160,32,28,176,28,193,32,59,192,59,226,64,124,128,124,193,0,252,0,
92646 252,148,2,34,2,35,18,4,140,4,142,20,13,192,13,196,16,30,192,30,200,192,70,
92647 0,70,18,32,145,64,145,102,193,48,65,48,131,130,104,2,104,176,30,0,30,1,150,
92648 61,64,61,66,192,125,100,125,68,33,99,57,99,64,50,200,2,200,22,69,157,101,
92649 157,128,169,144,41,144,75,211,64,83,64,142,167,34,167,35,15,78,101,78,102,
92650 126,157,230,157,232,21,59,245,59,248,90,121,10,121,16,84,242,212,242,226,
92651 169,237,41,237,67,12,3,76,5,0,8,6,176,6,180,16,14,32,14,48,48,28,80,28,96,
92652 64,126,224,127,0,139,28,139,28,193,6,3,14,3,16,8,6,224,6,228,21,61,80,19,
92653 48,32,3,1,150,2,105,4,4,118,4,120,8,67,28,180,156,23,240,192,94,0,63,192,
92654 96,64,148,192,97,128,149,0,99,128,119,64,99,192,150,64,100,0,150,192,100,
92655 64,100,128,100,192,152,0,101,0,152,192,101,192,154,0,102,0,102,64,103,64,
92656 156,128,103,192,157,64,105,192,106,0,107,128,162,0,109,192,164,128,124,64,
92657 124,192,125,128,101,64,125,192,111,192,136,0,103,128,142,139,25,64,143,64,
92658 102,128,143,139,25,128,144,192,96,0,145,0,162,64,145,64,163,0,221,128,221,
92659 192,223,192,252,192,225,128,235,0,227,0,243,0,243,192,245,192,253,0,238,0,
92660 254,64,252,129,48,1,51,199,167,128,55,199,239,7,236,199,243,7,240,199,251,
92661 7,249,71,255,7,252,200,73,128,242,72,74,128,26,200,74,192,57,72,76,136,83,
92662 136,96,200,97,11,24,11,24,75,24,128,154,203,24,199,95,75,25,0,159,75,27,64,
92663 148,75,27,128,156,75,27,192,148,11,28,0,148,139,60,139,60,233,223,71,94,
92664 105,226,233,227,41,227,64,153,105,234,192,151,41,235,0,152,105,235,64,155,
92665 41,236,0,167,169,236,64,161,233,236,128,167,105,236,234,212,233,240,169,
92666 240,233,241,41,229,41,241,64,160,169,241,135,99,128,128,152,64,13,32,96,
92667 224,
92668 };
92669 
92670 #if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
92671 /*
92672  *  Automatically generated by extract_caseconv.py, do not edit!
92673  */
92674 
92675 const duk_uint16_t duk_unicode_re_canon_lookup[65536] = {
92676 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,
92677 28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,
92678 53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,
92679 78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,65,66,67,68,69,70,
92680 71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,123,124,125,
92681 126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
92682 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
92683 162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
92684 180,924,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
92685 198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
92686 216,217,218,219,220,221,222,223,192,193,194,195,196,197,198,199,200,201,
92687 202,203,204,205,206,207,208,209,210,211,212,213,214,247,216,217,218,219,
92688 220,221,222,376,256,256,258,258,260,260,262,262,264,264,266,266,268,268,
92689 270,270,272,272,274,274,276,276,278,278,280,280,282,282,284,284,286,286,
92690 288,288,290,290,292,292,294,294,296,296,298,298,300,300,302,302,304,305,
92691 306,306,308,308,310,310,312,313,313,315,315,317,317,319,319,321,321,323,
92692 323,325,325,327,327,329,330,330,332,332,334,334,336,336,338,338,340,340,
92693 342,342,344,344,346,346,348,348,350,350,352,352,354,354,356,356,358,358,
92694 360,360,362,362,364,364,366,366,368,368,370,370,372,372,374,374,376,377,
92695 377,379,379,381,381,383,579,385,386,386,388,388,390,391,391,393,394,395,
92696 395,397,398,399,400,401,401,403,404,502,406,407,408,408,573,411,412,413,
92697 544,415,416,416,418,418,420,420,422,423,423,425,426,427,428,428,430,431,
92698 431,433,434,435,435,437,437,439,440,440,442,443,444,444,446,503,448,449,
92699 450,451,452,452,452,455,455,455,458,458,458,461,461,463,463,465,465,467,
92700 467,469,469,471,471,473,473,475,475,398,478,478,480,480,482,482,484,484,
92701 486,486,488,488,490,490,492,492,494,494,496,497,497,497,500,500,502,503,
92702 504,504,506,506,508,508,510,510,512,512,514,514,516,516,518,518,520,520,
92703 522,522,524,524,526,526,528,528,530,530,532,532,534,534,536,536,538,538,
92704 540,540,542,542,544,545,546,546,548,548,550,550,552,552,554,554,556,556,
92705 558,558,560,560,562,562,564,565,566,567,568,569,570,571,571,573,574,11390,
92706 11391,577,577,579,580,581,582,582,584,584,586,586,588,588,590,590,11375,
92707 11373,11376,385,390,597,393,394,600,399,602,400,42923L,605,606,607,403,
92708 42924L,610,404,612,42893L,42922L,615,407,406,42926L,11362,42925L,621,622,
92709 412,624,11374,413,627,628,415,630,631,632,633,634,635,636,11364,638,639,
92710 422,641,42949L,425,644,645,646,42929L,430,580,433,434,581,653,654,655,656,
92711 657,439,659,660,661,662,663,664,665,666,667,668,42930L,42928L,671,672,673,
92712 674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,
92713 692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,
92714 710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,
92715 728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,
92716 746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,
92717 764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,
92718 782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,
92719 800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,
92720 818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,
92721 836,921,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,
92722 854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,
92723 872,873,874,875,876,877,878,879,880,880,882,882,884,885,886,886,888,889,
92724 890,1021,1022,1023,894,895,896,897,898,899,900,901,902,903,904,905,906,907,
92725 908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,
92726 926,927,928,929,930,931,932,933,934,935,936,937,938,939,902,904,905,906,
92727 944,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,
92728 931,931,932,933,934,935,936,937,938,939,908,910,911,975,914,920,978,979,
92729 980,934,928,975,984,984,986,986,988,988,990,990,992,992,994,994,996,996,
92730 998,998,1000,1000,1002,1002,1004,1004,1006,1006,922,929,1017,895,1012,917,
92731 1014,1015,1015,1017,1018,1018,1020,1021,1022,1023,1024,1025,1026,1027,1028,
92732 1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,
92733 1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,
92734 1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1040,1041,
92735 1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,
92736 1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,
92737 1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,
92738 1039,1120,1120,1122,1122,1124,1124,1126,1126,1128,1128,1130,1130,1132,1132,
92739 1134,1134,1136,1136,1138,1138,1140,1140,1142,1142,1144,1144,1146,1146,1148,
92740 1148,1150,1150,1152,1152,1154,1155,1156,1157,1158,1159,1160,1161,1162,1162,
92741 1164,1164,1166,1166,1168,1168,1170,1170,1172,1172,1174,1174,1176,1176,1178,
92742 1178,1180,1180,1182,1182,1184,1184,1186,1186,1188,1188,1190,1190,1192,1192,
92743 1194,1194,1196,1196,1198,1198,1200,1200,1202,1202,1204,1204,1206,1206,1208,
92744 1208,1210,1210,1212,1212,1214,1214,1216,1217,1217,1219,1219,1221,1221,1223,
92745 1223,1225,1225,1227,1227,1229,1229,1216,1232,1232,1234,1234,1236,1236,1238,
92746 1238,1240,1240,1242,1242,1244,1244,1246,1246,1248,1248,1250,1250,1252,1252,
92747 1254,1254,1256,1256,1258,1258,1260,1260,1262,1262,1264,1264,1266,1266,1268,
92748 1268,1270,1270,1272,1272,1274,1274,1276,1276,1278,1278,1280,1280,1282,1282,
92749 1284,1284,1286,1286,1288,1288,1290,1290,1292,1292,1294,1294,1296,1296,1298,
92750 1298,1300,1300,1302,1302,1304,1304,1306,1306,1308,1308,1310,1310,1312,1312,
92751 1314,1314,1316,1316,1318,1318,1320,1320,1322,1322,1324,1324,1326,1326,1328,
92752 1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,
92753 1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,
92754 1359,1360,1361,1362,1363,1364,1365,1366,1367,1368,1369,1370,1371,1372,1373,
92755 1374,1375,1376,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,
92756 1341,1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,
92757 1356,1357,1358,1359,1360,1361,1362,1363,1364,1365,1366,1415,1416,1417,1418,
92758 1419,1420,1421,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,
92759 1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,
92760 1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,
92761 1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,
92762 1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,
92763 1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,
92764 1509,1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,
92765 1524,1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,
92766 1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,
92767 1554,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,
92768 1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,
92769 1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,
92770 1599,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,
92771 1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,
92772 1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,
92773 1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,
92774 1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,
92775 1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,
92776 1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,
92777 1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,
92778 1719,1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,
92779 1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,
92780 1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,
92781 1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,
92782 1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,
92783 1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,
92784 1809,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,
92785 1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,
92786 1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,
92787 1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,
92788 1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,
92789 1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,
92790 1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,
92791 1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,
92792 1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,
92793 1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,
92794 1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,
92795 1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,
92796 1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,
92797 2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,
92798 2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,
92799 2034,2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,
92800 2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,
92801 2064,2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,
92802 2079,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,
92803 2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,
92804 2109,2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,
92805 2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,
92806 2139,2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,
92807 2154,2155,2156,2157,2158,2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,
92808 2169,2170,2171,2172,2173,2174,2175,2176,2177,2178,2179,2180,2181,2182,2183,
92809 2184,2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,
92810 2199,2200,2201,2202,2203,2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,
92811 2214,2215,2216,2217,2218,2219,2220,2221,2222,2223,2224,2225,2226,2227,2228,
92812 2229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,
92813 2244,2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,
92814 2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,
92815 2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,
92816 2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2303,
92817 2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,
92818 2319,2320,2321,2322,2323,2324,2325,2326,2327,2328,2329,2330,2331,2332,2333,
92819 2334,2335,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,
92820 2349,2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,2360,2361,2362,2363,
92821 2364,2365,2366,2367,2368,2369,2370,2371,2372,2373,2374,2375,2376,2377,2378,
92822 2379,2380,2381,2382,2383,2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,
92823 2394,2395,2396,2397,2398,2399,2400,2401,2402,2403,2404,2405,2406,2407,2408,
92824 2409,2410,2411,2412,2413,2414,2415,2416,2417,2418,2419,2420,2421,2422,2423,
92825 2424,2425,2426,2427,2428,2429,2430,2431,2432,2433,2434,2435,2436,2437,2438,
92826 2439,2440,2441,2442,2443,2444,2445,2446,2447,2448,2449,2450,2451,2452,2453,
92827 2454,2455,2456,2457,2458,2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,
92828 2469,2470,2471,2472,2473,2474,2475,2476,2477,2478,2479,2480,2481,2482,2483,
92829 2484,2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495,2496,2497,2498,
92830 2499,2500,2501,2502,2503,2504,2505,2506,2507,2508,2509,2510,2511,2512,2513,
92831 2514,2515,2516,2517,2518,2519,2520,2521,2522,2523,2524,2525,2526,2527,2528,
92832 2529,2530,2531,2532,2533,2534,2535,2536,2537,2538,2539,2540,2541,2542,2543,
92833 2544,2545,2546,2547,2548,2549,2550,2551,2552,2553,2554,2555,2556,2557,2558,
92834 2559,2560,2561,2562,2563,2564,2565,2566,2567,2568,2569,2570,2571,2572,2573,
92835 2574,2575,2576,2577,2578,2579,2580,2581,2582,2583,2584,2585,2586,2587,2588,
92836 2589,2590,2591,2592,2593,2594,2595,2596,2597,2598,2599,2600,2601,2602,2603,
92837 2604,2605,2606,2607,2608,2609,2610,2611,2612,2613,2614,2615,2616,2617,2618,
92838 2619,2620,2621,2622,2623,2624,2625,2626,2627,2628,2629,2630,2631,2632,2633,
92839 2634,2635,2636,2637,2638,2639,2640,2641,2642,2643,2644,2645,2646,2647,2648,
92840 2649,2650,2651,2652,2653,2654,2655,2656,2657,2658,2659,2660,2661,2662,2663,
92841 2664,2665,2666,2667,2668,2669,2670,2671,2672,2673,2674,2675,2676,2677,2678,
92842 2679,2680,2681,2682,2683,2684,2685,2686,2687,2688,2689,2690,2691,2692,2693,
92843 2694,2695,2696,2697,2698,2699,2700,2701,2702,2703,2704,2705,2706,2707,2708,
92844 2709,2710,2711,2712,2713,2714,2715,2716,2717,2718,2719,2720,2721,2722,2723,
92845 2724,2725,2726,2727,2728,2729,2730,2731,2732,2733,2734,2735,2736,2737,2738,
92846 2739,2740,2741,2742,2743,2744,2745,2746,2747,2748,2749,2750,2751,2752,2753,
92847 2754,2755,2756,2757,2758,2759,2760,2761,2762,2763,2764,2765,2766,2767,2768,
92848 2769,2770,2771,2772,2773,2774,2775,2776,2777,2778,2779,2780,2781,2782,2783,
92849 2784,2785,2786,2787,2788,2789,2790,2791,2792,2793,2794,2795,2796,2797,2798,
92850 2799,2800,2801,2802,2803,2804,2805,2806,2807,2808,2809,2810,2811,2812,2813,
92851 2814,2815,2816,2817,2818,2819,2820,2821,2822,2823,2824,2825,2826,2827,2828,
92852 2829,2830,2831,2832,2833,2834,2835,2836,2837,2838,2839,2840,2841,2842,2843,
92853 2844,2845,2846,2847,2848,2849,2850,2851,2852,2853,2854,2855,2856,2857,2858,
92854 2859,2860,2861,2862,2863,2864,2865,2866,2867,2868,2869,2870,2871,2872,2873,
92855 2874,2875,2876,2877,2878,2879,2880,2881,2882,2883,2884,2885,2886,2887,2888,
92856 2889,2890,2891,2892,2893,2894,2895,2896,2897,2898,2899,2900,2901,2902,2903,
92857 2904,2905,2906,2907,2908,2909,2910,2911,2912,2913,2914,2915,2916,2917,2918,
92858 2919,2920,2921,2922,2923,2924,2925,2926,2927,2928,2929,2930,2931,2932,2933,
92859 2934,2935,2936,2937,2938,2939,2940,2941,2942,2943,2944,2945,2946,2947,2948,
92860 2949,2950,2951,2952,2953,2954,2955,2956,2957,2958,2959,2960,2961,2962,2963,
92861 2964,2965,2966,2967,2968,2969,2970,2971,2972,2973,2974,2975,2976,2977,2978,
92862 2979,2980,2981,2982,2983,2984,2985,2986,2987,2988,2989,2990,2991,2992,2993,
92863 2994,2995,2996,2997,2998,2999,3000,3001,3002,3003,3004,3005,3006,3007,3008,
92864 3009,3010,3011,3012,3013,3014,3015,3016,3017,3018,3019,3020,3021,3022,3023,
92865 3024,3025,3026,3027,3028,3029,3030,3031,3032,3033,3034,3035,3036,3037,3038,
92866 3039,3040,3041,3042,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3053,
92867 3054,3055,3056,3057,3058,3059,3060,3061,3062,3063,3064,3065,3066,3067,3068,
92868 3069,3070,3071,3072,3073,3074,3075,3076,3077,3078,3079,3080,3081,3082,3083,
92869 3084,3085,3086,3087,3088,3089,3090,3091,3092,3093,3094,3095,3096,3097,3098,
92870 3099,3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3111,3112,3113,
92871 3114,3115,3116,3117,3118,3119,3120,3121,3122,3123,3124,3125,3126,3127,3128,
92872 3129,3130,3131,3132,3133,3134,3135,3136,3137,3138,3139,3140,3141,3142,3143,
92873 3144,3145,3146,3147,3148,3149,3150,3151,3152,3153,3154,3155,3156,3157,3158,
92874 3159,3160,3161,3162,3163,3164,3165,3166,3167,3168,3169,3170,3171,3172,3173,
92875 3174,3175,3176,3177,3178,3179,3180,3181,3182,3183,3184,3185,3186,3187,3188,
92876 3189,3190,3191,3192,3193,3194,3195,3196,3197,3198,3199,3200,3201,3202,3203,
92877 3204,3205,3206,3207,3208,3209,3210,3211,3212,3213,3214,3215,3216,3217,3218,
92878 3219,3220,3221,3222,3223,3224,3225,3226,3227,3228,3229,3230,3231,3232,3233,
92879 3234,3235,3236,3237,3238,3239,3240,3241,3242,3243,3244,3245,3246,3247,3248,
92880 3249,3250,3251,3252,3253,3254,3255,3256,3257,3258,3259,3260,3261,3262,3263,
92881 3264,3265,3266,3267,3268,3269,3270,3271,3272,3273,3274,3275,3276,3277,3278,
92882 3279,3280,3281,3282,3283,3284,3285,3286,3287,3288,3289,3290,3291,3292,3293,
92883 3294,3295,3296,3297,3298,3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,
92884 3309,3310,3311,3312,3313,3314,3315,3316,3317,3318,3319,3320,3321,3322,3323,
92885 3324,3325,3326,3327,3328,3329,3330,3331,3332,3333,3334,3335,3336,3337,3338,
92886 3339,3340,3341,3342,3343,3344,3345,3346,3347,3348,3349,3350,3351,3352,3353,
92887 3354,3355,3356,3357,3358,3359,3360,3361,3362,3363,3364,3365,3366,3367,3368,
92888 3369,3370,3371,3372,3373,3374,3375,3376,3377,3378,3379,3380,3381,3382,3383,
92889 3384,3385,3386,3387,3388,3389,3390,3391,3392,3393,3394,3395,3396,3397,3398,
92890 3399,3400,3401,3402,3403,3404,3405,3406,3407,3408,3409,3410,3411,3412,3413,
92891 3414,3415,3416,3417,3418,3419,3420,3421,3422,3423,3424,3425,3426,3427,3428,
92892 3429,3430,3431,3432,3433,3434,3435,3436,3437,3438,3439,3440,3441,3442,3443,
92893 3444,3445,3446,3447,3448,3449,3450,3451,3452,3453,3454,3455,3456,3457,3458,
92894 3459,3460,3461,3462,3463,3464,3465,3466,3467,3468,3469,3470,3471,3472,3473,
92895 3474,3475,3476,3477,3478,3479,3480,3481,3482,3483,3484,3485,3486,3487,3488,
92896 3489,3490,3491,3492,3493,3494,3495,3496,3497,3498,3499,3500,3501,3502,3503,
92897 3504,3505,3506,3507,3508,3509,3510,3511,3512,3513,3514,3515,3516,3517,3518,
92898 3519,3520,3521,3522,3523,3524,3525,3526,3527,3528,3529,3530,3531,3532,3533,
92899 3534,3535,3536,3537,3538,3539,3540,3541,3542,3543,3544,3545,3546,3547,3548,
92900 3549,3550,3551,3552,3553,3554,3555,3556,3557,3558,3559,3560,3561,3562,3563,
92901 3564,3565,3566,3567,3568,3569,3570,3571,3572,3573,3574,3575,3576,3577,3578,
92902 3579,3580,3581,3582,3583,3584,3585,3586,3587,3588,3589,3590,3591,3592,3593,
92903 3594,3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,
92904 3609,3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,
92905 3624,3625,3626,3627,3628,3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,
92906 3639,3640,3641,3642,3643,3644,3645,3646,3647,3648,3649,3650,3651,3652,3653,
92907 3654,3655,3656,3657,3658,3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,
92908 3669,3670,3671,3672,3673,3674,3675,3676,3677,3678,3679,3680,3681,3682,3683,
92909 3684,3685,3686,3687,3688,3689,3690,3691,3692,3693,3694,3695,3696,3697,3698,
92910 3699,3700,3701,3702,3703,3704,3705,3706,3707,3708,3709,3710,3711,3712,3713,
92911 3714,3715,3716,3717,3718,3719,3720,3721,3722,3723,3724,3725,3726,3727,3728,
92912 3729,3730,3731,3732,3733,3734,3735,3736,3737,3738,3739,3740,3741,3742,3743,
92913 3744,3745,3746,3747,3748,3749,3750,3751,3752,3753,3754,3755,3756,3757,3758,
92914 3759,3760,3761,3762,3763,3764,3765,3766,3767,3768,3769,3770,3771,3772,3773,
92915 3774,3775,3776,3777,3778,3779,3780,3781,3782,3783,3784,3785,3786,3787,3788,
92916 3789,3790,3791,3792,3793,3794,3795,3796,3797,3798,3799,3800,3801,3802,3803,
92917 3804,3805,3806,3807,3808,3809,3810,3811,3812,3813,3814,3815,3816,3817,3818,
92918 3819,3820,3821,3822,3823,3824,3825,3826,3827,3828,3829,3830,3831,3832,3833,
92919 3834,3835,3836,3837,3838,3839,3840,3841,3842,3843,3844,3845,3846,3847,3848,
92920 3849,3850,3851,3852,3853,3854,3855,3856,3857,3858,3859,3860,3861,3862,3863,
92921 3864,3865,3866,3867,3868,3869,3870,3871,3872,3873,3874,3875,3876,3877,3878,
92922 3879,3880,3881,3882,3883,3884,3885,3886,3887,3888,3889,3890,3891,3892,3893,
92923 3894,3895,3896,3897,3898,3899,3900,3901,3902,3903,3904,3905,3906,3907,3908,
92924 3909,3910,3911,3912,3913,3914,3915,3916,3917,3918,3919,3920,3921,3922,3923,
92925 3924,3925,3926,3927,3928,3929,3930,3931,3932,3933,3934,3935,3936,3937,3938,
92926 3939,3940,3941,3942,3943,3944,3945,3946,3947,3948,3949,3950,3951,3952,3953,
92927 3954,3955,3956,3957,3958,3959,3960,3961,3962,3963,3964,3965,3966,3967,3968,
92928 3969,3970,3971,3972,3973,3974,3975,3976,3977,3978,3979,3980,3981,3982,3983,
92929 3984,3985,3986,3987,3988,3989,3990,3991,3992,3993,3994,3995,3996,3997,3998,
92930 3999,4000,4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,
92931 4014,4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,
92932 4029,4030,4031,4032,4033,4034,4035,4036,4037,4038,4039,4040,4041,4042,4043,
92933 4044,4045,4046,4047,4048,4049,4050,4051,4052,4053,4054,4055,4056,4057,4058,
92934 4059,4060,4061,4062,4063,4064,4065,4066,4067,4068,4069,4070,4071,4072,4073,
92935 4074,4075,4076,4077,4078,4079,4080,4081,4082,4083,4084,4085,4086,4087,4088,
92936 4089,4090,4091,4092,4093,4094,4095,4096,4097,4098,4099,4100,4101,4102,4103,
92937 4104,4105,4106,4107,4108,4109,4110,4111,4112,4113,4114,4115,4116,4117,4118,
92938 4119,4120,4121,4122,4123,4124,4125,4126,4127,4128,4129,4130,4131,4132,4133,
92939 4134,4135,4136,4137,4138,4139,4140,4141,4142,4143,4144,4145,4146,4147,4148,
92940 4149,4150,4151,4152,4153,4154,4155,4156,4157,4158,4159,4160,4161,4162,4163,
92941 4164,4165,4166,4167,4168,4169,4170,4171,4172,4173,4174,4175,4176,4177,4178,
92942 4179,4180,4181,4182,4183,4184,4185,4186,4187,4188,4189,4190,4191,4192,4193,
92943 4194,4195,4196,4197,4198,4199,4200,4201,4202,4203,4204,4205,4206,4207,4208,
92944 4209,4210,4211,4212,4213,4214,4215,4216,4217,4218,4219,4220,4221,4222,4223,
92945 4224,4225,4226,4227,4228,4229,4230,4231,4232,4233,4234,4235,4236,4237,4238,
92946 4239,4240,4241,4242,4243,4244,4245,4246,4247,4248,4249,4250,4251,4252,4253,
92947 4254,4255,4256,4257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,
92948 4269,4270,4271,4272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,
92949 4284,4285,4286,4287,4288,4289,4290,4291,4292,4293,4294,4295,4296,4297,4298,
92950 4299,4300,4301,4302,4303,7312,7313,7314,7315,7316,7317,7318,7319,7320,7321,
92951 7322,7323,7324,7325,7326,7327,7328,7329,7330,7331,7332,7333,7334,7335,7336,
92952 7337,7338,7339,7340,7341,7342,7343,7344,7345,7346,7347,7348,7349,7350,7351,
92953 7352,7353,7354,4347,4348,7357,7358,7359,4352,4353,4354,4355,4356,4357,4358,
92954 4359,4360,4361,4362,4363,4364,4365,4366,4367,4368,4369,4370,4371,4372,4373,
92955 4374,4375,4376,4377,4378,4379,4380,4381,4382,4383,4384,4385,4386,4387,4388,
92956 4389,4390,4391,4392,4393,4394,4395,4396,4397,4398,4399,4400,4401,4402,4403,
92957 4404,4405,4406,4407,4408,4409,4410,4411,4412,4413,4414,4415,4416,4417,4418,
92958 4419,4420,4421,4422,4423,4424,4425,4426,4427,4428,4429,4430,4431,4432,4433,
92959 4434,4435,4436,4437,4438,4439,4440,4441,4442,4443,4444,4445,4446,4447,4448,
92960 4449,4450,4451,4452,4453,4454,4455,4456,4457,4458,4459,4460,4461,4462,4463,
92961 4464,4465,4466,4467,4468,4469,4470,4471,4472,4473,4474,4475,4476,4477,4478,
92962 4479,4480,4481,4482,4483,4484,4485,4486,4487,4488,4489,4490,4491,4492,4493,
92963 4494,4495,4496,4497,4498,4499,4500,4501,4502,4503,4504,4505,4506,4507,4508,
92964 4509,4510,4511,4512,4513,4514,4515,4516,4517,4518,4519,4520,4521,4522,4523,
92965 4524,4525,4526,4527,4528,4529,4530,4531,4532,4533,4534,4535,4536,4537,4538,
92966 4539,4540,4541,4542,4543,4544,4545,4546,4547,4548,4549,4550,4551,4552,4553,
92967 4554,4555,4556,4557,4558,4559,4560,4561,4562,4563,4564,4565,4566,4567,4568,
92968 4569,4570,4571,4572,4573,4574,4575,4576,4577,4578,4579,4580,4581,4582,4583,
92969 4584,4585,4586,4587,4588,4589,4590,4591,4592,4593,4594,4595,4596,4597,4598,
92970 4599,4600,4601,4602,4603,4604,4605,4606,4607,4608,4609,4610,4611,4612,4613,
92971 4614,4615,4616,4617,4618,4619,4620,4621,4622,4623,4624,4625,4626,4627,4628,
92972 4629,4630,4631,4632,4633,4634,4635,4636,4637,4638,4639,4640,4641,4642,4643,
92973 4644,4645,4646,4647,4648,4649,4650,4651,4652,4653,4654,4655,4656,4657,4658,
92974 4659,4660,4661,4662,4663,4664,4665,4666,4667,4668,4669,4670,4671,4672,4673,
92975 4674,4675,4676,4677,4678,4679,4680,4681,4682,4683,4684,4685,4686,4687,4688,
92976 4689,4690,4691,4692,4693,4694,4695,4696,4697,4698,4699,4700,4701,4702,4703,
92977 4704,4705,4706,4707,4708,4709,4710,4711,4712,4713,4714,4715,4716,4717,4718,
92978 4719,4720,4721,4722,4723,4724,4725,4726,4727,4728,4729,4730,4731,4732,4733,
92979 4734,4735,4736,4737,4738,4739,4740,4741,4742,4743,4744,4745,4746,4747,4748,
92980 4749,4750,4751,4752,4753,4754,4755,4756,4757,4758,4759,4760,4761,4762,4763,
92981 4764,4765,4766,4767,4768,4769,4770,4771,4772,4773,4774,4775,4776,4777,4778,
92982 4779,4780,4781,4782,4783,4784,4785,4786,4787,4788,4789,4790,4791,4792,4793,
92983 4794,4795,4796,4797,4798,4799,4800,4801,4802,4803,4804,4805,4806,4807,4808,
92984 4809,4810,4811,4812,4813,4814,4815,4816,4817,4818,4819,4820,4821,4822,4823,
92985 4824,4825,4826,4827,4828,4829,4830,4831,4832,4833,4834,4835,4836,4837,4838,
92986 4839,4840,4841,4842,4843,4844,4845,4846,4847,4848,4849,4850,4851,4852,4853,
92987 4854,4855,4856,4857,4858,4859,4860,4861,4862,4863,4864,4865,4866,4867,4868,
92988 4869,4870,4871,4872,4873,4874,4875,4876,4877,4878,4879,4880,4881,4882,4883,
92989 4884,4885,4886,4887,4888,4889,4890,4891,4892,4893,4894,4895,4896,4897,4898,
92990 4899,4900,4901,4902,4903,4904,4905,4906,4907,4908,4909,4910,4911,4912,4913,
92991 4914,4915,4916,4917,4918,4919,4920,4921,4922,4923,4924,4925,4926,4927,4928,
92992 4929,4930,4931,4932,4933,4934,4935,4936,4937,4938,4939,4940,4941,4942,4943,
92993 4944,4945,4946,4947,4948,4949,4950,4951,4952,4953,4954,4955,4956,4957,4958,
92994 4959,4960,4961,4962,4963,4964,4965,4966,4967,4968,4969,4970,4971,4972,4973,
92995 4974,4975,4976,4977,4978,4979,4980,4981,4982,4983,4984,4985,4986,4987,4988,
92996 4989,4990,4991,4992,4993,4994,4995,4996,4997,4998,4999,5000,5001,5002,5003,
92997 5004,5005,5006,5007,5008,5009,5010,5011,5012,5013,5014,5015,5016,5017,5018,
92998 5019,5020,5021,5022,5023,5024,5025,5026,5027,5028,5029,5030,5031,5032,5033,
92999 5034,5035,5036,5037,5038,5039,5040,5041,5042,5043,5044,5045,5046,5047,5048,
93000 5049,5050,5051,5052,5053,5054,5055,5056,5057,5058,5059,5060,5061,5062,5063,
93001 5064,5065,5066,5067,5068,5069,5070,5071,5072,5073,5074,5075,5076,5077,5078,
93002 5079,5080,5081,5082,5083,5084,5085,5086,5087,5088,5089,5090,5091,5092,5093,
93003 5094,5095,5096,5097,5098,5099,5100,5101,5102,5103,5104,5105,5106,5107,5108,
93004 5109,5110,5111,5104,5105,5106,5107,5108,5109,5118,5119,5120,5121,5122,5123,
93005 5124,5125,5126,5127,5128,5129,5130,5131,5132,5133,5134,5135,5136,5137,5138,
93006 5139,5140,5141,5142,5143,5144,5145,5146,5147,5148,5149,5150,5151,5152,5153,
93007 5154,5155,5156,5157,5158,5159,5160,5161,5162,5163,5164,5165,5166,5167,5168,
93008 5169,5170,5171,5172,5173,5174,5175,5176,5177,5178,5179,5180,5181,5182,5183,
93009 5184,5185,5186,5187,5188,5189,5190,5191,5192,5193,5194,5195,5196,5197,5198,
93010 5199,5200,5201,5202,5203,5204,5205,5206,5207,5208,5209,5210,5211,5212,5213,
93011 5214,5215,5216,5217,5218,5219,5220,5221,5222,5223,5224,5225,5226,5227,5228,
93012 5229,5230,5231,5232,5233,5234,5235,5236,5237,5238,5239,5240,5241,5242,5243,
93013 5244,5245,5246,5247,5248,5249,5250,5251,5252,5253,5254,5255,5256,5257,5258,
93014 5259,5260,5261,5262,5263,5264,5265,5266,5267,5268,5269,5270,5271,5272,5273,
93015 5274,5275,5276,5277,5278,5279,5280,5281,5282,5283,5284,5285,5286,5287,5288,
93016 5289,5290,5291,5292,5293,5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,
93017 5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,
93018 5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331,5332,5333,
93019 5334,5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347,5348,
93020 5349,5350,5351,5352,5353,5354,5355,5356,5357,5358,5359,5360,5361,5362,5363,
93021 5364,5365,5366,5367,5368,5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,
93022 5379,5380,5381,5382,5383,5384,5385,5386,5387,5388,5389,5390,5391,5392,5393,
93023 5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,
93024 5409,5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,
93025 5424,5425,5426,5427,5428,5429,5430,5431,5432,5433,5434,5435,5436,5437,5438,
93026 5439,5440,5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,
93027 5454,5455,5456,5457,5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,
93028 5469,5470,5471,5472,5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,
93029 5484,5485,5486,5487,5488,5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,
93030 5499,5500,5501,5502,5503,5504,5505,5506,5507,5508,5509,5510,5511,5512,5513,
93031 5514,5515,5516,5517,5518,5519,5520,5521,5522,5523,5524,5525,5526,5527,5528,
93032 5529,5530,5531,5532,5533,5534,5535,5536,5537,5538,5539,5540,5541,5542,5543,
93033 5544,5545,5546,5547,5548,5549,5550,5551,5552,5553,5554,5555,5556,5557,5558,
93034 5559,5560,5561,5562,5563,5564,5565,5566,5567,5568,5569,5570,5571,5572,5573,
93035 5574,5575,5576,5577,5578,5579,5580,5581,5582,5583,5584,5585,5586,5587,5588,
93036 5589,5590,5591,5592,5593,5594,5595,5596,5597,5598,5599,5600,5601,5602,5603,
93037 5604,5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,5615,5616,5617,5618,
93038 5619,5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,5631,5632,5633,
93039 5634,5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646,5647,5648,
93040 5649,5650,5651,5652,5653,5654,5655,5656,5657,5658,5659,5660,5661,5662,5663,
93041 5664,5665,5666,5667,5668,5669,5670,5671,5672,5673,5674,5675,5676,5677,5678,
93042 5679,5680,5681,5682,5683,5684,5685,5686,5687,5688,5689,5690,5691,5692,5693,
93043 5694,5695,5696,5697,5698,5699,5700,5701,5702,5703,5704,5705,5706,5707,5708,
93044 5709,5710,5711,5712,5713,5714,5715,5716,5717,5718,5719,5720,5721,5722,5723,
93045 5724,5725,5726,5727,5728,5729,5730,5731,5732,5733,5734,5735,5736,5737,5738,
93046 5739,5740,5741,5742,5743,5744,5745,5746,5747,5748,5749,5750,5751,5752,5753,
93047 5754,5755,5756,5757,5758,5759,5760,5761,5762,5763,5764,5765,5766,5767,5768,
93048 5769,5770,5771,5772,5773,5774,5775,5776,5777,5778,5779,5780,5781,5782,5783,
93049 5784,5785,5786,5787,5788,5789,5790,5791,5792,5793,5794,5795,5796,5797,5798,
93050 5799,5800,5801,5802,5803,5804,5805,5806,5807,5808,5809,5810,5811,5812,5813,
93051 5814,5815,5816,5817,5818,5819,5820,5821,5822,5823,5824,5825,5826,5827,5828,
93052 5829,5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840,5841,5842,5843,
93053 5844,5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856,5857,5858,
93054 5859,5860,5861,5862,5863,5864,5865,5866,5867,5868,5869,5870,5871,5872,5873,
93055 5874,5875,5876,5877,5878,5879,5880,5881,5882,5883,5884,5885,5886,5887,5888,
93056 5889,5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,
93057 5904,5905,5906,5907,5908,5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,
93058 5919,5920,5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,
93059 5934,5935,5936,5937,5938,5939,5940,5941,5942,5943,5944,5945,5946,5947,5948,
93060 5949,5950,5951,5952,5953,5954,5955,5956,5957,5958,5959,5960,5961,5962,5963,
93061 5964,5965,5966,5967,5968,5969,5970,5971,5972,5973,5974,5975,5976,5977,5978,
93062 5979,5980,5981,5982,5983,5984,5985,5986,5987,5988,5989,5990,5991,5992,5993,
93063 5994,5995,5996,5997,5998,5999,6000,6001,6002,6003,6004,6005,6006,6007,6008,
93064 6009,6010,6011,6012,6013,6014,6015,6016,6017,6018,6019,6020,6021,6022,6023,
93065 6024,6025,6026,6027,6028,6029,6030,6031,6032,6033,6034,6035,6036,6037,6038,
93066 6039,6040,6041,6042,6043,6044,6045,6046,6047,6048,6049,6050,6051,6052,6053,
93067 6054,6055,6056,6057,6058,6059,6060,6061,6062,6063,6064,6065,6066,6067,6068,
93068 6069,6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080,6081,6082,6083,
93069 6084,6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096,6097,6098,
93070 6099,6100,6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112,6113,
93071 6114,6115,6116,6117,6118,6119,6120,6121,6122,6123,6124,6125,6126,6127,6128,
93072 6129,6130,6131,6132,6133,6134,6135,6136,6137,6138,6139,6140,6141,6142,6143,
93073 6144,6145,6146,6147,6148,6149,6150,6151,6152,6153,6154,6155,6156,6157,6158,
93074 6159,6160,6161,6162,6163,6164,6165,6166,6167,6168,6169,6170,6171,6172,6173,
93075 6174,6175,6176,6177,6178,6179,6180,6181,6182,6183,6184,6185,6186,6187,6188,
93076 6189,6190,6191,6192,6193,6194,6195,6196,6197,6198,6199,6200,6201,6202,6203,
93077 6204,6205,6206,6207,6208,6209,6210,6211,6212,6213,6214,6215,6216,6217,6218,
93078 6219,6220,6221,6222,6223,6224,6225,6226,6227,6228,6229,6230,6231,6232,6233,
93079 6234,6235,6236,6237,6238,6239,6240,6241,6242,6243,6244,6245,6246,6247,6248,
93080 6249,6250,6251,6252,6253,6254,6255,6256,6257,6258,6259,6260,6261,6262,6263,
93081 6264,6265,6266,6267,6268,6269,6270,6271,6272,6273,6274,6275,6276,6277,6278,
93082 6279,6280,6281,6282,6283,6284,6285,6286,6287,6288,6289,6290,6291,6292,6293,
93083 6294,6295,6296,6297,6298,6299,6300,6301,6302,6303,6304,6305,6306,6307,6308,
93084 6309,6310,6311,6312,6313,6314,6315,6316,6317,6318,6319,6320,6321,6322,6323,
93085 6324,6325,6326,6327,6328,6329,6330,6331,6332,6333,6334,6335,6336,6337,6338,
93086 6339,6340,6341,6342,6343,6344,6345,6346,6347,6348,6349,6350,6351,6352,6353,
93087 6354,6355,6356,6357,6358,6359,6360,6361,6362,6363,6364,6365,6366,6367,6368,
93088 6369,6370,6371,6372,6373,6374,6375,6376,6377,6378,6379,6380,6381,6382,6383,
93089 6384,6385,6386,6387,6388,6389,6390,6391,6392,6393,6394,6395,6396,6397,6398,
93090 6399,6400,6401,6402,6403,6404,6405,6406,6407,6408,6409,6410,6411,6412,6413,
93091 6414,6415,6416,6417,6418,6419,6420,6421,6422,6423,6424,6425,6426,6427,6428,
93092 6429,6430,6431,6432,6433,6434,6435,6436,6437,6438,6439,6440,6441,6442,6443,
93093 6444,6445,6446,6447,6448,6449,6450,6451,6452,6453,6454,6455,6456,6457,6458,
93094 6459,6460,6461,6462,6463,6464,6465,6466,6467,6468,6469,6470,6471,6472,6473,
93095 6474,6475,6476,6477,6478,6479,6480,6481,6482,6483,6484,6485,6486,6487,6488,
93096 6489,6490,6491,6492,6493,6494,6495,6496,6497,6498,6499,6500,6501,6502,6503,
93097 6504,6505,6506,6507,6508,6509,6510,6511,6512,6513,6514,6515,6516,6517,6518,
93098 6519,6520,6521,6522,6523,6524,6525,6526,6527,6528,6529,6530,6531,6532,6533,
93099 6534,6535,6536,6537,6538,6539,6540,6541,6542,6543,6544,6545,6546,6547,6548,
93100 6549,6550,6551,6552,6553,6554,6555,6556,6557,6558,6559,6560,6561,6562,6563,
93101 6564,6565,6566,6567,6568,6569,6570,6571,6572,6573,6574,6575,6576,6577,6578,
93102 6579,6580,6581,6582,6583,6584,6585,6586,6587,6588,6589,6590,6591,6592,6593,
93103 6594,6595,6596,6597,6598,6599,6600,6601,6602,6603,6604,6605,6606,6607,6608,
93104 6609,6610,6611,6612,6613,6614,6615,6616,6617,6618,6619,6620,6621,6622,6623,
93105 6624,6625,6626,6627,6628,6629,6630,6631,6632,6633,6634,6635,6636,6637,6638,
93106 6639,6640,6641,6642,6643,6644,6645,6646,6647,6648,6649,6650,6651,6652,6653,
93107 6654,6655,6656,6657,6658,6659,6660,6661,6662,6663,6664,6665,6666,6667,6668,
93108 6669,6670,6671,6672,6673,6674,6675,6676,6677,6678,6679,6680,6681,6682,6683,
93109 6684,6685,6686,6687,6688,6689,6690,6691,6692,6693,6694,6695,6696,6697,6698,
93110 6699,6700,6701,6702,6703,6704,6705,6706,6707,6708,6709,6710,6711,6712,6713,
93111 6714,6715,6716,6717,6718,6719,6720,6721,6722,6723,6724,6725,6726,6727,6728,
93112 6729,6730,6731,6732,6733,6734,6735,6736,6737,6738,6739,6740,6741,6742,6743,
93113 6744,6745,6746,6747,6748,6749,6750,6751,6752,6753,6754,6755,6756,6757,6758,
93114 6759,6760,6761,6762,6763,6764,6765,6766,6767,6768,6769,6770,6771,6772,6773,
93115 6774,6775,6776,6777,6778,6779,6780,6781,6782,6783,6784,6785,6786,6787,6788,
93116 6789,6790,6791,6792,6793,6794,6795,6796,6797,6798,6799,6800,6801,6802,6803,
93117 6804,6805,6806,6807,6808,6809,6810,6811,6812,6813,6814,6815,6816,6817,6818,
93118 6819,6820,6821,6822,6823,6824,6825,6826,6827,6828,6829,6830,6831,6832,6833,
93119 6834,6835,6836,6837,6838,6839,6840,6841,6842,6843,6844,6845,6846,6847,6848,
93120 6849,6850,6851,6852,6853,6854,6855,6856,6857,6858,6859,6860,6861,6862,6863,
93121 6864,6865,6866,6867,6868,6869,6870,6871,6872,6873,6874,6875,6876,6877,6878,
93122 6879,6880,6881,6882,6883,6884,6885,6886,6887,6888,6889,6890,6891,6892,6893,
93123 6894,6895,6896,6897,6898,6899,6900,6901,6902,6903,6904,6905,6906,6907,6908,
93124 6909,6910,6911,6912,6913,6914,6915,6916,6917,6918,6919,6920,6921,6922,6923,
93125 6924,6925,6926,6927,6928,6929,6930,6931,6932,6933,6934,6935,6936,6937,6938,
93126 6939,6940,6941,6942,6943,6944,6945,6946,6947,6948,6949,6950,6951,6952,6953,
93127 6954,6955,6956,6957,6958,6959,6960,6961,6962,6963,6964,6965,6966,6967,6968,
93128 6969,6970,6971,6972,6973,6974,6975,6976,6977,6978,6979,6980,6981,6982,6983,
93129 6984,6985,6986,6987,6988,6989,6990,6991,6992,6993,6994,6995,6996,6997,6998,
93130 6999,7000,7001,7002,7003,7004,7005,7006,7007,7008,7009,7010,7011,7012,7013,
93131 7014,7015,7016,7017,7018,7019,7020,7021,7022,7023,7024,7025,7026,7027,7028,
93132 7029,7030,7031,7032,7033,7034,7035,7036,7037,7038,7039,7040,7041,7042,7043,
93133 7044,7045,7046,7047,7048,7049,7050,7051,7052,7053,7054,7055,7056,7057,7058,
93134 7059,7060,7061,7062,7063,7064,7065,7066,7067,7068,7069,7070,7071,7072,7073,
93135 7074,7075,7076,7077,7078,7079,7080,7081,7082,7083,7084,7085,7086,7087,7088,
93136 7089,7090,7091,7092,7093,7094,7095,7096,7097,7098,7099,7100,7101,7102,7103,
93137 7104,7105,7106,7107,7108,7109,7110,7111,7112,7113,7114,7115,7116,7117,7118,
93138 7119,7120,7121,7122,7123,7124,7125,7126,7127,7128,7129,7130,7131,7132,7133,
93139 7134,7135,7136,7137,7138,7139,7140,7141,7142,7143,7144,7145,7146,7147,7148,
93140 7149,7150,7151,7152,7153,7154,7155,7156,7157,7158,7159,7160,7161,7162,7163,
93141 7164,7165,7166,7167,7168,7169,7170,7171,7172,7173,7174,7175,7176,7177,7178,
93142 7179,7180,7181,7182,7183,7184,7185,7186,7187,7188,7189,7190,7191,7192,7193,
93143 7194,7195,7196,7197,7198,7199,7200,7201,7202,7203,7204,7205,7206,7207,7208,
93144 7209,7210,7211,7212,7213,7214,7215,7216,7217,7218,7219,7220,7221,7222,7223,
93145 7224,7225,7226,7227,7228,7229,7230,7231,7232,7233,7234,7235,7236,7237,7238,
93146 7239,7240,7241,7242,7243,7244,7245,7246,7247,7248,7249,7250,7251,7252,7253,
93147 7254,7255,7256,7257,7258,7259,7260,7261,7262,7263,7264,7265,7266,7267,7268,
93148 7269,7270,7271,7272,7273,7274,7275,7276,7277,7278,7279,7280,7281,7282,7283,
93149 7284,7285,7286,7287,7288,7289,7290,7291,7292,7293,7294,7295,1042,1044,1054,
93150 1057,1058,1058,1066,1122,42570L,7305,7306,7307,7308,7309,7310,7311,7312,
93151 7313,7314,7315,7316,7317,7318,7319,7320,7321,7322,7323,7324,7325,7326,7327,
93152 7328,7329,7330,7331,7332,7333,7334,7335,7336,7337,7338,7339,7340,7341,7342,
93153 7343,7344,7345,7346,7347,7348,7349,7350,7351,7352,7353,7354,7355,7356,7357,
93154 7358,7359,7360,7361,7362,7363,7364,7365,7366,7367,7368,7369,7370,7371,7372,
93155 7373,7374,7375,7376,7377,7378,7379,7380,7381,7382,7383,7384,7385,7386,7387,
93156 7388,7389,7390,7391,7392,7393,7394,7395,7396,7397,7398,7399,7400,7401,7402,
93157 7403,7404,7405,7406,7407,7408,7409,7410,7411,7412,7413,7414,7415,7416,7417,
93158 7418,7419,7420,7421,7422,7423,7424,7425,7426,7427,7428,7429,7430,7431,7432,
93159 7433,7434,7435,7436,7437,7438,7439,7440,7441,7442,7443,7444,7445,7446,7447,
93160 7448,7449,7450,7451,7452,7453,7454,7455,7456,7457,7458,7459,7460,7461,7462,
93161 7463,7464,7465,7466,7467,7468,7469,7470,7471,7472,7473,7474,7475,7476,7477,
93162 7478,7479,7480,7481,7482,7483,7484,7485,7486,7487,7488,7489,7490,7491,7492,
93163 7493,7494,7495,7496,7497,7498,7499,7500,7501,7502,7503,7504,7505,7506,7507,
93164 7508,7509,7510,7511,7512,7513,7514,7515,7516,7517,7518,7519,7520,7521,7522,
93165 7523,7524,7525,7526,7527,7528,7529,7530,7531,7532,7533,7534,7535,7536,7537,
93166 7538,7539,7540,7541,7542,7543,7544,42877L,7546,7547,7548,11363,7550,7551,
93167 7552,7553,7554,7555,7556,7557,7558,7559,7560,7561,7562,7563,7564,7565,
93168 42950L,7567,7568,7569,7570,7571,7572,7573,7574,7575,7576,7577,7578,7579,
93169 7580,7581,7582,7583,7584,7585,7586,7587,7588,7589,7590,7591,7592,7593,7594,
93170 7595,7596,7597,7598,7599,7600,7601,7602,7603,7604,7605,7606,7607,7608,7609,
93171 7610,7611,7612,7613,7614,7615,7616,7617,7618,7619,7620,7621,7622,7623,7624,
93172 7625,7626,7627,7628,7629,7630,7631,7632,7633,7634,7635,7636,7637,7638,7639,
93173 7640,7641,7642,7643,7644,7645,7646,7647,7648,7649,7650,7651,7652,7653,7654,
93174 7655,7656,7657,7658,7659,7660,7661,7662,7663,7664,7665,7666,7667,7668,7669,
93175 7670,7671,7672,7673,7674,7675,7676,7677,7678,7679,7680,7680,7682,7682,7684,
93176 7684,7686,7686,7688,7688,7690,7690,7692,7692,7694,7694,7696,7696,7698,7698,
93177 7700,7700,7702,7702,7704,7704,7706,7706,7708,7708,7710,7710,7712,7712,7714,
93178 7714,7716,7716,7718,7718,7720,7720,7722,7722,7724,7724,7726,7726,7728,7728,
93179 7730,7730,7732,7732,7734,7734,7736,7736,7738,7738,7740,7740,7742,7742,7744,
93180 7744,7746,7746,7748,7748,7750,7750,7752,7752,7754,7754,7756,7756,7758,7758,
93181 7760,7760,7762,7762,7764,7764,7766,7766,7768,7768,7770,7770,7772,7772,7774,
93182 7774,7776,7776,7778,7778,7780,7780,7782,7782,7784,7784,7786,7786,7788,7788,
93183 7790,7790,7792,7792,7794,7794,7796,7796,7798,7798,7800,7800,7802,7802,7804,
93184 7804,7806,7806,7808,7808,7810,7810,7812,7812,7814,7814,7816,7816,7818,7818,
93185 7820,7820,7822,7822,7824,7824,7826,7826,7828,7828,7830,7831,7832,7833,7834,
93186 7776,7836,7837,7838,7839,7840,7840,7842,7842,7844,7844,7846,7846,7848,7848,
93187 7850,7850,7852,7852,7854,7854,7856,7856,7858,7858,7860,7860,7862,7862,7864,
93188 7864,7866,7866,7868,7868,7870,7870,7872,7872,7874,7874,7876,7876,7878,7878,
93189 7880,7880,7882,7882,7884,7884,7886,7886,7888,7888,7890,7890,7892,7892,7894,
93190 7894,7896,7896,7898,7898,7900,7900,7902,7902,7904,7904,7906,7906,7908,7908,
93191 7910,7910,7912,7912,7914,7914,7916,7916,7918,7918,7920,7920,7922,7922,7924,
93192 7924,7926,7926,7928,7928,7930,7930,7932,7932,7934,7934,7944,7945,7946,7947,
93193 7948,7949,7950,7951,7944,7945,7946,7947,7948,7949,7950,7951,7960,7961,7962,
93194 7963,7964,7965,7958,7959,7960,7961,7962,7963,7964,7965,7966,7967,7976,7977,
93195 7978,7979,7980,7981,7982,7983,7976,7977,7978,7979,7980,7981,7982,7983,7992,
93196 7993,7994,7995,7996,7997,7998,7999,7992,7993,7994,7995,7996,7997,7998,7999,
93197 8008,8009,8010,8011,8012,8013,8006,8007,8008,8009,8010,8011,8012,8013,8014,
93198 8015,8016,8025,8018,8027,8020,8029,8022,8031,8024,8025,8026,8027,8028,8029,
93199 8030,8031,8040,8041,8042,8043,8044,8045,8046,8047,8040,8041,8042,8043,8044,
93200 8045,8046,8047,8122,8123,8136,8137,8138,8139,8154,8155,8184,8185,8170,8171,
93201 8186,8187,8062,8063,8064,8065,8066,8067,8068,8069,8070,8071,8072,8073,8074,
93202 8075,8076,8077,8078,8079,8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,
93203 8090,8091,8092,8093,8094,8095,8096,8097,8098,8099,8100,8101,8102,8103,8104,
93204 8105,8106,8107,8108,8109,8110,8111,8120,8121,8114,8115,8116,8117,8118,8119,
93205 8120,8121,8122,8123,8124,8125,921,8127,8128,8129,8130,8131,8132,8133,8134,
93206 8135,8136,8137,8138,8139,8140,8141,8142,8143,8152,8153,8146,8147,8148,8149,
93207 8150,8151,8152,8153,8154,8155,8156,8157,8158,8159,8168,8169,8162,8163,8164,
93208 8172,8166,8167,8168,8169,8170,8171,8172,8173,8174,8175,8176,8177,8178,8179,
93209 8180,8181,8182,8183,8184,8185,8186,8187,8188,8189,8190,8191,8192,8193,8194,
93210 8195,8196,8197,8198,8199,8200,8201,8202,8203,8204,8205,8206,8207,8208,8209,
93211 8210,8211,8212,8213,8214,8215,8216,8217,8218,8219,8220,8221,8222,8223,8224,
93212 8225,8226,8227,8228,8229,8230,8231,8232,8233,8234,8235,8236,8237,8238,8239,
93213 8240,8241,8242,8243,8244,8245,8246,8247,8248,8249,8250,8251,8252,8253,8254,
93214 8255,8256,8257,8258,8259,8260,8261,8262,8263,8264,8265,8266,8267,8268,8269,
93215 8270,8271,8272,8273,8274,8275,8276,8277,8278,8279,8280,8281,8282,8283,8284,
93216 8285,8286,8287,8288,8289,8290,8291,8292,8293,8294,8295,8296,8297,8298,8299,
93217 8300,8301,8302,8303,8304,8305,8306,8307,8308,8309,8310,8311,8312,8313,8314,
93218 8315,8316,8317,8318,8319,8320,8321,8322,8323,8324,8325,8326,8327,8328,8329,
93219 8330,8331,8332,8333,8334,8335,8336,8337,8338,8339,8340,8341,8342,8343,8344,
93220 8345,8346,8347,8348,8349,8350,8351,8352,8353,8354,8355,8356,8357,8358,8359,
93221 8360,8361,8362,8363,8364,8365,8366,8367,8368,8369,8370,8371,8372,8373,8374,
93222 8375,8376,8377,8378,8379,8380,8381,8382,8383,8384,8385,8386,8387,8388,8389,
93223 8390,8391,8392,8393,8394,8395,8396,8397,8398,8399,8400,8401,8402,8403,8404,
93224 8405,8406,8407,8408,8409,8410,8411,8412,8413,8414,8415,8416,8417,8418,8419,
93225 8420,8421,8422,8423,8424,8425,8426,8427,8428,8429,8430,8431,8432,8433,8434,
93226 8435,8436,8437,8438,8439,8440,8441,8442,8443,8444,8445,8446,8447,8448,8449,
93227 8450,8451,8452,8453,8454,8455,8456,8457,8458,8459,8460,8461,8462,8463,8464,
93228 8465,8466,8467,8468,8469,8470,8471,8472,8473,8474,8475,8476,8477,8478,8479,
93229 8480,8481,8482,8483,8484,8485,8486,8487,8488,8489,8490,8491,8492,8493,8494,
93230 8495,8496,8497,8498,8499,8500,8501,8502,8503,8504,8505,8506,8507,8508,8509,
93231 8510,8511,8512,8513,8514,8515,8516,8517,8518,8519,8520,8521,8522,8523,8524,
93232 8525,8498,8527,8528,8529,8530,8531,8532,8533,8534,8535,8536,8537,8538,8539,
93233 8540,8541,8542,8543,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,
93234 8555,8556,8557,8558,8559,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,
93235 8554,8555,8556,8557,8558,8559,8576,8577,8578,8579,8579,8581,8582,8583,8584,
93236 8585,8586,8587,8588,8589,8590,8591,8592,8593,8594,8595,8596,8597,8598,8599,
93237 8600,8601,8602,8603,8604,8605,8606,8607,8608,8609,8610,8611,8612,8613,8614,
93238 8615,8616,8617,8618,8619,8620,8621,8622,8623,8624,8625,8626,8627,8628,8629,
93239 8630,8631,8632,8633,8634,8635,8636,8637,8638,8639,8640,8641,8642,8643,8644,
93240 8645,8646,8647,8648,8649,8650,8651,8652,8653,8654,8655,8656,8657,8658,8659,
93241 8660,8661,8662,8663,8664,8665,8666,8667,8668,8669,8670,8671,8672,8673,8674,
93242 8675,8676,8677,8678,8679,8680,8681,8682,8683,8684,8685,8686,8687,8688,8689,
93243 8690,8691,8692,8693,8694,8695,8696,8697,8698,8699,8700,8701,8702,8703,8704,
93244 8705,8706,8707,8708,8709,8710,8711,8712,8713,8714,8715,8716,8717,8718,8719,
93245 8720,8721,8722,8723,8724,8725,8726,8727,8728,8729,8730,8731,8732,8733,8734,
93246 8735,8736,8737,8738,8739,8740,8741,8742,8743,8744,8745,8746,8747,8748,8749,
93247 8750,8751,8752,8753,8754,8755,8756,8757,8758,8759,8760,8761,8762,8763,8764,
93248 8765,8766,8767,8768,8769,8770,8771,8772,8773,8774,8775,8776,8777,8778,8779,
93249 8780,8781,8782,8783,8784,8785,8786,8787,8788,8789,8790,8791,8792,8793,8794,
93250 8795,8796,8797,8798,8799,8800,8801,8802,8803,8804,8805,8806,8807,8808,8809,
93251 8810,8811,8812,8813,8814,8815,8816,8817,8818,8819,8820,8821,8822,8823,8824,
93252 8825,8826,8827,8828,8829,8830,8831,8832,8833,8834,8835,8836,8837,8838,8839,
93253 8840,8841,8842,8843,8844,8845,8846,8847,8848,8849,8850,8851,8852,8853,8854,
93254 8855,8856,8857,8858,8859,8860,8861,8862,8863,8864,8865,8866,8867,8868,8869,
93255 8870,8871,8872,8873,8874,8875,8876,8877,8878,8879,8880,8881,8882,8883,8884,
93256 8885,8886,8887,8888,8889,8890,8891,8892,8893,8894,8895,8896,8897,8898,8899,
93257 8900,8901,8902,8903,8904,8905,8906,8907,8908,8909,8910,8911,8912,8913,8914,
93258 8915,8916,8917,8918,8919,8920,8921,8922,8923,8924,8925,8926,8927,8928,8929,
93259 8930,8931,8932,8933,8934,8935,8936,8937,8938,8939,8940,8941,8942,8943,8944,
93260 8945,8946,8947,8948,8949,8950,8951,8952,8953,8954,8955,8956,8957,8958,8959,
93261 8960,8961,8962,8963,8964,8965,8966,8967,8968,8969,8970,8971,8972,8973,8974,
93262 8975,8976,8977,8978,8979,8980,8981,8982,8983,8984,8985,8986,8987,8988,8989,
93263 8990,8991,8992,8993,8994,8995,8996,8997,8998,8999,9000,9001,9002,9003,9004,
93264 9005,9006,9007,9008,9009,9010,9011,9012,9013,9014,9015,9016,9017,9018,9019,
93265 9020,9021,9022,9023,9024,9025,9026,9027,9028,9029,9030,9031,9032,9033,9034,
93266 9035,9036,9037,9038,9039,9040,9041,9042,9043,9044,9045,9046,9047,9048,9049,
93267 9050,9051,9052,9053,9054,9055,9056,9057,9058,9059,9060,9061,9062,9063,9064,
93268 9065,9066,9067,9068,9069,9070,9071,9072,9073,9074,9075,9076,9077,9078,9079,
93269 9080,9081,9082,9083,9084,9085,9086,9087,9088,9089,9090,9091,9092,9093,9094,
93270 9095,9096,9097,9098,9099,9100,9101,9102,9103,9104,9105,9106,9107,9108,9109,
93271 9110,9111,9112,9113,9114,9115,9116,9117,9118,9119,9120,9121,9122,9123,9124,
93272 9125,9126,9127,9128,9129,9130,9131,9132,9133,9134,9135,9136,9137,9138,9139,
93273 9140,9141,9142,9143,9144,9145,9146,9147,9148,9149,9150,9151,9152,9153,9154,
93274 9155,9156,9157,9158,9159,9160,9161,9162,9163,9164,9165,9166,9167,9168,9169,
93275 9170,9171,9172,9173,9174,9175,9176,9177,9178,9179,9180,9181,9182,9183,9184,
93276 9185,9186,9187,9188,9189,9190,9191,9192,9193,9194,9195,9196,9197,9198,9199,
93277 9200,9201,9202,9203,9204,9205,9206,9207,9208,9209,9210,9211,9212,9213,9214,
93278 9215,9216,9217,9218,9219,9220,9221,9222,9223,9224,9225,9226,9227,9228,9229,
93279 9230,9231,9232,9233,9234,9235,9236,9237,9238,9239,9240,9241,9242,9243,9244,
93280 9245,9246,9247,9248,9249,9250,9251,9252,9253,9254,9255,9256,9257,9258,9259,
93281 9260,9261,9262,9263,9264,9265,9266,9267,9268,9269,9270,9271,9272,9273,9274,
93282 9275,9276,9277,9278,9279,9280,9281,9282,9283,9284,9285,9286,9287,9288,9289,
93283 9290,9291,9292,9293,9294,9295,9296,9297,9298,9299,9300,9301,9302,9303,9304,
93284 9305,9306,9307,9308,9309,9310,9311,9312,9313,9314,9315,9316,9317,9318,9319,
93285 9320,9321,9322,9323,9324,9325,9326,9327,9328,9329,9330,9331,9332,9333,9334,
93286 9335,9336,9337,9338,9339,9340,9341,9342,9343,9344,9345,9346,9347,9348,9349,
93287 9350,9351,9352,9353,9354,9355,9356,9357,9358,9359,9360,9361,9362,9363,9364,
93288 9365,9366,9367,9368,9369,9370,9371,9372,9373,9374,9375,9376,9377,9378,9379,
93289 9380,9381,9382,9383,9384,9385,9386,9387,9388,9389,9390,9391,9392,9393,9394,
93290 9395,9396,9397,9398,9399,9400,9401,9402,9403,9404,9405,9406,9407,9408,9409,
93291 9410,9411,9412,9413,9414,9415,9416,9417,9418,9419,9420,9421,9422,9423,9398,
93292 9399,9400,9401,9402,9403,9404,9405,9406,9407,9408,9409,9410,9411,9412,9413,
93293 9414,9415,9416,9417,9418,9419,9420,9421,9422,9423,9450,9451,9452,9453,9454,
93294 9455,9456,9457,9458,9459,9460,9461,9462,9463,9464,9465,9466,9467,9468,9469,
93295 9470,9471,9472,9473,9474,9475,9476,9477,9478,9479,9480,9481,9482,9483,9484,
93296 9485,9486,9487,9488,9489,9490,9491,9492,9493,9494,9495,9496,9497,9498,9499,
93297 9500,9501,9502,9503,9504,9505,9506,9507,9508,9509,9510,9511,9512,9513,9514,
93298 9515,9516,9517,9518,9519,9520,9521,9522,9523,9524,9525,9526,9527,9528,9529,
93299 9530,9531,9532,9533,9534,9535,9536,9537,9538,9539,9540,9541,9542,9543,9544,
93300 9545,9546,9547,9548,9549,9550,9551,9552,9553,9554,9555,9556,9557,9558,9559,
93301 9560,9561,9562,9563,9564,9565,9566,9567,9568,9569,9570,9571,9572,9573,9574,
93302 9575,9576,9577,9578,9579,9580,9581,9582,9583,9584,9585,9586,9587,9588,9589,
93303 9590,9591,9592,9593,9594,9595,9596,9597,9598,9599,9600,9601,9602,9603,9604,
93304 9605,9606,9607,9608,9609,9610,9611,9612,9613,9614,9615,9616,9617,9618,9619,
93305 9620,9621,9622,9623,9624,9625,9626,9627,9628,9629,9630,9631,9632,9633,9634,
93306 9635,9636,9637,9638,9639,9640,9641,9642,9643,9644,9645,9646,9647,9648,9649,
93307 9650,9651,9652,9653,9654,9655,9656,9657,9658,9659,9660,9661,9662,9663,9664,
93308 9665,9666,9667,9668,9669,9670,9671,9672,9673,9674,9675,9676,9677,9678,9679,
93309 9680,9681,9682,9683,9684,9685,9686,9687,9688,9689,9690,9691,9692,9693,9694,
93310 9695,9696,9697,9698,9699,9700,9701,9702,9703,9704,9705,9706,9707,9708,9709,
93311 9710,9711,9712,9713,9714,9715,9716,9717,9718,9719,9720,9721,9722,9723,9724,
93312 9725,9726,9727,9728,9729,9730,9731,9732,9733,9734,9735,9736,9737,9738,9739,
93313 9740,9741,9742,9743,9744,9745,9746,9747,9748,9749,9750,9751,9752,9753,9754,
93314 9755,9756,9757,9758,9759,9760,9761,9762,9763,9764,9765,9766,9767,9768,9769,
93315 9770,9771,9772,9773,9774,9775,9776,9777,9778,9779,9780,9781,9782,9783,9784,
93316 9785,9786,9787,9788,9789,9790,9791,9792,9793,9794,9795,9796,9797,9798,9799,
93317 9800,9801,9802,9803,9804,9805,9806,9807,9808,9809,9810,9811,9812,9813,9814,
93318 9815,9816,9817,9818,9819,9820,9821,9822,9823,9824,9825,9826,9827,9828,9829,
93319 9830,9831,9832,9833,9834,9835,9836,9837,9838,9839,9840,9841,9842,9843,9844,
93320 9845,9846,9847,9848,9849,9850,9851,9852,9853,9854,9855,9856,9857,9858,9859,
93321 9860,9861,9862,9863,9864,9865,9866,9867,9868,9869,9870,9871,9872,9873,9874,
93322 9875,9876,9877,9878,9879,9880,9881,9882,9883,9884,9885,9886,9887,9888,9889,
93323 9890,9891,9892,9893,9894,9895,9896,9897,9898,9899,9900,9901,9902,9903,9904,
93324 9905,9906,9907,9908,9909,9910,9911,9912,9913,9914,9915,9916,9917,9918,9919,
93325 9920,9921,9922,9923,9924,9925,9926,9927,9928,9929,9930,9931,9932,9933,9934,
93326 9935,9936,9937,9938,9939,9940,9941,9942,9943,9944,9945,9946,9947,9948,9949,
93327 9950,9951,9952,9953,9954,9955,9956,9957,9958,9959,9960,9961,9962,9963,9964,
93328 9965,9966,9967,9968,9969,9970,9971,9972,9973,9974,9975,9976,9977,9978,9979,
93329 9980,9981,9982,9983,9984,9985,9986,9987,9988,9989,9990,9991,9992,9993,9994,
93330 9995,9996,9997,9998,9999,10000,10001,10002,10003,10004,10005,10006,10007,
93331 10008,10009,10010,10011,10012,10013,10014,10015,10016,10017,10018,10019,
93332 10020,10021,10022,10023,10024,10025,10026,10027,10028,10029,10030,10031,
93333 10032,10033,10034,10035,10036,10037,10038,10039,10040,10041,10042,10043,
93334 10044,10045,10046,10047,10048,10049,10050,10051,10052,10053,10054,10055,
93335 10056,10057,10058,10059,10060,10061,10062,10063,10064,10065,10066,10067,
93336 10068,10069,10070,10071,10072,10073,10074,10075,10076,10077,10078,10079,
93337 10080,10081,10082,10083,10084,10085,10086,10087,10088,10089,10090,10091,
93338 10092,10093,10094,10095,10096,10097,10098,10099,10100,10101,10102,10103,
93339 10104,10105,10106,10107,10108,10109,10110,10111,10112,10113,10114,10115,
93340 10116,10117,10118,10119,10120,10121,10122,10123,10124,10125,10126,10127,
93341 10128,10129,10130,10131,10132,10133,10134,10135,10136,10137,10138,10139,
93342 10140,10141,10142,10143,10144,10145,10146,10147,10148,10149,10150,10151,
93343 10152,10153,10154,10155,10156,10157,10158,10159,10160,10161,10162,10163,
93344 10164,10165,10166,10167,10168,10169,10170,10171,10172,10173,10174,10175,
93345 10176,10177,10178,10179,10180,10181,10182,10183,10184,10185,10186,10187,
93346 10188,10189,10190,10191,10192,10193,10194,10195,10196,10197,10198,10199,
93347 10200,10201,10202,10203,10204,10205,10206,10207,10208,10209,10210,10211,
93348 10212,10213,10214,10215,10216,10217,10218,10219,10220,10221,10222,10223,
93349 10224,10225,10226,10227,10228,10229,10230,10231,10232,10233,10234,10235,
93350 10236,10237,10238,10239,10240,10241,10242,10243,10244,10245,10246,10247,
93351 10248,10249,10250,10251,10252,10253,10254,10255,10256,10257,10258,10259,
93352 10260,10261,10262,10263,10264,10265,10266,10267,10268,10269,10270,10271,
93353 10272,10273,10274,10275,10276,10277,10278,10279,10280,10281,10282,10283,
93354 10284,10285,10286,10287,10288,10289,10290,10291,10292,10293,10294,10295,
93355 10296,10297,10298,10299,10300,10301,10302,10303,10304,10305,10306,10307,
93356 10308,10309,10310,10311,10312,10313,10314,10315,10316,10317,10318,10319,
93357 10320,10321,10322,10323,10324,10325,10326,10327,10328,10329,10330,10331,
93358 10332,10333,10334,10335,10336,10337,10338,10339,10340,10341,10342,10343,
93359 10344,10345,10346,10347,10348,10349,10350,10351,10352,10353,10354,10355,
93360 10356,10357,10358,10359,10360,10361,10362,10363,10364,10365,10366,10367,
93361 10368,10369,10370,10371,10372,10373,10374,10375,10376,10377,10378,10379,
93362 10380,10381,10382,10383,10384,10385,10386,10387,10388,10389,10390,10391,
93363 10392,10393,10394,10395,10396,10397,10398,10399,10400,10401,10402,10403,
93364 10404,10405,10406,10407,10408,10409,10410,10411,10412,10413,10414,10415,
93365 10416,10417,10418,10419,10420,10421,10422,10423,10424,10425,10426,10427,
93366 10428,10429,10430,10431,10432,10433,10434,10435,10436,10437,10438,10439,
93367 10440,10441,10442,10443,10444,10445,10446,10447,10448,10449,10450,10451,
93368 10452,10453,10454,10455,10456,10457,10458,10459,10460,10461,10462,10463,
93369 10464,10465,10466,10467,10468,10469,10470,10471,10472,10473,10474,10475,
93370 10476,10477,10478,10479,10480,10481,10482,10483,10484,10485,10486,10487,
93371 10488,10489,10490,10491,10492,10493,10494,10495,10496,10497,10498,10499,
93372 10500,10501,10502,10503,10504,10505,10506,10507,10508,10509,10510,10511,
93373 10512,10513,10514,10515,10516,10517,10518,10519,10520,10521,10522,10523,
93374 10524,10525,10526,10527,10528,10529,10530,10531,10532,10533,10534,10535,
93375 10536,10537,10538,10539,10540,10541,10542,10543,10544,10545,10546,10547,
93376 10548,10549,10550,10551,10552,10553,10554,10555,10556,10557,10558,10559,
93377 10560,10561,10562,10563,10564,10565,10566,10567,10568,10569,10570,10571,
93378 10572,10573,10574,10575,10576,10577,10578,10579,10580,10581,10582,10583,
93379 10584,10585,10586,10587,10588,10589,10590,10591,10592,10593,10594,10595,
93380 10596,10597,10598,10599,10600,10601,10602,10603,10604,10605,10606,10607,
93381 10608,10609,10610,10611,10612,10613,10614,10615,10616,10617,10618,10619,
93382 10620,10621,10622,10623,10624,10625,10626,10627,10628,10629,10630,10631,
93383 10632,10633,10634,10635,10636,10637,10638,10639,10640,10641,10642,10643,
93384 10644,10645,10646,10647,10648,10649,10650,10651,10652,10653,10654,10655,
93385 10656,10657,10658,10659,10660,10661,10662,10663,10664,10665,10666,10667,
93386 10668,10669,10670,10671,10672,10673,10674,10675,10676,10677,10678,10679,
93387 10680,10681,10682,10683,10684,10685,10686,10687,10688,10689,10690,10691,
93388 10692,10693,10694,10695,10696,10697,10698,10699,10700,10701,10702,10703,
93389 10704,10705,10706,10707,10708,10709,10710,10711,10712,10713,10714,10715,
93390 10716,10717,10718,10719,10720,10721,10722,10723,10724,10725,10726,10727,
93391 10728,10729,10730,10731,10732,10733,10734,10735,10736,10737,10738,10739,
93392 10740,10741,10742,10743,10744,10745,10746,10747,10748,10749,10750,10751,
93393 10752,10753,10754,10755,10756,10757,10758,10759,10760,10761,10762,10763,
93394 10764,10765,10766,10767,10768,10769,10770,10771,10772,10773,10774,10775,
93395 10776,10777,10778,10779,10780,10781,10782,10783,10784,10785,10786,10787,
93396 10788,10789,10790,10791,10792,10793,10794,10795,10796,10797,10798,10799,
93397 10800,10801,10802,10803,10804,10805,10806,10807,10808,10809,10810,10811,
93398 10812,10813,10814,10815,10816,10817,10818,10819,10820,10821,10822,10823,
93399 10824,10825,10826,10827,10828,10829,10830,10831,10832,10833,10834,10835,
93400 10836,10837,10838,10839,10840,10841,10842,10843,10844,10845,10846,10847,
93401 10848,10849,10850,10851,10852,10853,10854,10855,10856,10857,10858,10859,
93402 10860,10861,10862,10863,10864,10865,10866,10867,10868,10869,10870,10871,
93403 10872,10873,10874,10875,10876,10877,10878,10879,10880,10881,10882,10883,
93404 10884,10885,10886,10887,10888,10889,10890,10891,10892,10893,10894,10895,
93405 10896,10897,10898,10899,10900,10901,10902,10903,10904,10905,10906,10907,
93406 10908,10909,10910,10911,10912,10913,10914,10915,10916,10917,10918,10919,
93407 10920,10921,10922,10923,10924,10925,10926,10927,10928,10929,10930,10931,
93408 10932,10933,10934,10935,10936,10937,10938,10939,10940,10941,10942,10943,
93409 10944,10945,10946,10947,10948,10949,10950,10951,10952,10953,10954,10955,
93410 10956,10957,10958,10959,10960,10961,10962,10963,10964,10965,10966,10967,
93411 10968,10969,10970,10971,10972,10973,10974,10975,10976,10977,10978,10979,
93412 10980,10981,10982,10983,10984,10985,10986,10987,10988,10989,10990,10991,
93413 10992,10993,10994,10995,10996,10997,10998,10999,11000,11001,11002,11003,
93414 11004,11005,11006,11007,11008,11009,11010,11011,11012,11013,11014,11015,
93415 11016,11017,11018,11019,11020,11021,11022,11023,11024,11025,11026,11027,
93416 11028,11029,11030,11031,11032,11033,11034,11035,11036,11037,11038,11039,
93417 11040,11041,11042,11043,11044,11045,11046,11047,11048,11049,11050,11051,
93418 11052,11053,11054,11055,11056,11057,11058,11059,11060,11061,11062,11063,
93419 11064,11065,11066,11067,11068,11069,11070,11071,11072,11073,11074,11075,
93420 11076,11077,11078,11079,11080,11081,11082,11083,11084,11085,11086,11087,
93421 11088,11089,11090,11091,11092,11093,11094,11095,11096,11097,11098,11099,
93422 11100,11101,11102,11103,11104,11105,11106,11107,11108,11109,11110,11111,
93423 11112,11113,11114,11115,11116,11117,11118,11119,11120,11121,11122,11123,
93424 11124,11125,11126,11127,11128,11129,11130,11131,11132,11133,11134,11135,
93425 11136,11137,11138,11139,11140,11141,11142,11143,11144,11145,11146,11147,
93426 11148,11149,11150,11151,11152,11153,11154,11155,11156,11157,11158,11159,
93427 11160,11161,11162,11163,11164,11165,11166,11167,11168,11169,11170,11171,
93428 11172,11173,11174,11175,11176,11177,11178,11179,11180,11181,11182,11183,
93429 11184,11185,11186,11187,11188,11189,11190,11191,11192,11193,11194,11195,
93430 11196,11197,11198,11199,11200,11201,11202,11203,11204,11205,11206,11207,
93431 11208,11209,11210,11211,11212,11213,11214,11215,11216,11217,11218,11219,
93432 11220,11221,11222,11223,11224,11225,11226,11227,11228,11229,11230,11231,
93433 11232,11233,11234,11235,11236,11237,11238,11239,11240,11241,11242,11243,
93434 11244,11245,11246,11247,11248,11249,11250,11251,11252,11253,11254,11255,
93435 11256,11257,11258,11259,11260,11261,11262,11263,11264,11265,11266,11267,
93436 11268,11269,11270,11271,11272,11273,11274,11275,11276,11277,11278,11279,
93437 11280,11281,11282,11283,11284,11285,11286,11287,11288,11289,11290,11291,
93438 11292,11293,11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,
93439 11304,11305,11306,11307,11308,11309,11310,11311,11264,11265,11266,11267,
93440 11268,11269,11270,11271,11272,11273,11274,11275,11276,11277,11278,11279,
93441 11280,11281,11282,11283,11284,11285,11286,11287,11288,11289,11290,11291,
93442 11292,11293,11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,
93443 11304,11305,11306,11307,11308,11309,11310,11359,11360,11360,11362,11363,
93444 11364,570,574,11367,11367,11369,11369,11371,11371,11373,11374,11375,11376,
93445 11377,11378,11378,11380,11381,11381,11383,11384,11385,11386,11387,11388,
93446 11389,11390,11391,11392,11392,11394,11394,11396,11396,11398,11398,11400,
93447 11400,11402,11402,11404,11404,11406,11406,11408,11408,11410,11410,11412,
93448 11412,11414,11414,11416,11416,11418,11418,11420,11420,11422,11422,11424,
93449 11424,11426,11426,11428,11428,11430,11430,11432,11432,11434,11434,11436,
93450 11436,11438,11438,11440,11440,11442,11442,11444,11444,11446,11446,11448,
93451 11448,11450,11450,11452,11452,11454,11454,11456,11456,11458,11458,11460,
93452 11460,11462,11462,11464,11464,11466,11466,11468,11468,11470,11470,11472,
93453 11472,11474,11474,11476,11476,11478,11478,11480,11480,11482,11482,11484,
93454 11484,11486,11486,11488,11488,11490,11490,11492,11493,11494,11495,11496,
93455 11497,11498,11499,11499,11501,11501,11503,11504,11505,11506,11506,11508,
93456 11509,11510,11511,11512,11513,11514,11515,11516,11517,11518,11519,4256,
93457 4257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,4270,4271,
93458 4272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,4285,4286,
93459 4287,4288,4289,4290,4291,4292,4293,11558,4295,11560,11561,11562,11563,
93460 11564,4301,11566,11567,11568,11569,11570,11571,11572,11573,11574,11575,
93461 11576,11577,11578,11579,11580,11581,11582,11583,11584,11585,11586,11587,
93462 11588,11589,11590,11591,11592,11593,11594,11595,11596,11597,11598,11599,
93463 11600,11601,11602,11603,11604,11605,11606,11607,11608,11609,11610,11611,
93464 11612,11613,11614,11615,11616,11617,11618,11619,11620,11621,11622,11623,
93465 11624,11625,11626,11627,11628,11629,11630,11631,11632,11633,11634,11635,
93466 11636,11637,11638,11639,11640,11641,11642,11643,11644,11645,11646,11647,
93467 11648,11649,11650,11651,11652,11653,11654,11655,11656,11657,11658,11659,
93468 11660,11661,11662,11663,11664,11665,11666,11667,11668,11669,11670,11671,
93469 11672,11673,11674,11675,11676,11677,11678,11679,11680,11681,11682,11683,
93470 11684,11685,11686,11687,11688,11689,11690,11691,11692,11693,11694,11695,
93471 11696,11697,11698,11699,11700,11701,11702,11703,11704,11705,11706,11707,
93472 11708,11709,11710,11711,11712,11713,11714,11715,11716,11717,11718,11719,
93473 11720,11721,11722,11723,11724,11725,11726,11727,11728,11729,11730,11731,
93474 11732,11733,11734,11735,11736,11737,11738,11739,11740,11741,11742,11743,
93475 11744,11745,11746,11747,11748,11749,11750,11751,11752,11753,11754,11755,
93476 11756,11757,11758,11759,11760,11761,11762,11763,11764,11765,11766,11767,
93477 11768,11769,11770,11771,11772,11773,11774,11775,11776,11777,11778,11779,
93478 11780,11781,11782,11783,11784,11785,11786,11787,11788,11789,11790,11791,
93479 11792,11793,11794,11795,11796,11797,11798,11799,11800,11801,11802,11803,
93480 11804,11805,11806,11807,11808,11809,11810,11811,11812,11813,11814,11815,
93481 11816,11817,11818,11819,11820,11821,11822,11823,11824,11825,11826,11827,
93482 11828,11829,11830,11831,11832,11833,11834,11835,11836,11837,11838,11839,
93483 11840,11841,11842,11843,11844,11845,11846,11847,11848,11849,11850,11851,
93484 11852,11853,11854,11855,11856,11857,11858,11859,11860,11861,11862,11863,
93485 11864,11865,11866,11867,11868,11869,11870,11871,11872,11873,11874,11875,
93486 11876,11877,11878,11879,11880,11881,11882,11883,11884,11885,11886,11887,
93487 11888,11889,11890,11891,11892,11893,11894,11895,11896,11897,11898,11899,
93488 11900,11901,11902,11903,11904,11905,11906,11907,11908,11909,11910,11911,
93489 11912,11913,11914,11915,11916,11917,11918,11919,11920,11921,11922,11923,
93490 11924,11925,11926,11927,11928,11929,11930,11931,11932,11933,11934,11935,
93491 11936,11937,11938,11939,11940,11941,11942,11943,11944,11945,11946,11947,
93492 11948,11949,11950,11951,11952,11953,11954,11955,11956,11957,11958,11959,
93493 11960,11961,11962,11963,11964,11965,11966,11967,11968,11969,11970,11971,
93494 11972,11973,11974,11975,11976,11977,11978,11979,11980,11981,11982,11983,
93495 11984,11985,11986,11987,11988,11989,11990,11991,11992,11993,11994,11995,
93496 11996,11997,11998,11999,12000,12001,12002,12003,12004,12005,12006,12007,
93497 12008,12009,12010,12011,12012,12013,12014,12015,12016,12017,12018,12019,
93498 12020,12021,12022,12023,12024,12025,12026,12027,12028,12029,12030,12031,
93499 12032,12033,12034,12035,12036,12037,12038,12039,12040,12041,12042,12043,
93500 12044,12045,12046,12047,12048,12049,12050,12051,12052,12053,12054,12055,
93501 12056,12057,12058,12059,12060,12061,12062,12063,12064,12065,12066,12067,
93502 12068,12069,12070,12071,12072,12073,12074,12075,12076,12077,12078,12079,
93503 12080,12081,12082,12083,12084,12085,12086,12087,12088,12089,12090,12091,
93504 12092,12093,12094,12095,12096,12097,12098,12099,12100,12101,12102,12103,
93505 12104,12105,12106,12107,12108,12109,12110,12111,12112,12113,12114,12115,
93506 12116,12117,12118,12119,12120,12121,12122,12123,12124,12125,12126,12127,
93507 12128,12129,12130,12131,12132,12133,12134,12135,12136,12137,12138,12139,
93508 12140,12141,12142,12143,12144,12145,12146,12147,12148,12149,12150,12151,
93509 12152,12153,12154,12155,12156,12157,12158,12159,12160,12161,12162,12163,
93510 12164,12165,12166,12167,12168,12169,12170,12171,12172,12173,12174,12175,
93511 12176,12177,12178,12179,12180,12181,12182,12183,12184,12185,12186,12187,
93512 12188,12189,12190,12191,12192,12193,12194,12195,12196,12197,12198,12199,
93513 12200,12201,12202,12203,12204,12205,12206,12207,12208,12209,12210,12211,
93514 12212,12213,12214,12215,12216,12217,12218,12219,12220,12221,12222,12223,
93515 12224,12225,12226,12227,12228,12229,12230,12231,12232,12233,12234,12235,
93516 12236,12237,12238,12239,12240,12241,12242,12243,12244,12245,12246,12247,
93517 12248,12249,12250,12251,12252,12253,12254,12255,12256,12257,12258,12259,
93518 12260,12261,12262,12263,12264,12265,12266,12267,12268,12269,12270,12271,
93519 12272,12273,12274,12275,12276,12277,12278,12279,12280,12281,12282,12283,
93520 12284,12285,12286,12287,12288,12289,12290,12291,12292,12293,12294,12295,
93521 12296,12297,12298,12299,12300,12301,12302,12303,12304,12305,12306,12307,
93522 12308,12309,12310,12311,12312,12313,12314,12315,12316,12317,12318,12319,
93523 12320,12321,12322,12323,12324,12325,12326,12327,12328,12329,12330,12331,
93524 12332,12333,12334,12335,12336,12337,12338,12339,12340,12341,12342,12343,
93525 12344,12345,12346,12347,12348,12349,12350,12351,12352,12353,12354,12355,
93526 12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,
93527 12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,
93528 12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,
93529 12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,
93530 12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,
93531 12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,
93532 12428,12429,12430,12431,12432,12433,12434,12435,12436,12437,12438,12439,
93533 12440,12441,12442,12443,12444,12445,12446,12447,12448,12449,12450,12451,
93534 12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,
93535 12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,
93536 12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,
93537 12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,
93538 12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,
93539 12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,
93540 12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,12535,
93541 12536,12537,12538,12539,12540,12541,12542,12543,12544,12545,12546,12547,
93542 12548,12549,12550,12551,12552,12553,12554,12555,12556,12557,12558,12559,
93543 12560,12561,12562,12563,12564,12565,12566,12567,12568,12569,12570,12571,
93544 12572,12573,12574,12575,12576,12577,12578,12579,12580,12581,12582,12583,
93545 12584,12585,12586,12587,12588,12589,12590,12591,12592,12593,12594,12595,
93546 12596,12597,12598,12599,12600,12601,12602,12603,12604,12605,12606,12607,
93547 12608,12609,12610,12611,12612,12613,12614,12615,12616,12617,12618,12619,
93548 12620,12621,12622,12623,12624,12625,12626,12627,12628,12629,12630,12631,
93549 12632,12633,12634,12635,12636,12637,12638,12639,12640,12641,12642,12643,
93550 12644,12645,12646,12647,12648,12649,12650,12651,12652,12653,12654,12655,
93551 12656,12657,12658,12659,12660,12661,12662,12663,12664,12665,12666,12667,
93552 12668,12669,12670,12671,12672,12673,12674,12675,12676,12677,12678,12679,
93553 12680,12681,12682,12683,12684,12685,12686,12687,12688,12689,12690,12691,
93554 12692,12693,12694,12695,12696,12697,12698,12699,12700,12701,12702,12703,
93555 12704,12705,12706,12707,12708,12709,12710,12711,12712,12713,12714,12715,
93556 12716,12717,12718,12719,12720,12721,12722,12723,12724,12725,12726,12727,
93557 12728,12729,12730,12731,12732,12733,12734,12735,12736,12737,12738,12739,
93558 12740,12741,12742,12743,12744,12745,12746,12747,12748,12749,12750,12751,
93559 12752,12753,12754,12755,12756,12757,12758,12759,12760,12761,12762,12763,
93560 12764,12765,12766,12767,12768,12769,12770,12771,12772,12773,12774,12775,
93561 12776,12777,12778,12779,12780,12781,12782,12783,12784,12785,12786,12787,
93562 12788,12789,12790,12791,12792,12793,12794,12795,12796,12797,12798,12799,
93563 12800,12801,12802,12803,12804,12805,12806,12807,12808,12809,12810,12811,
93564 12812,12813,12814,12815,12816,12817,12818,12819,12820,12821,12822,12823,
93565 12824,12825,12826,12827,12828,12829,12830,12831,12832,12833,12834,12835,
93566 12836,12837,12838,12839,12840,12841,12842,12843,12844,12845,12846,12847,
93567 12848,12849,12850,12851,12852,12853,12854,12855,12856,12857,12858,12859,
93568 12860,12861,12862,12863,12864,12865,12866,12867,12868,12869,12870,12871,
93569 12872,12873,12874,12875,12876,12877,12878,12879,12880,12881,12882,12883,
93570 12884,12885,12886,12887,12888,12889,12890,12891,12892,12893,12894,12895,
93571 12896,12897,12898,12899,12900,12901,12902,12903,12904,12905,12906,12907,
93572 12908,12909,12910,12911,12912,12913,12914,12915,12916,12917,12918,12919,
93573 12920,12921,12922,12923,12924,12925,12926,12927,12928,12929,12930,12931,
93574 12932,12933,12934,12935,12936,12937,12938,12939,12940,12941,12942,12943,
93575 12944,12945,12946,12947,12948,12949,12950,12951,12952,12953,12954,12955,
93576 12956,12957,12958,12959,12960,12961,12962,12963,12964,12965,12966,12967,
93577 12968,12969,12970,12971,12972,12973,12974,12975,12976,12977,12978,12979,
93578 12980,12981,12982,12983,12984,12985,12986,12987,12988,12989,12990,12991,
93579 12992,12993,12994,12995,12996,12997,12998,12999,13000,13001,13002,13003,
93580 13004,13005,13006,13007,13008,13009,13010,13011,13012,13013,13014,13015,
93581 13016,13017,13018,13019,13020,13021,13022,13023,13024,13025,13026,13027,
93582 13028,13029,13030,13031,13032,13033,13034,13035,13036,13037,13038,13039,
93583 13040,13041,13042,13043,13044,13045,13046,13047,13048,13049,13050,13051,
93584 13052,13053,13054,13055,13056,13057,13058,13059,13060,13061,13062,13063,
93585 13064,13065,13066,13067,13068,13069,13070,13071,13072,13073,13074,13075,
93586 13076,13077,13078,13079,13080,13081,13082,13083,13084,13085,13086,13087,
93587 13088,13089,13090,13091,13092,13093,13094,13095,13096,13097,13098,13099,
93588 13100,13101,13102,13103,13104,13105,13106,13107,13108,13109,13110,13111,
93589 13112,13113,13114,13115,13116,13117,13118,13119,13120,13121,13122,13123,
93590 13124,13125,13126,13127,13128,13129,13130,13131,13132,13133,13134,13135,
93591 13136,13137,13138,13139,13140,13141,13142,13143,13144,13145,13146,13147,
93592 13148,13149,13150,13151,13152,13153,13154,13155,13156,13157,13158,13159,
93593 13160,13161,13162,13163,13164,13165,13166,13167,13168,13169,13170,13171,
93594 13172,13173,13174,13175,13176,13177,13178,13179,13180,13181,13182,13183,
93595 13184,13185,13186,13187,13188,13189,13190,13191,13192,13193,13194,13195,
93596 13196,13197,13198,13199,13200,13201,13202,13203,13204,13205,13206,13207,
93597 13208,13209,13210,13211,13212,13213,13214,13215,13216,13217,13218,13219,
93598 13220,13221,13222,13223,13224,13225,13226,13227,13228,13229,13230,13231,
93599 13232,13233,13234,13235,13236,13237,13238,13239,13240,13241,13242,13243,
93600 13244,13245,13246,13247,13248,13249,13250,13251,13252,13253,13254,13255,
93601 13256,13257,13258,13259,13260,13261,13262,13263,13264,13265,13266,13267,
93602 13268,13269,13270,13271,13272,13273,13274,13275,13276,13277,13278,13279,
93603 13280,13281,13282,13283,13284,13285,13286,13287,13288,13289,13290,13291,
93604 13292,13293,13294,13295,13296,13297,13298,13299,13300,13301,13302,13303,
93605 13304,13305,13306,13307,13308,13309,13310,13311,13312,13313,13314,13315,
93606 13316,13317,13318,13319,13320,13321,13322,13323,13324,13325,13326,13327,
93607 13328,13329,13330,13331,13332,13333,13334,13335,13336,13337,13338,13339,
93608 13340,13341,13342,13343,13344,13345,13346,13347,13348,13349,13350,13351,
93609 13352,13353,13354,13355,13356,13357,13358,13359,13360,13361,13362,13363,
93610 13364,13365,13366,13367,13368,13369,13370,13371,13372,13373,13374,13375,
93611 13376,13377,13378,13379,13380,13381,13382,13383,13384,13385,13386,13387,
93612 13388,13389,13390,13391,13392,13393,13394,13395,13396,13397,13398,13399,
93613 13400,13401,13402,13403,13404,13405,13406,13407,13408,13409,13410,13411,
93614 13412,13413,13414,13415,13416,13417,13418,13419,13420,13421,13422,13423,
93615 13424,13425,13426,13427,13428,13429,13430,13431,13432,13433,13434,13435,
93616 13436,13437,13438,13439,13440,13441,13442,13443,13444,13445,13446,13447,
93617 13448,13449,13450,13451,13452,13453,13454,13455,13456,13457,13458,13459,
93618 13460,13461,13462,13463,13464,13465,13466,13467,13468,13469,13470,13471,
93619 13472,13473,13474,13475,13476,13477,13478,13479,13480,13481,13482,13483,
93620 13484,13485,13486,13487,13488,13489,13490,13491,13492,13493,13494,13495,
93621 13496,13497,13498,13499,13500,13501,13502,13503,13504,13505,13506,13507,
93622 13508,13509,13510,13511,13512,13513,13514,13515,13516,13517,13518,13519,
93623 13520,13521,13522,13523,13524,13525,13526,13527,13528,13529,13530,13531,
93624 13532,13533,13534,13535,13536,13537,13538,13539,13540,13541,13542,13543,
93625 13544,13545,13546,13547,13548,13549,13550,13551,13552,13553,13554,13555,
93626 13556,13557,13558,13559,13560,13561,13562,13563,13564,13565,13566,13567,
93627 13568,13569,13570,13571,13572,13573,13574,13575,13576,13577,13578,13579,
93628 13580,13581,13582,13583,13584,13585,13586,13587,13588,13589,13590,13591,
93629 13592,13593,13594,13595,13596,13597,13598,13599,13600,13601,13602,13603,
93630 13604,13605,13606,13607,13608,13609,13610,13611,13612,13613,13614,13615,
93631 13616,13617,13618,13619,13620,13621,13622,13623,13624,13625,13626,13627,
93632 13628,13629,13630,13631,13632,13633,13634,13635,13636,13637,13638,13639,
93633 13640,13641,13642,13643,13644,13645,13646,13647,13648,13649,13650,13651,
93634 13652,13653,13654,13655,13656,13657,13658,13659,13660,13661,13662,13663,
93635 13664,13665,13666,13667,13668,13669,13670,13671,13672,13673,13674,13675,
93636 13676,13677,13678,13679,13680,13681,13682,13683,13684,13685,13686,13687,
93637 13688,13689,13690,13691,13692,13693,13694,13695,13696,13697,13698,13699,
93638 13700,13701,13702,13703,13704,13705,13706,13707,13708,13709,13710,13711,
93639 13712,13713,13714,13715,13716,13717,13718,13719,13720,13721,13722,13723,
93640 13724,13725,13726,13727,13728,13729,13730,13731,13732,13733,13734,13735,
93641 13736,13737,13738,13739,13740,13741,13742,13743,13744,13745,13746,13747,
93642 13748,13749,13750,13751,13752,13753,13754,13755,13756,13757,13758,13759,
93643 13760,13761,13762,13763,13764,13765,13766,13767,13768,13769,13770,13771,
93644 13772,13773,13774,13775,13776,13777,13778,13779,13780,13781,13782,13783,
93645 13784,13785,13786,13787,13788,13789,13790,13791,13792,13793,13794,13795,
93646 13796,13797,13798,13799,13800,13801,13802,13803,13804,13805,13806,13807,
93647 13808,13809,13810,13811,13812,13813,13814,13815,13816,13817,13818,13819,
93648 13820,13821,13822,13823,13824,13825,13826,13827,13828,13829,13830,13831,
93649 13832,13833,13834,13835,13836,13837,13838,13839,13840,13841,13842,13843,
93650 13844,13845,13846,13847,13848,13849,13850,13851,13852,13853,13854,13855,
93651 13856,13857,13858,13859,13860,13861,13862,13863,13864,13865,13866,13867,
93652 13868,13869,13870,13871,13872,13873,13874,13875,13876,13877,13878,13879,
93653 13880,13881,13882,13883,13884,13885,13886,13887,13888,13889,13890,13891,
93654 13892,13893,13894,13895,13896,13897,13898,13899,13900,13901,13902,13903,
93655 13904,13905,13906,13907,13908,13909,13910,13911,13912,13913,13914,13915,
93656 13916,13917,13918,13919,13920,13921,13922,13923,13924,13925,13926,13927,
93657 13928,13929,13930,13931,13932,13933,13934,13935,13936,13937,13938,13939,
93658 13940,13941,13942,13943,13944,13945,13946,13947,13948,13949,13950,13951,
93659 13952,13953,13954,13955,13956,13957,13958,13959,13960,13961,13962,13963,
93660 13964,13965,13966,13967,13968,13969,13970,13971,13972,13973,13974,13975,
93661 13976,13977,13978,13979,13980,13981,13982,13983,13984,13985,13986,13987,
93662 13988,13989,13990,13991,13992,13993,13994,13995,13996,13997,13998,13999,
93663 14000,14001,14002,14003,14004,14005,14006,14007,14008,14009,14010,14011,
93664 14012,14013,14014,14015,14016,14017,14018,14019,14020,14021,14022,14023,
93665 14024,14025,14026,14027,14028,14029,14030,14031,14032,14033,14034,14035,
93666 14036,14037,14038,14039,14040,14041,14042,14043,14044,14045,14046,14047,
93667 14048,14049,14050,14051,14052,14053,14054,14055,14056,14057,14058,14059,
93668 14060,14061,14062,14063,14064,14065,14066,14067,14068,14069,14070,14071,
93669 14072,14073,14074,14075,14076,14077,14078,14079,14080,14081,14082,14083,
93670 14084,14085,14086,14087,14088,14089,14090,14091,14092,14093,14094,14095,
93671 14096,14097,14098,14099,14100,14101,14102,14103,14104,14105,14106,14107,
93672 14108,14109,14110,14111,14112,14113,14114,14115,14116,14117,14118,14119,
93673 14120,14121,14122,14123,14124,14125,14126,14127,14128,14129,14130,14131,
93674 14132,14133,14134,14135,14136,14137,14138,14139,14140,14141,14142,14143,
93675 14144,14145,14146,14147,14148,14149,14150,14151,14152,14153,14154,14155,
93676 14156,14157,14158,14159,14160,14161,14162,14163,14164,14165,14166,14167,
93677 14168,14169,14170,14171,14172,14173,14174,14175,14176,14177,14178,14179,
93678 14180,14181,14182,14183,14184,14185,14186,14187,14188,14189,14190,14191,
93679 14192,14193,14194,14195,14196,14197,14198,14199,14200,14201,14202,14203,
93680 14204,14205,14206,14207,14208,14209,14210,14211,14212,14213,14214,14215,
93681 14216,14217,14218,14219,14220,14221,14222,14223,14224,14225,14226,14227,
93682 14228,14229,14230,14231,14232,14233,14234,14235,14236,14237,14238,14239,
93683 14240,14241,14242,14243,14244,14245,14246,14247,14248,14249,14250,14251,
93684 14252,14253,14254,14255,14256,14257,14258,14259,14260,14261,14262,14263,
93685 14264,14265,14266,14267,14268,14269,14270,14271,14272,14273,14274,14275,
93686 14276,14277,14278,14279,14280,14281,14282,14283,14284,14285,14286,14287,
93687 14288,14289,14290,14291,14292,14293,14294,14295,14296,14297,14298,14299,
93688 14300,14301,14302,14303,14304,14305,14306,14307,14308,14309,14310,14311,
93689 14312,14313,14314,14315,14316,14317,14318,14319,14320,14321,14322,14323,
93690 14324,14325,14326,14327,14328,14329,14330,14331,14332,14333,14334,14335,
93691 14336,14337,14338,14339,14340,14341,14342,14343,14344,14345,14346,14347,
93692 14348,14349,14350,14351,14352,14353,14354,14355,14356,14357,14358,14359,
93693 14360,14361,14362,14363,14364,14365,14366,14367,14368,14369,14370,14371,
93694 14372,14373,14374,14375,14376,14377,14378,14379,14380,14381,14382,14383,
93695 14384,14385,14386,14387,14388,14389,14390,14391,14392,14393,14394,14395,
93696 14396,14397,14398,14399,14400,14401,14402,14403,14404,14405,14406,14407,
93697 14408,14409,14410,14411,14412,14413,14414,14415,14416,14417,14418,14419,
93698 14420,14421,14422,14423,14424,14425,14426,14427,14428,14429,14430,14431,
93699 14432,14433,14434,14435,14436,14437,14438,14439,14440,14441,14442,14443,
93700 14444,14445,14446,14447,14448,14449,14450,14451,14452,14453,14454,14455,
93701 14456,14457,14458,14459,14460,14461,14462,14463,14464,14465,14466,14467,
93702 14468,14469,14470,14471,14472,14473,14474,14475,14476,14477,14478,14479,
93703 14480,14481,14482,14483,14484,14485,14486,14487,14488,14489,14490,14491,
93704 14492,14493,14494,14495,14496,14497,14498,14499,14500,14501,14502,14503,
93705 14504,14505,14506,14507,14508,14509,14510,14511,14512,14513,14514,14515,
93706 14516,14517,14518,14519,14520,14521,14522,14523,14524,14525,14526,14527,
93707 14528,14529,14530,14531,14532,14533,14534,14535,14536,14537,14538,14539,
93708 14540,14541,14542,14543,14544,14545,14546,14547,14548,14549,14550,14551,
93709 14552,14553,14554,14555,14556,14557,14558,14559,14560,14561,14562,14563,
93710 14564,14565,14566,14567,14568,14569,14570,14571,14572,14573,14574,14575,
93711 14576,14577,14578,14579,14580,14581,14582,14583,14584,14585,14586,14587,
93712 14588,14589,14590,14591,14592,14593,14594,14595,14596,14597,14598,14599,
93713 14600,14601,14602,14603,14604,14605,14606,14607,14608,14609,14610,14611,
93714 14612,14613,14614,14615,14616,14617,14618,14619,14620,14621,14622,14623,
93715 14624,14625,14626,14627,14628,14629,14630,14631,14632,14633,14634,14635,
93716 14636,14637,14638,14639,14640,14641,14642,14643,14644,14645,14646,14647,
93717 14648,14649,14650,14651,14652,14653,14654,14655,14656,14657,14658,14659,
93718 14660,14661,14662,14663,14664,14665,14666,14667,14668,14669,14670,14671,
93719 14672,14673,14674,14675,14676,14677,14678,14679,14680,14681,14682,14683,
93720 14684,14685,14686,14687,14688,14689,14690,14691,14692,14693,14694,14695,
93721 14696,14697,14698,14699,14700,14701,14702,14703,14704,14705,14706,14707,
93722 14708,14709,14710,14711,14712,14713,14714,14715,14716,14717,14718,14719,
93723 14720,14721,14722,14723,14724,14725,14726,14727,14728,14729,14730,14731,
93724 14732,14733,14734,14735,14736,14737,14738,14739,14740,14741,14742,14743,
93725 14744,14745,14746,14747,14748,14749,14750,14751,14752,14753,14754,14755,
93726 14756,14757,14758,14759,14760,14761,14762,14763,14764,14765,14766,14767,
93727 14768,14769,14770,14771,14772,14773,14774,14775,14776,14777,14778,14779,
93728 14780,14781,14782,14783,14784,14785,14786,14787,14788,14789,14790,14791,
93729 14792,14793,14794,14795,14796,14797,14798,14799,14800,14801,14802,14803,
93730 14804,14805,14806,14807,14808,14809,14810,14811,14812,14813,14814,14815,
93731 14816,14817,14818,14819,14820,14821,14822,14823,14824,14825,14826,14827,
93732 14828,14829,14830,14831,14832,14833,14834,14835,14836,14837,14838,14839,
93733 14840,14841,14842,14843,14844,14845,14846,14847,14848,14849,14850,14851,
93734 14852,14853,14854,14855,14856,14857,14858,14859,14860,14861,14862,14863,
93735 14864,14865,14866,14867,14868,14869,14870,14871,14872,14873,14874,14875,
93736 14876,14877,14878,14879,14880,14881,14882,14883,14884,14885,14886,14887,
93737 14888,14889,14890,14891,14892,14893,14894,14895,14896,14897,14898,14899,
93738 14900,14901,14902,14903,14904,14905,14906,14907,14908,14909,14910,14911,
93739 14912,14913,14914,14915,14916,14917,14918,14919,14920,14921,14922,14923,
93740 14924,14925,14926,14927,14928,14929,14930,14931,14932,14933,14934,14935,
93741 14936,14937,14938,14939,14940,14941,14942,14943,14944,14945,14946,14947,
93742 14948,14949,14950,14951,14952,14953,14954,14955,14956,14957,14958,14959,
93743 14960,14961,14962,14963,14964,14965,14966,14967,14968,14969,14970,14971,
93744 14972,14973,14974,14975,14976,14977,14978,14979,14980,14981,14982,14983,
93745 14984,14985,14986,14987,14988,14989,14990,14991,14992,14993,14994,14995,
93746 14996,14997,14998,14999,15000,15001,15002,15003,15004,15005,15006,15007,
93747 15008,15009,15010,15011,15012,15013,15014,15015,15016,15017,15018,15019,
93748 15020,15021,15022,15023,15024,15025,15026,15027,15028,15029,15030,15031,
93749 15032,15033,15034,15035,15036,15037,15038,15039,15040,15041,15042,15043,
93750 15044,15045,15046,15047,15048,15049,15050,15051,15052,15053,15054,15055,
93751 15056,15057,15058,15059,15060,15061,15062,15063,15064,15065,15066,15067,
93752 15068,15069,15070,15071,15072,15073,15074,15075,15076,15077,15078,15079,
93753 15080,15081,15082,15083,15084,15085,15086,15087,15088,15089,15090,15091,
93754 15092,15093,15094,15095,15096,15097,15098,15099,15100,15101,15102,15103,
93755 15104,15105,15106,15107,15108,15109,15110,15111,15112,15113,15114,15115,
93756 15116,15117,15118,15119,15120,15121,15122,15123,15124,15125,15126,15127,
93757 15128,15129,15130,15131,15132,15133,15134,15135,15136,15137,15138,15139,
93758 15140,15141,15142,15143,15144,15145,15146,15147,15148,15149,15150,15151,
93759 15152,15153,15154,15155,15156,15157,15158,15159,15160,15161,15162,15163,
93760 15164,15165,15166,15167,15168,15169,15170,15171,15172,15173,15174,15175,
93761 15176,15177,15178,15179,15180,15181,15182,15183,15184,15185,15186,15187,
93762 15188,15189,15190,15191,15192,15193,15194,15195,15196,15197,15198,15199,
93763 15200,15201,15202,15203,15204,15205,15206,15207,15208,15209,15210,15211,
93764 15212,15213,15214,15215,15216,15217,15218,15219,15220,15221,15222,15223,
93765 15224,15225,15226,15227,15228,15229,15230,15231,15232,15233,15234,15235,
93766 15236,15237,15238,15239,15240,15241,15242,15243,15244,15245,15246,15247,
93767 15248,15249,15250,15251,15252,15253,15254,15255,15256,15257,15258,15259,
93768 15260,15261,15262,15263,15264,15265,15266,15267,15268,15269,15270,15271,
93769 15272,15273,15274,15275,15276,15277,15278,15279,15280,15281,15282,15283,
93770 15284,15285,15286,15287,15288,15289,15290,15291,15292,15293,15294,15295,
93771 15296,15297,15298,15299,15300,15301,15302,15303,15304,15305,15306,15307,
93772 15308,15309,15310,15311,15312,15313,15314,15315,15316,15317,15318,15319,
93773 15320,15321,15322,15323,15324,15325,15326,15327,15328,15329,15330,15331,
93774 15332,15333,15334,15335,15336,15337,15338,15339,15340,15341,15342,15343,
93775 15344,15345,15346,15347,15348,15349,15350,15351,15352,15353,15354,15355,
93776 15356,15357,15358,15359,15360,15361,15362,15363,15364,15365,15366,15367,
93777 15368,15369,15370,15371,15372,15373,15374,15375,15376,15377,15378,15379,
93778 15380,15381,15382,15383,15384,15385,15386,15387,15388,15389,15390,15391,
93779 15392,15393,15394,15395,15396,15397,15398,15399,15400,15401,15402,15403,
93780 15404,15405,15406,15407,15408,15409,15410,15411,15412,15413,15414,15415,
93781 15416,15417,15418,15419,15420,15421,15422,15423,15424,15425,15426,15427,
93782 15428,15429,15430,15431,15432,15433,15434,15435,15436,15437,15438,15439,
93783 15440,15441,15442,15443,15444,15445,15446,15447,15448,15449,15450,15451,
93784 15452,15453,15454,15455,15456,15457,15458,15459,15460,15461,15462,15463,
93785 15464,15465,15466,15467,15468,15469,15470,15471,15472,15473,15474,15475,
93786 15476,15477,15478,15479,15480,15481,15482,15483,15484,15485,15486,15487,
93787 15488,15489,15490,15491,15492,15493,15494,15495,15496,15497,15498,15499,
93788 15500,15501,15502,15503,15504,15505,15506,15507,15508,15509,15510,15511,
93789 15512,15513,15514,15515,15516,15517,15518,15519,15520,15521,15522,15523,
93790 15524,15525,15526,15527,15528,15529,15530,15531,15532,15533,15534,15535,
93791 15536,15537,15538,15539,15540,15541,15542,15543,15544,15545,15546,15547,
93792 15548,15549,15550,15551,15552,15553,15554,15555,15556,15557,15558,15559,
93793 15560,15561,15562,15563,15564,15565,15566,15567,15568,15569,15570,15571,
93794 15572,15573,15574,15575,15576,15577,15578,15579,15580,15581,15582,15583,
93795 15584,15585,15586,15587,15588,15589,15590,15591,15592,15593,15594,15595,
93796 15596,15597,15598,15599,15600,15601,15602,15603,15604,15605,15606,15607,
93797 15608,15609,15610,15611,15612,15613,15614,15615,15616,15617,15618,15619,
93798 15620,15621,15622,15623,15624,15625,15626,15627,15628,15629,15630,15631,
93799 15632,15633,15634,15635,15636,15637,15638,15639,15640,15641,15642,15643,
93800 15644,15645,15646,15647,15648,15649,15650,15651,15652,15653,15654,15655,
93801 15656,15657,15658,15659,15660,15661,15662,15663,15664,15665,15666,15667,
93802 15668,15669,15670,15671,15672,15673,15674,15675,15676,15677,15678,15679,
93803 15680,15681,15682,15683,15684,15685,15686,15687,15688,15689,15690,15691,
93804 15692,15693,15694,15695,15696,15697,15698,15699,15700,15701,15702,15703,
93805 15704,15705,15706,15707,15708,15709,15710,15711,15712,15713,15714,15715,
93806 15716,15717,15718,15719,15720,15721,15722,15723,15724,15725,15726,15727,
93807 15728,15729,15730,15731,15732,15733,15734,15735,15736,15737,15738,15739,
93808 15740,15741,15742,15743,15744,15745,15746,15747,15748,15749,15750,15751,
93809 15752,15753,15754,15755,15756,15757,15758,15759,15760,15761,15762,15763,
93810 15764,15765,15766,15767,15768,15769,15770,15771,15772,15773,15774,15775,
93811 15776,15777,15778,15779,15780,15781,15782,15783,15784,15785,15786,15787,
93812 15788,15789,15790,15791,15792,15793,15794,15795,15796,15797,15798,15799,
93813 15800,15801,15802,15803,15804,15805,15806,15807,15808,15809,15810,15811,
93814 15812,15813,15814,15815,15816,15817,15818,15819,15820,15821,15822,15823,
93815 15824,15825,15826,15827,15828,15829,15830,15831,15832,15833,15834,15835,
93816 15836,15837,15838,15839,15840,15841,15842,15843,15844,15845,15846,15847,
93817 15848,15849,15850,15851,15852,15853,15854,15855,15856,15857,15858,15859,
93818 15860,15861,15862,15863,15864,15865,15866,15867,15868,15869,15870,15871,
93819 15872,15873,15874,15875,15876,15877,15878,15879,15880,15881,15882,15883,
93820 15884,15885,15886,15887,15888,15889,15890,15891,15892,15893,15894,15895,
93821 15896,15897,15898,15899,15900,15901,15902,15903,15904,15905,15906,15907,
93822 15908,15909,15910,15911,15912,15913,15914,15915,15916,15917,15918,15919,
93823 15920,15921,15922,15923,15924,15925,15926,15927,15928,15929,15930,15931,
93824 15932,15933,15934,15935,15936,15937,15938,15939,15940,15941,15942,15943,
93825 15944,15945,15946,15947,15948,15949,15950,15951,15952,15953,15954,15955,
93826 15956,15957,15958,15959,15960,15961,15962,15963,15964,15965,15966,15967,
93827 15968,15969,15970,15971,15972,15973,15974,15975,15976,15977,15978,15979,
93828 15980,15981,15982,15983,15984,15985,15986,15987,15988,15989,15990,15991,
93829 15992,15993,15994,15995,15996,15997,15998,15999,16000,16001,16002,16003,
93830 16004,16005,16006,16007,16008,16009,16010,16011,16012,16013,16014,16015,
93831 16016,16017,16018,16019,16020,16021,16022,16023,16024,16025,16026,16027,
93832 16028,16029,16030,16031,16032,16033,16034,16035,16036,16037,16038,16039,
93833 16040,16041,16042,16043,16044,16045,16046,16047,16048,16049,16050,16051,
93834 16052,16053,16054,16055,16056,16057,16058,16059,16060,16061,16062,16063,
93835 16064,16065,16066,16067,16068,16069,16070,16071,16072,16073,16074,16075,
93836 16076,16077,16078,16079,16080,16081,16082,16083,16084,16085,16086,16087,
93837 16088,16089,16090,16091,16092,16093,16094,16095,16096,16097,16098,16099,
93838 16100,16101,16102,16103,16104,16105,16106,16107,16108,16109,16110,16111,
93839 16112,16113,16114,16115,16116,16117,16118,16119,16120,16121,16122,16123,
93840 16124,16125,16126,16127,16128,16129,16130,16131,16132,16133,16134,16135,
93841 16136,16137,16138,16139,16140,16141,16142,16143,16144,16145,16146,16147,
93842 16148,16149,16150,16151,16152,16153,16154,16155,16156,16157,16158,16159,
93843 16160,16161,16162,16163,16164,16165,16166,16167,16168,16169,16170,16171,
93844 16172,16173,16174,16175,16176,16177,16178,16179,16180,16181,16182,16183,
93845 16184,16185,16186,16187,16188,16189,16190,16191,16192,16193,16194,16195,
93846 16196,16197,16198,16199,16200,16201,16202,16203,16204,16205,16206,16207,
93847 16208,16209,16210,16211,16212,16213,16214,16215,16216,16217,16218,16219,
93848 16220,16221,16222,16223,16224,16225,16226,16227,16228,16229,16230,16231,
93849 16232,16233,16234,16235,16236,16237,16238,16239,16240,16241,16242,16243,
93850 16244,16245,16246,16247,16248,16249,16250,16251,16252,16253,16254,16255,
93851 16256,16257,16258,16259,16260,16261,16262,16263,16264,16265,16266,16267,
93852 16268,16269,16270,16271,16272,16273,16274,16275,16276,16277,16278,16279,
93853 16280,16281,16282,16283,16284,16285,16286,16287,16288,16289,16290,16291,
93854 16292,16293,16294,16295,16296,16297,16298,16299,16300,16301,16302,16303,
93855 16304,16305,16306,16307,16308,16309,16310,16311,16312,16313,16314,16315,
93856 16316,16317,16318,16319,16320,16321,16322,16323,16324,16325,16326,16327,
93857 16328,16329,16330,16331,16332,16333,16334,16335,16336,16337,16338,16339,
93858 16340,16341,16342,16343,16344,16345,16346,16347,16348,16349,16350,16351,
93859 16352,16353,16354,16355,16356,16357,16358,16359,16360,16361,16362,16363,
93860 16364,16365,16366,16367,16368,16369,16370,16371,16372,16373,16374,16375,
93861 16376,16377,16378,16379,16380,16381,16382,16383,16384,16385,16386,16387,
93862 16388,16389,16390,16391,16392,16393,16394,16395,16396,16397,16398,16399,
93863 16400,16401,16402,16403,16404,16405,16406,16407,16408,16409,16410,16411,
93864 16412,16413,16414,16415,16416,16417,16418,16419,16420,16421,16422,16423,
93865 16424,16425,16426,16427,16428,16429,16430,16431,16432,16433,16434,16435,
93866 16436,16437,16438,16439,16440,16441,16442,16443,16444,16445,16446,16447,
93867 16448,16449,16450,16451,16452,16453,16454,16455,16456,16457,16458,16459,
93868 16460,16461,16462,16463,16464,16465,16466,16467,16468,16469,16470,16471,
93869 16472,16473,16474,16475,16476,16477,16478,16479,16480,16481,16482,16483,
93870 16484,16485,16486,16487,16488,16489,16490,16491,16492,16493,16494,16495,
93871 16496,16497,16498,16499,16500,16501,16502,16503,16504,16505,16506,16507,
93872 16508,16509,16510,16511,16512,16513,16514,16515,16516,16517,16518,16519,
93873 16520,16521,16522,16523,16524,16525,16526,16527,16528,16529,16530,16531,
93874 16532,16533,16534,16535,16536,16537,16538,16539,16540,16541,16542,16543,
93875 16544,16545,16546,16547,16548,16549,16550,16551,16552,16553,16554,16555,
93876 16556,16557,16558,16559,16560,16561,16562,16563,16564,16565,16566,16567,
93877 16568,16569,16570,16571,16572,16573,16574,16575,16576,16577,16578,16579,
93878 16580,16581,16582,16583,16584,16585,16586,16587,16588,16589,16590,16591,
93879 16592,16593,16594,16595,16596,16597,16598,16599,16600,16601,16602,16603,
93880 16604,16605,16606,16607,16608,16609,16610,16611,16612,16613,16614,16615,
93881 16616,16617,16618,16619,16620,16621,16622,16623,16624,16625,16626,16627,
93882 16628,16629,16630,16631,16632,16633,16634,16635,16636,16637,16638,16639,
93883 16640,16641,16642,16643,16644,16645,16646,16647,16648,16649,16650,16651,
93884 16652,16653,16654,16655,16656,16657,16658,16659,16660,16661,16662,16663,
93885 16664,16665,16666,16667,16668,16669,16670,16671,16672,16673,16674,16675,
93886 16676,16677,16678,16679,16680,16681,16682,16683,16684,16685,16686,16687,
93887 16688,16689,16690,16691,16692,16693,16694,16695,16696,16697,16698,16699,
93888 16700,16701,16702,16703,16704,16705,16706,16707,16708,16709,16710,16711,
93889 16712,16713,16714,16715,16716,16717,16718,16719,16720,16721,16722,16723,
93890 16724,16725,16726,16727,16728,16729,16730,16731,16732,16733,16734,16735,
93891 16736,16737,16738,16739,16740,16741,16742,16743,16744,16745,16746,16747,
93892 16748,16749,16750,16751,16752,16753,16754,16755,16756,16757,16758,16759,
93893 16760,16761,16762,16763,16764,16765,16766,16767,16768,16769,16770,16771,
93894 16772,16773,16774,16775,16776,16777,16778,16779,16780,16781,16782,16783,
93895 16784,16785,16786,16787,16788,16789,16790,16791,16792,16793,16794,16795,
93896 16796,16797,16798,16799,16800,16801,16802,16803,16804,16805,16806,16807,
93897 16808,16809,16810,16811,16812,16813,16814,16815,16816,16817,16818,16819,
93898 16820,16821,16822,16823,16824,16825,16826,16827,16828,16829,16830,16831,
93899 16832,16833,16834,16835,16836,16837,16838,16839,16840,16841,16842,16843,
93900 16844,16845,16846,16847,16848,16849,16850,16851,16852,16853,16854,16855,
93901 16856,16857,16858,16859,16860,16861,16862,16863,16864,16865,16866,16867,
93902 16868,16869,16870,16871,16872,16873,16874,16875,16876,16877,16878,16879,
93903 16880,16881,16882,16883,16884,16885,16886,16887,16888,16889,16890,16891,
93904 16892,16893,16894,16895,16896,16897,16898,16899,16900,16901,16902,16903,
93905 16904,16905,16906,16907,16908,16909,16910,16911,16912,16913,16914,16915,
93906 16916,16917,16918,16919,16920,16921,16922,16923,16924,16925,16926,16927,
93907 16928,16929,16930,16931,16932,16933,16934,16935,16936,16937,16938,16939,
93908 16940,16941,16942,16943,16944,16945,16946,16947,16948,16949,16950,16951,
93909 16952,16953,16954,16955,16956,16957,16958,16959,16960,16961,16962,16963,
93910 16964,16965,16966,16967,16968,16969,16970,16971,16972,16973,16974,16975,
93911 16976,16977,16978,16979,16980,16981,16982,16983,16984,16985,16986,16987,
93912 16988,16989,16990,16991,16992,16993,16994,16995,16996,16997,16998,16999,
93913 17000,17001,17002,17003,17004,17005,17006,17007,17008,17009,17010,17011,
93914 17012,17013,17014,17015,17016,17017,17018,17019,17020,17021,17022,17023,
93915 17024,17025,17026,17027,17028,17029,17030,17031,17032,17033,17034,17035,
93916 17036,17037,17038,17039,17040,17041,17042,17043,17044,17045,17046,17047,
93917 17048,17049,17050,17051,17052,17053,17054,17055,17056,17057,17058,17059,
93918 17060,17061,17062,17063,17064,17065,17066,17067,17068,17069,17070,17071,
93919 17072,17073,17074,17075,17076,17077,17078,17079,17080,17081,17082,17083,
93920 17084,17085,17086,17087,17088,17089,17090,17091,17092,17093,17094,17095,
93921 17096,17097,17098,17099,17100,17101,17102,17103,17104,17105,17106,17107,
93922 17108,17109,17110,17111,17112,17113,17114,17115,17116,17117,17118,17119,
93923 17120,17121,17122,17123,17124,17125,17126,17127,17128,17129,17130,17131,
93924 17132,17133,17134,17135,17136,17137,17138,17139,17140,17141,17142,17143,
93925 17144,17145,17146,17147,17148,17149,17150,17151,17152,17153,17154,17155,
93926 17156,17157,17158,17159,17160,17161,17162,17163,17164,17165,17166,17167,
93927 17168,17169,17170,17171,17172,17173,17174,17175,17176,17177,17178,17179,
93928 17180,17181,17182,17183,17184,17185,17186,17187,17188,17189,17190,17191,
93929 17192,17193,17194,17195,17196,17197,17198,17199,17200,17201,17202,17203,
93930 17204,17205,17206,17207,17208,17209,17210,17211,17212,17213,17214,17215,
93931 17216,17217,17218,17219,17220,17221,17222,17223,17224,17225,17226,17227,
93932 17228,17229,17230,17231,17232,17233,17234,17235,17236,17237,17238,17239,
93933 17240,17241,17242,17243,17244,17245,17246,17247,17248,17249,17250,17251,
93934 17252,17253,17254,17255,17256,17257,17258,17259,17260,17261,17262,17263,
93935 17264,17265,17266,17267,17268,17269,17270,17271,17272,17273,17274,17275,
93936 17276,17277,17278,17279,17280,17281,17282,17283,17284,17285,17286,17287,
93937 17288,17289,17290,17291,17292,17293,17294,17295,17296,17297,17298,17299,
93938 17300,17301,17302,17303,17304,17305,17306,17307,17308,17309,17310,17311,
93939 17312,17313,17314,17315,17316,17317,17318,17319,17320,17321,17322,17323,
93940 17324,17325,17326,17327,17328,17329,17330,17331,17332,17333,17334,17335,
93941 17336,17337,17338,17339,17340,17341,17342,17343,17344,17345,17346,17347,
93942 17348,17349,17350,17351,17352,17353,17354,17355,17356,17357,17358,17359,
93943 17360,17361,17362,17363,17364,17365,17366,17367,17368,17369,17370,17371,
93944 17372,17373,17374,17375,17376,17377,17378,17379,17380,17381,17382,17383,
93945 17384,17385,17386,17387,17388,17389,17390,17391,17392,17393,17394,17395,
93946 17396,17397,17398,17399,17400,17401,17402,17403,17404,17405,17406,17407,
93947 17408,17409,17410,17411,17412,17413,17414,17415,17416,17417,17418,17419,
93948 17420,17421,17422,17423,17424,17425,17426,17427,17428,17429,17430,17431,
93949 17432,17433,17434,17435,17436,17437,17438,17439,17440,17441,17442,17443,
93950 17444,17445,17446,17447,17448,17449,17450,17451,17452,17453,17454,17455,
93951 17456,17457,17458,17459,17460,17461,17462,17463,17464,17465,17466,17467,
93952 17468,17469,17470,17471,17472,17473,17474,17475,17476,17477,17478,17479,
93953 17480,17481,17482,17483,17484,17485,17486,17487,17488,17489,17490,17491,
93954 17492,17493,17494,17495,17496,17497,17498,17499,17500,17501,17502,17503,
93955 17504,17505,17506,17507,17508,17509,17510,17511,17512,17513,17514,17515,
93956 17516,17517,17518,17519,17520,17521,17522,17523,17524,17525,17526,17527,
93957 17528,17529,17530,17531,17532,17533,17534,17535,17536,17537,17538,17539,
93958 17540,17541,17542,17543,17544,17545,17546,17547,17548,17549,17550,17551,
93959 17552,17553,17554,17555,17556,17557,17558,17559,17560,17561,17562,17563,
93960 17564,17565,17566,17567,17568,17569,17570,17571,17572,17573,17574,17575,
93961 17576,17577,17578,17579,17580,17581,17582,17583,17584,17585,17586,17587,
93962 17588,17589,17590,17591,17592,17593,17594,17595,17596,17597,17598,17599,
93963 17600,17601,17602,17603,17604,17605,17606,17607,17608,17609,17610,17611,
93964 17612,17613,17614,17615,17616,17617,17618,17619,17620,17621,17622,17623,
93965 17624,17625,17626,17627,17628,17629,17630,17631,17632,17633,17634,17635,
93966 17636,17637,17638,17639,17640,17641,17642,17643,17644,17645,17646,17647,
93967 17648,17649,17650,17651,17652,17653,17654,17655,17656,17657,17658,17659,
93968 17660,17661,17662,17663,17664,17665,17666,17667,17668,17669,17670,17671,
93969 17672,17673,17674,17675,17676,17677,17678,17679,17680,17681,17682,17683,
93970 17684,17685,17686,17687,17688,17689,17690,17691,17692,17693,17694,17695,
93971 17696,17697,17698,17699,17700,17701,17702,17703,17704,17705,17706,17707,
93972 17708,17709,17710,17711,17712,17713,17714,17715,17716,17717,17718,17719,
93973 17720,17721,17722,17723,17724,17725,17726,17727,17728,17729,17730,17731,
93974 17732,17733,17734,17735,17736,17737,17738,17739,17740,17741,17742,17743,
93975 17744,17745,17746,17747,17748,17749,17750,17751,17752,17753,17754,17755,
93976 17756,17757,17758,17759,17760,17761,17762,17763,17764,17765,17766,17767,
93977 17768,17769,17770,17771,17772,17773,17774,17775,17776,17777,17778,17779,
93978 17780,17781,17782,17783,17784,17785,17786,17787,17788,17789,17790,17791,
93979 17792,17793,17794,17795,17796,17797,17798,17799,17800,17801,17802,17803,
93980 17804,17805,17806,17807,17808,17809,17810,17811,17812,17813,17814,17815,
93981 17816,17817,17818,17819,17820,17821,17822,17823,17824,17825,17826,17827,
93982 17828,17829,17830,17831,17832,17833,17834,17835,17836,17837,17838,17839,
93983 17840,17841,17842,17843,17844,17845,17846,17847,17848,17849,17850,17851,
93984 17852,17853,17854,17855,17856,17857,17858,17859,17860,17861,17862,17863,
93985 17864,17865,17866,17867,17868,17869,17870,17871,17872,17873,17874,17875,
93986 17876,17877,17878,17879,17880,17881,17882,17883,17884,17885,17886,17887,
93987 17888,17889,17890,17891,17892,17893,17894,17895,17896,17897,17898,17899,
93988 17900,17901,17902,17903,17904,17905,17906,17907,17908,17909,17910,17911,
93989 17912,17913,17914,17915,17916,17917,17918,17919,17920,17921,17922,17923,
93990 17924,17925,17926,17927,17928,17929,17930,17931,17932,17933,17934,17935,
93991 17936,17937,17938,17939,17940,17941,17942,17943,17944,17945,17946,17947,
93992 17948,17949,17950,17951,17952,17953,17954,17955,17956,17957,17958,17959,
93993 17960,17961,17962,17963,17964,17965,17966,17967,17968,17969,17970,17971,
93994 17972,17973,17974,17975,17976,17977,17978,17979,17980,17981,17982,17983,
93995 17984,17985,17986,17987,17988,17989,17990,17991,17992,17993,17994,17995,
93996 17996,17997,17998,17999,18000,18001,18002,18003,18004,18005,18006,18007,
93997 18008,18009,18010,18011,18012,18013,18014,18015,18016,18017,18018,18019,
93998 18020,18021,18022,18023,18024,18025,18026,18027,18028,18029,18030,18031,
93999 18032,18033,18034,18035,18036,18037,18038,18039,18040,18041,18042,18043,
94000 18044,18045,18046,18047,18048,18049,18050,18051,18052,18053,18054,18055,
94001 18056,18057,18058,18059,18060,18061,18062,18063,18064,18065,18066,18067,
94002 18068,18069,18070,18071,18072,18073,18074,18075,18076,18077,18078,18079,
94003 18080,18081,18082,18083,18084,18085,18086,18087,18088,18089,18090,18091,
94004 18092,18093,18094,18095,18096,18097,18098,18099,18100,18101,18102,18103,
94005 18104,18105,18106,18107,18108,18109,18110,18111,18112,18113,18114,18115,
94006 18116,18117,18118,18119,18120,18121,18122,18123,18124,18125,18126,18127,
94007 18128,18129,18130,18131,18132,18133,18134,18135,18136,18137,18138,18139,
94008 18140,18141,18142,18143,18144,18145,18146,18147,18148,18149,18150,18151,
94009 18152,18153,18154,18155,18156,18157,18158,18159,18160,18161,18162,18163,
94010 18164,18165,18166,18167,18168,18169,18170,18171,18172,18173,18174,18175,
94011 18176,18177,18178,18179,18180,18181,18182,18183,18184,18185,18186,18187,
94012 18188,18189,18190,18191,18192,18193,18194,18195,18196,18197,18198,18199,
94013 18200,18201,18202,18203,18204,18205,18206,18207,18208,18209,18210,18211,
94014 18212,18213,18214,18215,18216,18217,18218,18219,18220,18221,18222,18223,
94015 18224,18225,18226,18227,18228,18229,18230,18231,18232,18233,18234,18235,
94016 18236,18237,18238,18239,18240,18241,18242,18243,18244,18245,18246,18247,
94017 18248,18249,18250,18251,18252,18253,18254,18255,18256,18257,18258,18259,
94018 18260,18261,18262,18263,18264,18265,18266,18267,18268,18269,18270,18271,
94019 18272,18273,18274,18275,18276,18277,18278,18279,18280,18281,18282,18283,
94020 18284,18285,18286,18287,18288,18289,18290,18291,18292,18293,18294,18295,
94021 18296,18297,18298,18299,18300,18301,18302,18303,18304,18305,18306,18307,
94022 18308,18309,18310,18311,18312,18313,18314,18315,18316,18317,18318,18319,
94023 18320,18321,18322,18323,18324,18325,18326,18327,18328,18329,18330,18331,
94024 18332,18333,18334,18335,18336,18337,18338,18339,18340,18341,18342,18343,
94025 18344,18345,18346,18347,18348,18349,18350,18351,18352,18353,18354,18355,
94026 18356,18357,18358,18359,18360,18361,18362,18363,18364,18365,18366,18367,
94027 18368,18369,18370,18371,18372,18373,18374,18375,18376,18377,18378,18379,
94028 18380,18381,18382,18383,18384,18385,18386,18387,18388,18389,18390,18391,
94029 18392,18393,18394,18395,18396,18397,18398,18399,18400,18401,18402,18403,
94030 18404,18405,18406,18407,18408,18409,18410,18411,18412,18413,18414,18415,
94031 18416,18417,18418,18419,18420,18421,18422,18423,18424,18425,18426,18427,
94032 18428,18429,18430,18431,18432,18433,18434,18435,18436,18437,18438,18439,
94033 18440,18441,18442,18443,18444,18445,18446,18447,18448,18449,18450,18451,
94034 18452,18453,18454,18455,18456,18457,18458,18459,18460,18461,18462,18463,
94035 18464,18465,18466,18467,18468,18469,18470,18471,18472,18473,18474,18475,
94036 18476,18477,18478,18479,18480,18481,18482,18483,18484,18485,18486,18487,
94037 18488,18489,18490,18491,18492,18493,18494,18495,18496,18497,18498,18499,
94038 18500,18501,18502,18503,18504,18505,18506,18507,18508,18509,18510,18511,
94039 18512,18513,18514,18515,18516,18517,18518,18519,18520,18521,18522,18523,
94040 18524,18525,18526,18527,18528,18529,18530,18531,18532,18533,18534,18535,
94041 18536,18537,18538,18539,18540,18541,18542,18543,18544,18545,18546,18547,
94042 18548,18549,18550,18551,18552,18553,18554,18555,18556,18557,18558,18559,
94043 18560,18561,18562,18563,18564,18565,18566,18567,18568,18569,18570,18571,
94044 18572,18573,18574,18575,18576,18577,18578,18579,18580,18581,18582,18583,
94045 18584,18585,18586,18587,18588,18589,18590,18591,18592,18593,18594,18595,
94046 18596,18597,18598,18599,18600,18601,18602,18603,18604,18605,18606,18607,
94047 18608,18609,18610,18611,18612,18613,18614,18615,18616,18617,18618,18619,
94048 18620,18621,18622,18623,18624,18625,18626,18627,18628,18629,18630,18631,
94049 18632,18633,18634,18635,18636,18637,18638,18639,18640,18641,18642,18643,
94050 18644,18645,18646,18647,18648,18649,18650,18651,18652,18653,18654,18655,
94051 18656,18657,18658,18659,18660,18661,18662,18663,18664,18665,18666,18667,
94052 18668,18669,18670,18671,18672,18673,18674,18675,18676,18677,18678,18679,
94053 18680,18681,18682,18683,18684,18685,18686,18687,18688,18689,18690,18691,
94054 18692,18693,18694,18695,18696,18697,18698,18699,18700,18701,18702,18703,
94055 18704,18705,18706,18707,18708,18709,18710,18711,18712,18713,18714,18715,
94056 18716,18717,18718,18719,18720,18721,18722,18723,18724,18725,18726,18727,
94057 18728,18729,18730,18731,18732,18733,18734,18735,18736,18737,18738,18739,
94058 18740,18741,18742,18743,18744,18745,18746,18747,18748,18749,18750,18751,
94059 18752,18753,18754,18755,18756,18757,18758,18759,18760,18761,18762,18763,
94060 18764,18765,18766,18767,18768,18769,18770,18771,18772,18773,18774,18775,
94061 18776,18777,18778,18779,18780,18781,18782,18783,18784,18785,18786,18787,
94062 18788,18789,18790,18791,18792,18793,18794,18795,18796,18797,18798,18799,
94063 18800,18801,18802,18803,18804,18805,18806,18807,18808,18809,18810,18811,
94064 18812,18813,18814,18815,18816,18817,18818,18819,18820,18821,18822,18823,
94065 18824,18825,18826,18827,18828,18829,18830,18831,18832,18833,18834,18835,
94066 18836,18837,18838,18839,18840,18841,18842,18843,18844,18845,18846,18847,
94067 18848,18849,18850,18851,18852,18853,18854,18855,18856,18857,18858,18859,
94068 18860,18861,18862,18863,18864,18865,18866,18867,18868,18869,18870,18871,
94069 18872,18873,18874,18875,18876,18877,18878,18879,18880,18881,18882,18883,
94070 18884,18885,18886,18887,18888,18889,18890,18891,18892,18893,18894,18895,
94071 18896,18897,18898,18899,18900,18901,18902,18903,18904,18905,18906,18907,
94072 18908,18909,18910,18911,18912,18913,18914,18915,18916,18917,18918,18919,
94073 18920,18921,18922,18923,18924,18925,18926,18927,18928,18929,18930,18931,
94074 18932,18933,18934,18935,18936,18937,18938,18939,18940,18941,18942,18943,
94075 18944,18945,18946,18947,18948,18949,18950,18951,18952,18953,18954,18955,
94076 18956,18957,18958,18959,18960,18961,18962,18963,18964,18965,18966,18967,
94077 18968,18969,18970,18971,18972,18973,18974,18975,18976,18977,18978,18979,
94078 18980,18981,18982,18983,18984,18985,18986,18987,18988,18989,18990,18991,
94079 18992,18993,18994,18995,18996,18997,18998,18999,19000,19001,19002,19003,
94080 19004,19005,19006,19007,19008,19009,19010,19011,19012,19013,19014,19015,
94081 19016,19017,19018,19019,19020,19021,19022,19023,19024,19025,19026,19027,
94082 19028,19029,19030,19031,19032,19033,19034,19035,19036,19037,19038,19039,
94083 19040,19041,19042,19043,19044,19045,19046,19047,19048,19049,19050,19051,
94084 19052,19053,19054,19055,19056,19057,19058,19059,19060,19061,19062,19063,
94085 19064,19065,19066,19067,19068,19069,19070,19071,19072,19073,19074,19075,
94086 19076,19077,19078,19079,19080,19081,19082,19083,19084,19085,19086,19087,
94087 19088,19089,19090,19091,19092,19093,19094,19095,19096,19097,19098,19099,
94088 19100,19101,19102,19103,19104,19105,19106,19107,19108,19109,19110,19111,
94089 19112,19113,19114,19115,19116,19117,19118,19119,19120,19121,19122,19123,
94090 19124,19125,19126,19127,19128,19129,19130,19131,19132,19133,19134,19135,
94091 19136,19137,19138,19139,19140,19141,19142,19143,19144,19145,19146,19147,
94092 19148,19149,19150,19151,19152,19153,19154,19155,19156,19157,19158,19159,
94093 19160,19161,19162,19163,19164,19165,19166,19167,19168,19169,19170,19171,
94094 19172,19173,19174,19175,19176,19177,19178,19179,19180,19181,19182,19183,
94095 19184,19185,19186,19187,19188,19189,19190,19191,19192,19193,19194,19195,
94096 19196,19197,19198,19199,19200,19201,19202,19203,19204,19205,19206,19207,
94097 19208,19209,19210,19211,19212,19213,19214,19215,19216,19217,19218,19219,
94098 19220,19221,19222,19223,19224,19225,19226,19227,19228,19229,19230,19231,
94099 19232,19233,19234,19235,19236,19237,19238,19239,19240,19241,19242,19243,
94100 19244,19245,19246,19247,19248,19249,19250,19251,19252,19253,19254,19255,
94101 19256,19257,19258,19259,19260,19261,19262,19263,19264,19265,19266,19267,
94102 19268,19269,19270,19271,19272,19273,19274,19275,19276,19277,19278,19279,
94103 19280,19281,19282,19283,19284,19285,19286,19287,19288,19289,19290,19291,
94104 19292,19293,19294,19295,19296,19297,19298,19299,19300,19301,19302,19303,
94105 19304,19305,19306,19307,19308,19309,19310,19311,19312,19313,19314,19315,
94106 19316,19317,19318,19319,19320,19321,19322,19323,19324,19325,19326,19327,
94107 19328,19329,19330,19331,19332,19333,19334,19335,19336,19337,19338,19339,
94108 19340,19341,19342,19343,19344,19345,19346,19347,19348,19349,19350,19351,
94109 19352,19353,19354,19355,19356,19357,19358,19359,19360,19361,19362,19363,
94110 19364,19365,19366,19367,19368,19369,19370,19371,19372,19373,19374,19375,
94111 19376,19377,19378,19379,19380,19381,19382,19383,19384,19385,19386,19387,
94112 19388,19389,19390,19391,19392,19393,19394,19395,19396,19397,19398,19399,
94113 19400,19401,19402,19403,19404,19405,19406,19407,19408,19409,19410,19411,
94114 19412,19413,19414,19415,19416,19417,19418,19419,19420,19421,19422,19423,
94115 19424,19425,19426,19427,19428,19429,19430,19431,19432,19433,19434,19435,
94116 19436,19437,19438,19439,19440,19441,19442,19443,19444,19445,19446,19447,
94117 19448,19449,19450,19451,19452,19453,19454,19455,19456,19457,19458,19459,
94118 19460,19461,19462,19463,19464,19465,19466,19467,19468,19469,19470,19471,
94119 19472,19473,19474,19475,19476,19477,19478,19479,19480,19481,19482,19483,
94120 19484,19485,19486,19487,19488,19489,19490,19491,19492,19493,19494,19495,
94121 19496,19497,19498,19499,19500,19501,19502,19503,19504,19505,19506,19507,
94122 19508,19509,19510,19511,19512,19513,19514,19515,19516,19517,19518,19519,
94123 19520,19521,19522,19523,19524,19525,19526,19527,19528,19529,19530,19531,
94124 19532,19533,19534,19535,19536,19537,19538,19539,19540,19541,19542,19543,
94125 19544,19545,19546,19547,19548,19549,19550,19551,19552,19553,19554,19555,
94126 19556,19557,19558,19559,19560,19561,19562,19563,19564,19565,19566,19567,
94127 19568,19569,19570,19571,19572,19573,19574,19575,19576,19577,19578,19579,
94128 19580,19581,19582,19583,19584,19585,19586,19587,19588,19589,19590,19591,
94129 19592,19593,19594,19595,19596,19597,19598,19599,19600,19601,19602,19603,
94130 19604,19605,19606,19607,19608,19609,19610,19611,19612,19613,19614,19615,
94131 19616,19617,19618,19619,19620,19621,19622,19623,19624,19625,19626,19627,
94132 19628,19629,19630,19631,19632,19633,19634,19635,19636,19637,19638,19639,
94133 19640,19641,19642,19643,19644,19645,19646,19647,19648,19649,19650,19651,
94134 19652,19653,19654,19655,19656,19657,19658,19659,19660,19661,19662,19663,
94135 19664,19665,19666,19667,19668,19669,19670,19671,19672,19673,19674,19675,
94136 19676,19677,19678,19679,19680,19681,19682,19683,19684,19685,19686,19687,
94137 19688,19689,19690,19691,19692,19693,19694,19695,19696,19697,19698,19699,
94138 19700,19701,19702,19703,19704,19705,19706,19707,19708,19709,19710,19711,
94139 19712,19713,19714,19715,19716,19717,19718,19719,19720,19721,19722,19723,
94140 19724,19725,19726,19727,19728,19729,19730,19731,19732,19733,19734,19735,
94141 19736,19737,19738,19739,19740,19741,19742,19743,19744,19745,19746,19747,
94142 19748,19749,19750,19751,19752,19753,19754,19755,19756,19757,19758,19759,
94143 19760,19761,19762,19763,19764,19765,19766,19767,19768,19769,19770,19771,
94144 19772,19773,19774,19775,19776,19777,19778,19779,19780,19781,19782,19783,
94145 19784,19785,19786,19787,19788,19789,19790,19791,19792,19793,19794,19795,
94146 19796,19797,19798,19799,19800,19801,19802,19803,19804,19805,19806,19807,
94147 19808,19809,19810,19811,19812,19813,19814,19815,19816,19817,19818,19819,
94148 19820,19821,19822,19823,19824,19825,19826,19827,19828,19829,19830,19831,
94149 19832,19833,19834,19835,19836,19837,19838,19839,19840,19841,19842,19843,
94150 19844,19845,19846,19847,19848,19849,19850,19851,19852,19853,19854,19855,
94151 19856,19857,19858,19859,19860,19861,19862,19863,19864,19865,19866,19867,
94152 19868,19869,19870,19871,19872,19873,19874,19875,19876,19877,19878,19879,
94153 19880,19881,19882,19883,19884,19885,19886,19887,19888,19889,19890,19891,
94154 19892,19893,19894,19895,19896,19897,19898,19899,19900,19901,19902,19903,
94155 19904,19905,19906,19907,19908,19909,19910,19911,19912,19913,19914,19915,
94156 19916,19917,19918,19919,19920,19921,19922,19923,19924,19925,19926,19927,
94157 19928,19929,19930,19931,19932,19933,19934,19935,19936,19937,19938,19939,
94158 19940,19941,19942,19943,19944,19945,19946,19947,19948,19949,19950,19951,
94159 19952,19953,19954,19955,19956,19957,19958,19959,19960,19961,19962,19963,
94160 19964,19965,19966,19967,19968,19969,19970,19971,19972,19973,19974,19975,
94161 19976,19977,19978,19979,19980,19981,19982,19983,19984,19985,19986,19987,
94162 19988,19989,19990,19991,19992,19993,19994,19995,19996,19997,19998,19999,
94163 20000,20001,20002,20003,20004,20005,20006,20007,20008,20009,20010,20011,
94164 20012,20013,20014,20015,20016,20017,20018,20019,20020,20021,20022,20023,
94165 20024,20025,20026,20027,20028,20029,20030,20031,20032,20033,20034,20035,
94166 20036,20037,20038,20039,20040,20041,20042,20043,20044,20045,20046,20047,
94167 20048,20049,20050,20051,20052,20053,20054,20055,20056,20057,20058,20059,
94168 20060,20061,20062,20063,20064,20065,20066,20067,20068,20069,20070,20071,
94169 20072,20073,20074,20075,20076,20077,20078,20079,20080,20081,20082,20083,
94170 20084,20085,20086,20087,20088,20089,20090,20091,20092,20093,20094,20095,
94171 20096,20097,20098,20099,20100,20101,20102,20103,20104,20105,20106,20107,
94172 20108,20109,20110,20111,20112,20113,20114,20115,20116,20117,20118,20119,
94173 20120,20121,20122,20123,20124,20125,20126,20127,20128,20129,20130,20131,
94174 20132,20133,20134,20135,20136,20137,20138,20139,20140,20141,20142,20143,
94175 20144,20145,20146,20147,20148,20149,20150,20151,20152,20153,20154,20155,
94176 20156,20157,20158,20159,20160,20161,20162,20163,20164,20165,20166,20167,
94177 20168,20169,20170,20171,20172,20173,20174,20175,20176,20177,20178,20179,
94178 20180,20181,20182,20183,20184,20185,20186,20187,20188,20189,20190,20191,
94179 20192,20193,20194,20195,20196,20197,20198,20199,20200,20201,20202,20203,
94180 20204,20205,20206,20207,20208,20209,20210,20211,20212,20213,20214,20215,
94181 20216,20217,20218,20219,20220,20221,20222,20223,20224,20225,20226,20227,
94182 20228,20229,20230,20231,20232,20233,20234,20235,20236,20237,20238,20239,
94183 20240,20241,20242,20243,20244,20245,20246,20247,20248,20249,20250,20251,
94184 20252,20253,20254,20255,20256,20257,20258,20259,20260,20261,20262,20263,
94185 20264,20265,20266,20267,20268,20269,20270,20271,20272,20273,20274,20275,
94186 20276,20277,20278,20279,20280,20281,20282,20283,20284,20285,20286,20287,
94187 20288,20289,20290,20291,20292,20293,20294,20295,20296,20297,20298,20299,
94188 20300,20301,20302,20303,20304,20305,20306,20307,20308,20309,20310,20311,
94189 20312,20313,20314,20315,20316,20317,20318,20319,20320,20321,20322,20323,
94190 20324,20325,20326,20327,20328,20329,20330,20331,20332,20333,20334,20335,
94191 20336,20337,20338,20339,20340,20341,20342,20343,20344,20345,20346,20347,
94192 20348,20349,20350,20351,20352,20353,20354,20355,20356,20357,20358,20359,
94193 20360,20361,20362,20363,20364,20365,20366,20367,20368,20369,20370,20371,
94194 20372,20373,20374,20375,20376,20377,20378,20379,20380,20381,20382,20383,
94195 20384,20385,20386,20387,20388,20389,20390,20391,20392,20393,20394,20395,
94196 20396,20397,20398,20399,20400,20401,20402,20403,20404,20405,20406,20407,
94197 20408,20409,20410,20411,20412,20413,20414,20415,20416,20417,20418,20419,
94198 20420,20421,20422,20423,20424,20425,20426,20427,20428,20429,20430,20431,
94199 20432,20433,20434,20435,20436,20437,20438,20439,20440,20441,20442,20443,
94200 20444,20445,20446,20447,20448,20449,20450,20451,20452,20453,20454,20455,
94201 20456,20457,20458,20459,20460,20461,20462,20463,20464,20465,20466,20467,
94202 20468,20469,20470,20471,20472,20473,20474,20475,20476,20477,20478,20479,
94203 20480,20481,20482,20483,20484,20485,20486,20487,20488,20489,20490,20491,
94204 20492,20493,20494,20495,20496,20497,20498,20499,20500,20501,20502,20503,
94205 20504,20505,20506,20507,20508,20509,20510,20511,20512,20513,20514,20515,
94206 20516,20517,20518,20519,20520,20521,20522,20523,20524,20525,20526,20527,
94207 20528,20529,20530,20531,20532,20533,20534,20535,20536,20537,20538,20539,
94208 20540,20541,20542,20543,20544,20545,20546,20547,20548,20549,20550,20551,
94209 20552,20553,20554,20555,20556,20557,20558,20559,20560,20561,20562,20563,
94210 20564,20565,20566,20567,20568,20569,20570,20571,20572,20573,20574,20575,
94211 20576,20577,20578,20579,20580,20581,20582,20583,20584,20585,20586,20587,
94212 20588,20589,20590,20591,20592,20593,20594,20595,20596,20597,20598,20599,
94213 20600,20601,20602,20603,20604,20605,20606,20607,20608,20609,20610,20611,
94214 20612,20613,20614,20615,20616,20617,20618,20619,20620,20621,20622,20623,
94215 20624,20625,20626,20627,20628,20629,20630,20631,20632,20633,20634,20635,
94216 20636,20637,20638,20639,20640,20641,20642,20643,20644,20645,20646,20647,
94217 20648,20649,20650,20651,20652,20653,20654,20655,20656,20657,20658,20659,
94218 20660,20661,20662,20663,20664,20665,20666,20667,20668,20669,20670,20671,
94219 20672,20673,20674,20675,20676,20677,20678,20679,20680,20681,20682,20683,
94220 20684,20685,20686,20687,20688,20689,20690,20691,20692,20693,20694,20695,
94221 20696,20697,20698,20699,20700,20701,20702,20703,20704,20705,20706,20707,
94222 20708,20709,20710,20711,20712,20713,20714,20715,20716,20717,20718,20719,
94223 20720,20721,20722,20723,20724,20725,20726,20727,20728,20729,20730,20731,
94224 20732,20733,20734,20735,20736,20737,20738,20739,20740,20741,20742,20743,
94225 20744,20745,20746,20747,20748,20749,20750,20751,20752,20753,20754,20755,
94226 20756,20757,20758,20759,20760,20761,20762,20763,20764,20765,20766,20767,
94227 20768,20769,20770,20771,20772,20773,20774,20775,20776,20777,20778,20779,
94228 20780,20781,20782,20783,20784,20785,20786,20787,20788,20789,20790,20791,
94229 20792,20793,20794,20795,20796,20797,20798,20799,20800,20801,20802,20803,
94230 20804,20805,20806,20807,20808,20809,20810,20811,20812,20813,20814,20815,
94231 20816,20817,20818,20819,20820,20821,20822,20823,20824,20825,20826,20827,
94232 20828,20829,20830,20831,20832,20833,20834,20835,20836,20837,20838,20839,
94233 20840,20841,20842,20843,20844,20845,20846,20847,20848,20849,20850,20851,
94234 20852,20853,20854,20855,20856,20857,20858,20859,20860,20861,20862,20863,
94235 20864,20865,20866,20867,20868,20869,20870,20871,20872,20873,20874,20875,
94236 20876,20877,20878,20879,20880,20881,20882,20883,20884,20885,20886,20887,
94237 20888,20889,20890,20891,20892,20893,20894,20895,20896,20897,20898,20899,
94238 20900,20901,20902,20903,20904,20905,20906,20907,20908,20909,20910,20911,
94239 20912,20913,20914,20915,20916,20917,20918,20919,20920,20921,20922,20923,
94240 20924,20925,20926,20927,20928,20929,20930,20931,20932,20933,20934,20935,
94241 20936,20937,20938,20939,20940,20941,20942,20943,20944,20945,20946,20947,
94242 20948,20949,20950,20951,20952,20953,20954,20955,20956,20957,20958,20959,
94243 20960,20961,20962,20963,20964,20965,20966,20967,20968,20969,20970,20971,
94244 20972,20973,20974,20975,20976,20977,20978,20979,20980,20981,20982,20983,
94245 20984,20985,20986,20987,20988,20989,20990,20991,20992,20993,20994,20995,
94246 20996,20997,20998,20999,21000,21001,21002,21003,21004,21005,21006,21007,
94247 21008,21009,21010,21011,21012,21013,21014,21015,21016,21017,21018,21019,
94248 21020,21021,21022,21023,21024,21025,21026,21027,21028,21029,21030,21031,
94249 21032,21033,21034,21035,21036,21037,21038,21039,21040,21041,21042,21043,
94250 21044,21045,21046,21047,21048,21049,21050,21051,21052,21053,21054,21055,
94251 21056,21057,21058,21059,21060,21061,21062,21063,21064,21065,21066,21067,
94252 21068,21069,21070,21071,21072,21073,21074,21075,21076,21077,21078,21079,
94253 21080,21081,21082,21083,21084,21085,21086,21087,21088,21089,21090,21091,
94254 21092,21093,21094,21095,21096,21097,21098,21099,21100,21101,21102,21103,
94255 21104,21105,21106,21107,21108,21109,21110,21111,21112,21113,21114,21115,
94256 21116,21117,21118,21119,21120,21121,21122,21123,21124,21125,21126,21127,
94257 21128,21129,21130,21131,21132,21133,21134,21135,21136,21137,21138,21139,
94258 21140,21141,21142,21143,21144,21145,21146,21147,21148,21149,21150,21151,
94259 21152,21153,21154,21155,21156,21157,21158,21159,21160,21161,21162,21163,
94260 21164,21165,21166,21167,21168,21169,21170,21171,21172,21173,21174,21175,
94261 21176,21177,21178,21179,21180,21181,21182,21183,21184,21185,21186,21187,
94262 21188,21189,21190,21191,21192,21193,21194,21195,21196,21197,21198,21199,
94263 21200,21201,21202,21203,21204,21205,21206,21207,21208,21209,21210,21211,
94264 21212,21213,21214,21215,21216,21217,21218,21219,21220,21221,21222,21223,
94265 21224,21225,21226,21227,21228,21229,21230,21231,21232,21233,21234,21235,
94266 21236,21237,21238,21239,21240,21241,21242,21243,21244,21245,21246,21247,
94267 21248,21249,21250,21251,21252,21253,21254,21255,21256,21257,21258,21259,
94268 21260,21261,21262,21263,21264,21265,21266,21267,21268,21269,21270,21271,
94269 21272,21273,21274,21275,21276,21277,21278,21279,21280,21281,21282,21283,
94270 21284,21285,21286,21287,21288,21289,21290,21291,21292,21293,21294,21295,
94271 21296,21297,21298,21299,21300,21301,21302,21303,21304,21305,21306,21307,
94272 21308,21309,21310,21311,21312,21313,21314,21315,21316,21317,21318,21319,
94273 21320,21321,21322,21323,21324,21325,21326,21327,21328,21329,21330,21331,
94274 21332,21333,21334,21335,21336,21337,21338,21339,21340,21341,21342,21343,
94275 21344,21345,21346,21347,21348,21349,21350,21351,21352,21353,21354,21355,
94276 21356,21357,21358,21359,21360,21361,21362,21363,21364,21365,21366,21367,
94277 21368,21369,21370,21371,21372,21373,21374,21375,21376,21377,21378,21379,
94278 21380,21381,21382,21383,21384,21385,21386,21387,21388,21389,21390,21391,
94279 21392,21393,21394,21395,21396,21397,21398,21399,21400,21401,21402,21403,
94280 21404,21405,21406,21407,21408,21409,21410,21411,21412,21413,21414,21415,
94281 21416,21417,21418,21419,21420,21421,21422,21423,21424,21425,21426,21427,
94282 21428,21429,21430,21431,21432,21433,21434,21435,21436,21437,21438,21439,
94283 21440,21441,21442,21443,21444,21445,21446,21447,21448,21449,21450,21451,
94284 21452,21453,21454,21455,21456,21457,21458,21459,21460,21461,21462,21463,
94285 21464,21465,21466,21467,21468,21469,21470,21471,21472,21473,21474,21475,
94286 21476,21477,21478,21479,21480,21481,21482,21483,21484,21485,21486,21487,
94287 21488,21489,21490,21491,21492,21493,21494,21495,21496,21497,21498,21499,
94288 21500,21501,21502,21503,21504,21505,21506,21507,21508,21509,21510,21511,
94289 21512,21513,21514,21515,21516,21517,21518,21519,21520,21521,21522,21523,
94290 21524,21525,21526,21527,21528,21529,21530,21531,21532,21533,21534,21535,
94291 21536,21537,21538,21539,21540,21541,21542,21543,21544,21545,21546,21547,
94292 21548,21549,21550,21551,21552,21553,21554,21555,21556,21557,21558,21559,
94293 21560,21561,21562,21563,21564,21565,21566,21567,21568,21569,21570,21571,
94294 21572,21573,21574,21575,21576,21577,21578,21579,21580,21581,21582,21583,
94295 21584,21585,21586,21587,21588,21589,21590,21591,21592,21593,21594,21595,
94296 21596,21597,21598,21599,21600,21601,21602,21603,21604,21605,21606,21607,
94297 21608,21609,21610,21611,21612,21613,21614,21615,21616,21617,21618,21619,
94298 21620,21621,21622,21623,21624,21625,21626,21627,21628,21629,21630,21631,
94299 21632,21633,21634,21635,21636,21637,21638,21639,21640,21641,21642,21643,
94300 21644,21645,21646,21647,21648,21649,21650,21651,21652,21653,21654,21655,
94301 21656,21657,21658,21659,21660,21661,21662,21663,21664,21665,21666,21667,
94302 21668,21669,21670,21671,21672,21673,21674,21675,21676,21677,21678,21679,
94303 21680,21681,21682,21683,21684,21685,21686,21687,21688,21689,21690,21691,
94304 21692,21693,21694,21695,21696,21697,21698,21699,21700,21701,21702,21703,
94305 21704,21705,21706,21707,21708,21709,21710,21711,21712,21713,21714,21715,
94306 21716,21717,21718,21719,21720,21721,21722,21723,21724,21725,21726,21727,
94307 21728,21729,21730,21731,21732,21733,21734,21735,21736,21737,21738,21739,
94308 21740,21741,21742,21743,21744,21745,21746,21747,21748,21749,21750,21751,
94309 21752,21753,21754,21755,21756,21757,21758,21759,21760,21761,21762,21763,
94310 21764,21765,21766,21767,21768,21769,21770,21771,21772,21773,21774,21775,
94311 21776,21777,21778,21779,21780,21781,21782,21783,21784,21785,21786,21787,
94312 21788,21789,21790,21791,21792,21793,21794,21795,21796,21797,21798,21799,
94313 21800,21801,21802,21803,21804,21805,21806,21807,21808,21809,21810,21811,
94314 21812,21813,21814,21815,21816,21817,21818,21819,21820,21821,21822,21823,
94315 21824,21825,21826,21827,21828,21829,21830,21831,21832,21833,21834,21835,
94316 21836,21837,21838,21839,21840,21841,21842,21843,21844,21845,21846,21847,
94317 21848,21849,21850,21851,21852,21853,21854,21855,21856,21857,21858,21859,
94318 21860,21861,21862,21863,21864,21865,21866,21867,21868,21869,21870,21871,
94319 21872,21873,21874,21875,21876,21877,21878,21879,21880,21881,21882,21883,
94320 21884,21885,21886,21887,21888,21889,21890,21891,21892,21893,21894,21895,
94321 21896,21897,21898,21899,21900,21901,21902,21903,21904,21905,21906,21907,
94322 21908,21909,21910,21911,21912,21913,21914,21915,21916,21917,21918,21919,
94323 21920,21921,21922,21923,21924,21925,21926,21927,21928,21929,21930,21931,
94324 21932,21933,21934,21935,21936,21937,21938,21939,21940,21941,21942,21943,
94325 21944,21945,21946,21947,21948,21949,21950,21951,21952,21953,21954,21955,
94326 21956,21957,21958,21959,21960,21961,21962,21963,21964,21965,21966,21967,
94327 21968,21969,21970,21971,21972,21973,21974,21975,21976,21977,21978,21979,
94328 21980,21981,21982,21983,21984,21985,21986,21987,21988,21989,21990,21991,
94329 21992,21993,21994,21995,21996,21997,21998,21999,22000,22001,22002,22003,
94330 22004,22005,22006,22007,22008,22009,22010,22011,22012,22013,22014,22015,
94331 22016,22017,22018,22019,22020,22021,22022,22023,22024,22025,22026,22027,
94332 22028,22029,22030,22031,22032,22033,22034,22035,22036,22037,22038,22039,
94333 22040,22041,22042,22043,22044,22045,22046,22047,22048,22049,22050,22051,
94334 22052,22053,22054,22055,22056,22057,22058,22059,22060,22061,22062,22063,
94335 22064,22065,22066,22067,22068,22069,22070,22071,22072,22073,22074,22075,
94336 22076,22077,22078,22079,22080,22081,22082,22083,22084,22085,22086,22087,
94337 22088,22089,22090,22091,22092,22093,22094,22095,22096,22097,22098,22099,
94338 22100,22101,22102,22103,22104,22105,22106,22107,22108,22109,22110,22111,
94339 22112,22113,22114,22115,22116,22117,22118,22119,22120,22121,22122,22123,
94340 22124,22125,22126,22127,22128,22129,22130,22131,22132,22133,22134,22135,
94341 22136,22137,22138,22139,22140,22141,22142,22143,22144,22145,22146,22147,
94342 22148,22149,22150,22151,22152,22153,22154,22155,22156,22157,22158,22159,
94343 22160,22161,22162,22163,22164,22165,22166,22167,22168,22169,22170,22171,
94344 22172,22173,22174,22175,22176,22177,22178,22179,22180,22181,22182,22183,
94345 22184,22185,22186,22187,22188,22189,22190,22191,22192,22193,22194,22195,
94346 22196,22197,22198,22199,22200,22201,22202,22203,22204,22205,22206,22207,
94347 22208,22209,22210,22211,22212,22213,22214,22215,22216,22217,22218,22219,
94348 22220,22221,22222,22223,22224,22225,22226,22227,22228,22229,22230,22231,
94349 22232,22233,22234,22235,22236,22237,22238,22239,22240,22241,22242,22243,
94350 22244,22245,22246,22247,22248,22249,22250,22251,22252,22253,22254,22255,
94351 22256,22257,22258,22259,22260,22261,22262,22263,22264,22265,22266,22267,
94352 22268,22269,22270,22271,22272,22273,22274,22275,22276,22277,22278,22279,
94353 22280,22281,22282,22283,22284,22285,22286,22287,22288,22289,22290,22291,
94354 22292,22293,22294,22295,22296,22297,22298,22299,22300,22301,22302,22303,
94355 22304,22305,22306,22307,22308,22309,22310,22311,22312,22313,22314,22315,
94356 22316,22317,22318,22319,22320,22321,22322,22323,22324,22325,22326,22327,
94357 22328,22329,22330,22331,22332,22333,22334,22335,22336,22337,22338,22339,
94358 22340,22341,22342,22343,22344,22345,22346,22347,22348,22349,22350,22351,
94359 22352,22353,22354,22355,22356,22357,22358,22359,22360,22361,22362,22363,
94360 22364,22365,22366,22367,22368,22369,22370,22371,22372,22373,22374,22375,
94361 22376,22377,22378,22379,22380,22381,22382,22383,22384,22385,22386,22387,
94362 22388,22389,22390,22391,22392,22393,22394,22395,22396,22397,22398,22399,
94363 22400,22401,22402,22403,22404,22405,22406,22407,22408,22409,22410,22411,
94364 22412,22413,22414,22415,22416,22417,22418,22419,22420,22421,22422,22423,
94365 22424,22425,22426,22427,22428,22429,22430,22431,22432,22433,22434,22435,
94366 22436,22437,22438,22439,22440,22441,22442,22443,22444,22445,22446,22447,
94367 22448,22449,22450,22451,22452,22453,22454,22455,22456,22457,22458,22459,
94368 22460,22461,22462,22463,22464,22465,22466,22467,22468,22469,22470,22471,
94369 22472,22473,22474,22475,22476,22477,22478,22479,22480,22481,22482,22483,
94370 22484,22485,22486,22487,22488,22489,22490,22491,22492,22493,22494,22495,
94371 22496,22497,22498,22499,22500,22501,22502,22503,22504,22505,22506,22507,
94372 22508,22509,22510,22511,22512,22513,22514,22515,22516,22517,22518,22519,
94373 22520,22521,22522,22523,22524,22525,22526,22527,22528,22529,22530,22531,
94374 22532,22533,22534,22535,22536,22537,22538,22539,22540,22541,22542,22543,
94375 22544,22545,22546,22547,22548,22549,22550,22551,22552,22553,22554,22555,
94376 22556,22557,22558,22559,22560,22561,22562,22563,22564,22565,22566,22567,
94377 22568,22569,22570,22571,22572,22573,22574,22575,22576,22577,22578,22579,
94378 22580,22581,22582,22583,22584,22585,22586,22587,22588,22589,22590,22591,
94379 22592,22593,22594,22595,22596,22597,22598,22599,22600,22601,22602,22603,
94380 22604,22605,22606,22607,22608,22609,22610,22611,22612,22613,22614,22615,
94381 22616,22617,22618,22619,22620,22621,22622,22623,22624,22625,22626,22627,
94382 22628,22629,22630,22631,22632,22633,22634,22635,22636,22637,22638,22639,
94383 22640,22641,22642,22643,22644,22645,22646,22647,22648,22649,22650,22651,
94384 22652,22653,22654,22655,22656,22657,22658,22659,22660,22661,22662,22663,
94385 22664,22665,22666,22667,22668,22669,22670,22671,22672,22673,22674,22675,
94386 22676,22677,22678,22679,22680,22681,22682,22683,22684,22685,22686,22687,
94387 22688,22689,22690,22691,22692,22693,22694,22695,22696,22697,22698,22699,
94388 22700,22701,22702,22703,22704,22705,22706,22707,22708,22709,22710,22711,
94389 22712,22713,22714,22715,22716,22717,22718,22719,22720,22721,22722,22723,
94390 22724,22725,22726,22727,22728,22729,22730,22731,22732,22733,22734,22735,
94391 22736,22737,22738,22739,22740,22741,22742,22743,22744,22745,22746,22747,
94392 22748,22749,22750,22751,22752,22753,22754,22755,22756,22757,22758,22759,
94393 22760,22761,22762,22763,22764,22765,22766,22767,22768,22769,22770,22771,
94394 22772,22773,22774,22775,22776,22777,22778,22779,22780,22781,22782,22783,
94395 22784,22785,22786,22787,22788,22789,22790,22791,22792,22793,22794,22795,
94396 22796,22797,22798,22799,22800,22801,22802,22803,22804,22805,22806,22807,
94397 22808,22809,22810,22811,22812,22813,22814,22815,22816,22817,22818,22819,
94398 22820,22821,22822,22823,22824,22825,22826,22827,22828,22829,22830,22831,
94399 22832,22833,22834,22835,22836,22837,22838,22839,22840,22841,22842,22843,
94400 22844,22845,22846,22847,22848,22849,22850,22851,22852,22853,22854,22855,
94401 22856,22857,22858,22859,22860,22861,22862,22863,22864,22865,22866,22867,
94402 22868,22869,22870,22871,22872,22873,22874,22875,22876,22877,22878,22879,
94403 22880,22881,22882,22883,22884,22885,22886,22887,22888,22889,22890,22891,
94404 22892,22893,22894,22895,22896,22897,22898,22899,22900,22901,22902,22903,
94405 22904,22905,22906,22907,22908,22909,22910,22911,22912,22913,22914,22915,
94406 22916,22917,22918,22919,22920,22921,22922,22923,22924,22925,22926,22927,
94407 22928,22929,22930,22931,22932,22933,22934,22935,22936,22937,22938,22939,
94408 22940,22941,22942,22943,22944,22945,22946,22947,22948,22949,22950,22951,
94409 22952,22953,22954,22955,22956,22957,22958,22959,22960,22961,22962,22963,
94410 22964,22965,22966,22967,22968,22969,22970,22971,22972,22973,22974,22975,
94411 22976,22977,22978,22979,22980,22981,22982,22983,22984,22985,22986,22987,
94412 22988,22989,22990,22991,22992,22993,22994,22995,22996,22997,22998,22999,
94413 23000,23001,23002,23003,23004,23005,23006,23007,23008,23009,23010,23011,
94414 23012,23013,23014,23015,23016,23017,23018,23019,23020,23021,23022,23023,
94415 23024,23025,23026,23027,23028,23029,23030,23031,23032,23033,23034,23035,
94416 23036,23037,23038,23039,23040,23041,23042,23043,23044,23045,23046,23047,
94417 23048,23049,23050,23051,23052,23053,23054,23055,23056,23057,23058,23059,
94418 23060,23061,23062,23063,23064,23065,23066,23067,23068,23069,23070,23071,
94419 23072,23073,23074,23075,23076,23077,23078,23079,23080,23081,23082,23083,
94420 23084,23085,23086,23087,23088,23089,23090,23091,23092,23093,23094,23095,
94421 23096,23097,23098,23099,23100,23101,23102,23103,23104,23105,23106,23107,
94422 23108,23109,23110,23111,23112,23113,23114,23115,23116,23117,23118,23119,
94423 23120,23121,23122,23123,23124,23125,23126,23127,23128,23129,23130,23131,
94424 23132,23133,23134,23135,23136,23137,23138,23139,23140,23141,23142,23143,
94425 23144,23145,23146,23147,23148,23149,23150,23151,23152,23153,23154,23155,
94426 23156,23157,23158,23159,23160,23161,23162,23163,23164,23165,23166,23167,
94427 23168,23169,23170,23171,23172,23173,23174,23175,23176,23177,23178,23179,
94428 23180,23181,23182,23183,23184,23185,23186,23187,23188,23189,23190,23191,
94429 23192,23193,23194,23195,23196,23197,23198,23199,23200,23201,23202,23203,
94430 23204,23205,23206,23207,23208,23209,23210,23211,23212,23213,23214,23215,
94431 23216,23217,23218,23219,23220,23221,23222,23223,23224,23225,23226,23227,
94432 23228,23229,23230,23231,23232,23233,23234,23235,23236,23237,23238,23239,
94433 23240,23241,23242,23243,23244,23245,23246,23247,23248,23249,23250,23251,
94434 23252,23253,23254,23255,23256,23257,23258,23259,23260,23261,23262,23263,
94435 23264,23265,23266,23267,23268,23269,23270,23271,23272,23273,23274,23275,
94436 23276,23277,23278,23279,23280,23281,23282,23283,23284,23285,23286,23287,
94437 23288,23289,23290,23291,23292,23293,23294,23295,23296,23297,23298,23299,
94438 23300,23301,23302,23303,23304,23305,23306,23307,23308,23309,23310,23311,
94439 23312,23313,23314,23315,23316,23317,23318,23319,23320,23321,23322,23323,
94440 23324,23325,23326,23327,23328,23329,23330,23331,23332,23333,23334,23335,
94441 23336,23337,23338,23339,23340,23341,23342,23343,23344,23345,23346,23347,
94442 23348,23349,23350,23351,23352,23353,23354,23355,23356,23357,23358,23359,
94443 23360,23361,23362,23363,23364,23365,23366,23367,23368,23369,23370,23371,
94444 23372,23373,23374,23375,23376,23377,23378,23379,23380,23381,23382,23383,
94445 23384,23385,23386,23387,23388,23389,23390,23391,23392,23393,23394,23395,
94446 23396,23397,23398,23399,23400,23401,23402,23403,23404,23405,23406,23407,
94447 23408,23409,23410,23411,23412,23413,23414,23415,23416,23417,23418,23419,
94448 23420,23421,23422,23423,23424,23425,23426,23427,23428,23429,23430,23431,
94449 23432,23433,23434,23435,23436,23437,23438,23439,23440,23441,23442,23443,
94450 23444,23445,23446,23447,23448,23449,23450,23451,23452,23453,23454,23455,
94451 23456,23457,23458,23459,23460,23461,23462,23463,23464,23465,23466,23467,
94452 23468,23469,23470,23471,23472,23473,23474,23475,23476,23477,23478,23479,
94453 23480,23481,23482,23483,23484,23485,23486,23487,23488,23489,23490,23491,
94454 23492,23493,23494,23495,23496,23497,23498,23499,23500,23501,23502,23503,
94455 23504,23505,23506,23507,23508,23509,23510,23511,23512,23513,23514,23515,
94456 23516,23517,23518,23519,23520,23521,23522,23523,23524,23525,23526,23527,
94457 23528,23529,23530,23531,23532,23533,23534,23535,23536,23537,23538,23539,
94458 23540,23541,23542,23543,23544,23545,23546,23547,23548,23549,23550,23551,
94459 23552,23553,23554,23555,23556,23557,23558,23559,23560,23561,23562,23563,
94460 23564,23565,23566,23567,23568,23569,23570,23571,23572,23573,23574,23575,
94461 23576,23577,23578,23579,23580,23581,23582,23583,23584,23585,23586,23587,
94462 23588,23589,23590,23591,23592,23593,23594,23595,23596,23597,23598,23599,
94463 23600,23601,23602,23603,23604,23605,23606,23607,23608,23609,23610,23611,
94464 23612,23613,23614,23615,23616,23617,23618,23619,23620,23621,23622,23623,
94465 23624,23625,23626,23627,23628,23629,23630,23631,23632,23633,23634,23635,
94466 23636,23637,23638,23639,23640,23641,23642,23643,23644,23645,23646,23647,
94467 23648,23649,23650,23651,23652,23653,23654,23655,23656,23657,23658,23659,
94468 23660,23661,23662,23663,23664,23665,23666,23667,23668,23669,23670,23671,
94469 23672,23673,23674,23675,23676,23677,23678,23679,23680,23681,23682,23683,
94470 23684,23685,23686,23687,23688,23689,23690,23691,23692,23693,23694,23695,
94471 23696,23697,23698,23699,23700,23701,23702,23703,23704,23705,23706,23707,
94472 23708,23709,23710,23711,23712,23713,23714,23715,23716,23717,23718,23719,
94473 23720,23721,23722,23723,23724,23725,23726,23727,23728,23729,23730,23731,
94474 23732,23733,23734,23735,23736,23737,23738,23739,23740,23741,23742,23743,
94475 23744,23745,23746,23747,23748,23749,23750,23751,23752,23753,23754,23755,
94476 23756,23757,23758,23759,23760,23761,23762,23763,23764,23765,23766,23767,
94477 23768,23769,23770,23771,23772,23773,23774,23775,23776,23777,23778,23779,
94478 23780,23781,23782,23783,23784,23785,23786,23787,23788,23789,23790,23791,
94479 23792,23793,23794,23795,23796,23797,23798,23799,23800,23801,23802,23803,
94480 23804,23805,23806,23807,23808,23809,23810,23811,23812,23813,23814,23815,
94481 23816,23817,23818,23819,23820,23821,23822,23823,23824,23825,23826,23827,
94482 23828,23829,23830,23831,23832,23833,23834,23835,23836,23837,23838,23839,
94483 23840,23841,23842,23843,23844,23845,23846,23847,23848,23849,23850,23851,
94484 23852,23853,23854,23855,23856,23857,23858,23859,23860,23861,23862,23863,
94485 23864,23865,23866,23867,23868,23869,23870,23871,23872,23873,23874,23875,
94486 23876,23877,23878,23879,23880,23881,23882,23883,23884,23885,23886,23887,
94487 23888,23889,23890,23891,23892,23893,23894,23895,23896,23897,23898,23899,
94488 23900,23901,23902,23903,23904,23905,23906,23907,23908,23909,23910,23911,
94489 23912,23913,23914,23915,23916,23917,23918,23919,23920,23921,23922,23923,
94490 23924,23925,23926,23927,23928,23929,23930,23931,23932,23933,23934,23935,
94491 23936,23937,23938,23939,23940,23941,23942,23943,23944,23945,23946,23947,
94492 23948,23949,23950,23951,23952,23953,23954,23955,23956,23957,23958,23959,
94493 23960,23961,23962,23963,23964,23965,23966,23967,23968,23969,23970,23971,
94494 23972,23973,23974,23975,23976,23977,23978,23979,23980,23981,23982,23983,
94495 23984,23985,23986,23987,23988,23989,23990,23991,23992,23993,23994,23995,
94496 23996,23997,23998,23999,24000,24001,24002,24003,24004,24005,24006,24007,
94497 24008,24009,24010,24011,24012,24013,24014,24015,24016,24017,24018,24019,
94498 24020,24021,24022,24023,24024,24025,24026,24027,24028,24029,24030,24031,
94499 24032,24033,24034,24035,24036,24037,24038,24039,24040,24041,24042,24043,
94500 24044,24045,24046,24047,24048,24049,24050,24051,24052,24053,24054,24055,
94501 24056,24057,24058,24059,24060,24061,24062,24063,24064,24065,24066,24067,
94502 24068,24069,24070,24071,24072,24073,24074,24075,24076,24077,24078,24079,
94503 24080,24081,24082,24083,24084,24085,24086,24087,24088,24089,24090,24091,
94504 24092,24093,24094,24095,24096,24097,24098,24099,24100,24101,24102,24103,
94505 24104,24105,24106,24107,24108,24109,24110,24111,24112,24113,24114,24115,
94506 24116,24117,24118,24119,24120,24121,24122,24123,24124,24125,24126,24127,
94507 24128,24129,24130,24131,24132,24133,24134,24135,24136,24137,24138,24139,
94508 24140,24141,24142,24143,24144,24145,24146,24147,24148,24149,24150,24151,
94509 24152,24153,24154,24155,24156,24157,24158,24159,24160,24161,24162,24163,
94510 24164,24165,24166,24167,24168,24169,24170,24171,24172,24173,24174,24175,
94511 24176,24177,24178,24179,24180,24181,24182,24183,24184,24185,24186,24187,
94512 24188,24189,24190,24191,24192,24193,24194,24195,24196,24197,24198,24199,
94513 24200,24201,24202,24203,24204,24205,24206,24207,24208,24209,24210,24211,
94514 24212,24213,24214,24215,24216,24217,24218,24219,24220,24221,24222,24223,
94515 24224,24225,24226,24227,24228,24229,24230,24231,24232,24233,24234,24235,
94516 24236,24237,24238,24239,24240,24241,24242,24243,24244,24245,24246,24247,
94517 24248,24249,24250,24251,24252,24253,24254,24255,24256,24257,24258,24259,
94518 24260,24261,24262,24263,24264,24265,24266,24267,24268,24269,24270,24271,
94519 24272,24273,24274,24275,24276,24277,24278,24279,24280,24281,24282,24283,
94520 24284,24285,24286,24287,24288,24289,24290,24291,24292,24293,24294,24295,
94521 24296,24297,24298,24299,24300,24301,24302,24303,24304,24305,24306,24307,
94522 24308,24309,24310,24311,24312,24313,24314,24315,24316,24317,24318,24319,
94523 24320,24321,24322,24323,24324,24325,24326,24327,24328,24329,24330,24331,
94524 24332,24333,24334,24335,24336,24337,24338,24339,24340,24341,24342,24343,
94525 24344,24345,24346,24347,24348,24349,24350,24351,24352,24353,24354,24355,
94526 24356,24357,24358,24359,24360,24361,24362,24363,24364,24365,24366,24367,
94527 24368,24369,24370,24371,24372,24373,24374,24375,24376,24377,24378,24379,
94528 24380,24381,24382,24383,24384,24385,24386,24387,24388,24389,24390,24391,
94529 24392,24393,24394,24395,24396,24397,24398,24399,24400,24401,24402,24403,
94530 24404,24405,24406,24407,24408,24409,24410,24411,24412,24413,24414,24415,
94531 24416,24417,24418,24419,24420,24421,24422,24423,24424,24425,24426,24427,
94532 24428,24429,24430,24431,24432,24433,24434,24435,24436,24437,24438,24439,
94533 24440,24441,24442,24443,24444,24445,24446,24447,24448,24449,24450,24451,
94534 24452,24453,24454,24455,24456,24457,24458,24459,24460,24461,24462,24463,
94535 24464,24465,24466,24467,24468,24469,24470,24471,24472,24473,24474,24475,
94536 24476,24477,24478,24479,24480,24481,24482,24483,24484,24485,24486,24487,
94537 24488,24489,24490,24491,24492,24493,24494,24495,24496,24497,24498,24499,
94538 24500,24501,24502,24503,24504,24505,24506,24507,24508,24509,24510,24511,
94539 24512,24513,24514,24515,24516,24517,24518,24519,24520,24521,24522,24523,
94540 24524,24525,24526,24527,24528,24529,24530,24531,24532,24533,24534,24535,
94541 24536,24537,24538,24539,24540,24541,24542,24543,24544,24545,24546,24547,
94542 24548,24549,24550,24551,24552,24553,24554,24555,24556,24557,24558,24559,
94543 24560,24561,24562,24563,24564,24565,24566,24567,24568,24569,24570,24571,
94544 24572,24573,24574,24575,24576,24577,24578,24579,24580,24581,24582,24583,
94545 24584,24585,24586,24587,24588,24589,24590,24591,24592,24593,24594,24595,
94546 24596,24597,24598,24599,24600,24601,24602,24603,24604,24605,24606,24607,
94547 24608,24609,24610,24611,24612,24613,24614,24615,24616,24617,24618,24619,
94548 24620,24621,24622,24623,24624,24625,24626,24627,24628,24629,24630,24631,
94549 24632,24633,24634,24635,24636,24637,24638,24639,24640,24641,24642,24643,
94550 24644,24645,24646,24647,24648,24649,24650,24651,24652,24653,24654,24655,
94551 24656,24657,24658,24659,24660,24661,24662,24663,24664,24665,24666,24667,
94552 24668,24669,24670,24671,24672,24673,24674,24675,24676,24677,24678,24679,
94553 24680,24681,24682,24683,24684,24685,24686,24687,24688,24689,24690,24691,
94554 24692,24693,24694,24695,24696,24697,24698,24699,24700,24701,24702,24703,
94555 24704,24705,24706,24707,24708,24709,24710,24711,24712,24713,24714,24715,
94556 24716,24717,24718,24719,24720,24721,24722,24723,24724,24725,24726,24727,
94557 24728,24729,24730,24731,24732,24733,24734,24735,24736,24737,24738,24739,
94558 24740,24741,24742,24743,24744,24745,24746,24747,24748,24749,24750,24751,
94559 24752,24753,24754,24755,24756,24757,24758,24759,24760,24761,24762,24763,
94560 24764,24765,24766,24767,24768,24769,24770,24771,24772,24773,24774,24775,
94561 24776,24777,24778,24779,24780,24781,24782,24783,24784,24785,24786,24787,
94562 24788,24789,24790,24791,24792,24793,24794,24795,24796,24797,24798,24799,
94563 24800,24801,24802,24803,24804,24805,24806,24807,24808,24809,24810,24811,
94564 24812,24813,24814,24815,24816,24817,24818,24819,24820,24821,24822,24823,
94565 24824,24825,24826,24827,24828,24829,24830,24831,24832,24833,24834,24835,
94566 24836,24837,24838,24839,24840,24841,24842,24843,24844,24845,24846,24847,
94567 24848,24849,24850,24851,24852,24853,24854,24855,24856,24857,24858,24859,
94568 24860,24861,24862,24863,24864,24865,24866,24867,24868,24869,24870,24871,
94569 24872,24873,24874,24875,24876,24877,24878,24879,24880,24881,24882,24883,
94570 24884,24885,24886,24887,24888,24889,24890,24891,24892,24893,24894,24895,
94571 24896,24897,24898,24899,24900,24901,24902,24903,24904,24905,24906,24907,
94572 24908,24909,24910,24911,24912,24913,24914,24915,24916,24917,24918,24919,
94573 24920,24921,24922,24923,24924,24925,24926,24927,24928,24929,24930,24931,
94574 24932,24933,24934,24935,24936,24937,24938,24939,24940,24941,24942,24943,
94575 24944,24945,24946,24947,24948,24949,24950,24951,24952,24953,24954,24955,
94576 24956,24957,24958,24959,24960,24961,24962,24963,24964,24965,24966,24967,
94577 24968,24969,24970,24971,24972,24973,24974,24975,24976,24977,24978,24979,
94578 24980,24981,24982,24983,24984,24985,24986,24987,24988,24989,24990,24991,
94579 24992,24993,24994,24995,24996,24997,24998,24999,25000,25001,25002,25003,
94580 25004,25005,25006,25007,25008,25009,25010,25011,25012,25013,25014,25015,
94581 25016,25017,25018,25019,25020,25021,25022,25023,25024,25025,25026,25027,
94582 25028,25029,25030,25031,25032,25033,25034,25035,25036,25037,25038,25039,
94583 25040,25041,25042,25043,25044,25045,25046,25047,25048,25049,25050,25051,
94584 25052,25053,25054,25055,25056,25057,25058,25059,25060,25061,25062,25063,
94585 25064,25065,25066,25067,25068,25069,25070,25071,25072,25073,25074,25075,
94586 25076,25077,25078,25079,25080,25081,25082,25083,25084,25085,25086,25087,
94587 25088,25089,25090,25091,25092,25093,25094,25095,25096,25097,25098,25099,
94588 25100,25101,25102,25103,25104,25105,25106,25107,25108,25109,25110,25111,
94589 25112,25113,25114,25115,25116,25117,25118,25119,25120,25121,25122,25123,
94590 25124,25125,25126,25127,25128,25129,25130,25131,25132,25133,25134,25135,
94591 25136,25137,25138,25139,25140,25141,25142,25143,25144,25145,25146,25147,
94592 25148,25149,25150,25151,25152,25153,25154,25155,25156,25157,25158,25159,
94593 25160,25161,25162,25163,25164,25165,25166,25167,25168,25169,25170,25171,
94594 25172,25173,25174,25175,25176,25177,25178,25179,25180,25181,25182,25183,
94595 25184,25185,25186,25187,25188,25189,25190,25191,25192,25193,25194,25195,
94596 25196,25197,25198,25199,25200,25201,25202,25203,25204,25205,25206,25207,
94597 25208,25209,25210,25211,25212,25213,25214,25215,25216,25217,25218,25219,
94598 25220,25221,25222,25223,25224,25225,25226,25227,25228,25229,25230,25231,
94599 25232,25233,25234,25235,25236,25237,25238,25239,25240,25241,25242,25243,
94600 25244,25245,25246,25247,25248,25249,25250,25251,25252,25253,25254,25255,
94601 25256,25257,25258,25259,25260,25261,25262,25263,25264,25265,25266,25267,
94602 25268,25269,25270,25271,25272,25273,25274,25275,25276,25277,25278,25279,
94603 25280,25281,25282,25283,25284,25285,25286,25287,25288,25289,25290,25291,
94604 25292,25293,25294,25295,25296,25297,25298,25299,25300,25301,25302,25303,
94605 25304,25305,25306,25307,25308,25309,25310,25311,25312,25313,25314,25315,
94606 25316,25317,25318,25319,25320,25321,25322,25323,25324,25325,25326,25327,
94607 25328,25329,25330,25331,25332,25333,25334,25335,25336,25337,25338,25339,
94608 25340,25341,25342,25343,25344,25345,25346,25347,25348,25349,25350,25351,
94609 25352,25353,25354,25355,25356,25357,25358,25359,25360,25361,25362,25363,
94610 25364,25365,25366,25367,25368,25369,25370,25371,25372,25373,25374,25375,
94611 25376,25377,25378,25379,25380,25381,25382,25383,25384,25385,25386,25387,
94612 25388,25389,25390,25391,25392,25393,25394,25395,25396,25397,25398,25399,
94613 25400,25401,25402,25403,25404,25405,25406,25407,25408,25409,25410,25411,
94614 25412,25413,25414,25415,25416,25417,25418,25419,25420,25421,25422,25423,
94615 25424,25425,25426,25427,25428,25429,25430,25431,25432,25433,25434,25435,
94616 25436,25437,25438,25439,25440,25441,25442,25443,25444,25445,25446,25447,
94617 25448,25449,25450,25451,25452,25453,25454,25455,25456,25457,25458,25459,
94618 25460,25461,25462,25463,25464,25465,25466,25467,25468,25469,25470,25471,
94619 25472,25473,25474,25475,25476,25477,25478,25479,25480,25481,25482,25483,
94620 25484,25485,25486,25487,25488,25489,25490,25491,25492,25493,25494,25495,
94621 25496,25497,25498,25499,25500,25501,25502,25503,25504,25505,25506,25507,
94622 25508,25509,25510,25511,25512,25513,25514,25515,25516,25517,25518,25519,
94623 25520,25521,25522,25523,25524,25525,25526,25527,25528,25529,25530,25531,
94624 25532,25533,25534,25535,25536,25537,25538,25539,25540,25541,25542,25543,
94625 25544,25545,25546,25547,25548,25549,25550,25551,25552,25553,25554,25555,
94626 25556,25557,25558,25559,25560,25561,25562,25563,25564,25565,25566,25567,
94627 25568,25569,25570,25571,25572,25573,25574,25575,25576,25577,25578,25579,
94628 25580,25581,25582,25583,25584,25585,25586,25587,25588,25589,25590,25591,
94629 25592,25593,25594,25595,25596,25597,25598,25599,25600,25601,25602,25603,
94630 25604,25605,25606,25607,25608,25609,25610,25611,25612,25613,25614,25615,
94631 25616,25617,25618,25619,25620,25621,25622,25623,25624,25625,25626,25627,
94632 25628,25629,25630,25631,25632,25633,25634,25635,25636,25637,25638,25639,
94633 25640,25641,25642,25643,25644,25645,25646,25647,25648,25649,25650,25651,
94634 25652,25653,25654,25655,25656,25657,25658,25659,25660,25661,25662,25663,
94635 25664,25665,25666,25667,25668,25669,25670,25671,25672,25673,25674,25675,
94636 25676,25677,25678,25679,25680,25681,25682,25683,25684,25685,25686,25687,
94637 25688,25689,25690,25691,25692,25693,25694,25695,25696,25697,25698,25699,
94638 25700,25701,25702,25703,25704,25705,25706,25707,25708,25709,25710,25711,
94639 25712,25713,25714,25715,25716,25717,25718,25719,25720,25721,25722,25723,
94640 25724,25725,25726,25727,25728,25729,25730,25731,25732,25733,25734,25735,
94641 25736,25737,25738,25739,25740,25741,25742,25743,25744,25745,25746,25747,
94642 25748,25749,25750,25751,25752,25753,25754,25755,25756,25757,25758,25759,
94643 25760,25761,25762,25763,25764,25765,25766,25767,25768,25769,25770,25771,
94644 25772,25773,25774,25775,25776,25777,25778,25779,25780,25781,25782,25783,
94645 25784,25785,25786,25787,25788,25789,25790,25791,25792,25793,25794,25795,
94646 25796,25797,25798,25799,25800,25801,25802,25803,25804,25805,25806,25807,
94647 25808,25809,25810,25811,25812,25813,25814,25815,25816,25817,25818,25819,
94648 25820,25821,25822,25823,25824,25825,25826,25827,25828,25829,25830,25831,
94649 25832,25833,25834,25835,25836,25837,25838,25839,25840,25841,25842,25843,
94650 25844,25845,25846,25847,25848,25849,25850,25851,25852,25853,25854,25855,
94651 25856,25857,25858,25859,25860,25861,25862,25863,25864,25865,25866,25867,
94652 25868,25869,25870,25871,25872,25873,25874,25875,25876,25877,25878,25879,
94653 25880,25881,25882,25883,25884,25885,25886,25887,25888,25889,25890,25891,
94654 25892,25893,25894,25895,25896,25897,25898,25899,25900,25901,25902,25903,
94655 25904,25905,25906,25907,25908,25909,25910,25911,25912,25913,25914,25915,
94656 25916,25917,25918,25919,25920,25921,25922,25923,25924,25925,25926,25927,
94657 25928,25929,25930,25931,25932,25933,25934,25935,25936,25937,25938,25939,
94658 25940,25941,25942,25943,25944,25945,25946,25947,25948,25949,25950,25951,
94659 25952,25953,25954,25955,25956,25957,25958,25959,25960,25961,25962,25963,
94660 25964,25965,25966,25967,25968,25969,25970,25971,25972,25973,25974,25975,
94661 25976,25977,25978,25979,25980,25981,25982,25983,25984,25985,25986,25987,
94662 25988,25989,25990,25991,25992,25993,25994,25995,25996,25997,25998,25999,
94663 26000,26001,26002,26003,26004,26005,26006,26007,26008,26009,26010,26011,
94664 26012,26013,26014,26015,26016,26017,26018,26019,26020,26021,26022,26023,
94665 26024,26025,26026,26027,26028,26029,26030,26031,26032,26033,26034,26035,
94666 26036,26037,26038,26039,26040,26041,26042,26043,26044,26045,26046,26047,
94667 26048,26049,26050,26051,26052,26053,26054,26055,26056,26057,26058,26059,
94668 26060,26061,26062,26063,26064,26065,26066,26067,26068,26069,26070,26071,
94669 26072,26073,26074,26075,26076,26077,26078,26079,26080,26081,26082,26083,
94670 26084,26085,26086,26087,26088,26089,26090,26091,26092,26093,26094,26095,
94671 26096,26097,26098,26099,26100,26101,26102,26103,26104,26105,26106,26107,
94672 26108,26109,26110,26111,26112,26113,26114,26115,26116,26117,26118,26119,
94673 26120,26121,26122,26123,26124,26125,26126,26127,26128,26129,26130,26131,
94674 26132,26133,26134,26135,26136,26137,26138,26139,26140,26141,26142,26143,
94675 26144,26145,26146,26147,26148,26149,26150,26151,26152,26153,26154,26155,
94676 26156,26157,26158,26159,26160,26161,26162,26163,26164,26165,26166,26167,
94677 26168,26169,26170,26171,26172,26173,26174,26175,26176,26177,26178,26179,
94678 26180,26181,26182,26183,26184,26185,26186,26187,26188,26189,26190,26191,
94679 26192,26193,26194,26195,26196,26197,26198,26199,26200,26201,26202,26203,
94680 26204,26205,26206,26207,26208,26209,26210,26211,26212,26213,26214,26215,
94681 26216,26217,26218,26219,26220,26221,26222,26223,26224,26225,26226,26227,
94682 26228,26229,26230,26231,26232,26233,26234,26235,26236,26237,26238,26239,
94683 26240,26241,26242,26243,26244,26245,26246,26247,26248,26249,26250,26251,
94684 26252,26253,26254,26255,26256,26257,26258,26259,26260,26261,26262,26263,
94685 26264,26265,26266,26267,26268,26269,26270,26271,26272,26273,26274,26275,
94686 26276,26277,26278,26279,26280,26281,26282,26283,26284,26285,26286,26287,
94687 26288,26289,26290,26291,26292,26293,26294,26295,26296,26297,26298,26299,
94688 26300,26301,26302,26303,26304,26305,26306,26307,26308,26309,26310,26311,
94689 26312,26313,26314,26315,26316,26317,26318,26319,26320,26321,26322,26323,
94690 26324,26325,26326,26327,26328,26329,26330,26331,26332,26333,26334,26335,
94691 26336,26337,26338,26339,26340,26341,26342,26343,26344,26345,26346,26347,
94692 26348,26349,26350,26351,26352,26353,26354,26355,26356,26357,26358,26359,
94693 26360,26361,26362,26363,26364,26365,26366,26367,26368,26369,26370,26371,
94694 26372,26373,26374,26375,26376,26377,26378,26379,26380,26381,26382,26383,
94695 26384,26385,26386,26387,26388,26389,26390,26391,26392,26393,26394,26395,
94696 26396,26397,26398,26399,26400,26401,26402,26403,26404,26405,26406,26407,
94697 26408,26409,26410,26411,26412,26413,26414,26415,26416,26417,26418,26419,
94698 26420,26421,26422,26423,26424,26425,26426,26427,26428,26429,26430,26431,
94699 26432,26433,26434,26435,26436,26437,26438,26439,26440,26441,26442,26443,
94700 26444,26445,26446,26447,26448,26449,26450,26451,26452,26453,26454,26455,
94701 26456,26457,26458,26459,26460,26461,26462,26463,26464,26465,26466,26467,
94702 26468,26469,26470,26471,26472,26473,26474,26475,26476,26477,26478,26479,
94703 26480,26481,26482,26483,26484,26485,26486,26487,26488,26489,26490,26491,
94704 26492,26493,26494,26495,26496,26497,26498,26499,26500,26501,26502,26503,
94705 26504,26505,26506,26507,26508,26509,26510,26511,26512,26513,26514,26515,
94706 26516,26517,26518,26519,26520,26521,26522,26523,26524,26525,26526,26527,
94707 26528,26529,26530,26531,26532,26533,26534,26535,26536,26537,26538,26539,
94708 26540,26541,26542,26543,26544,26545,26546,26547,26548,26549,26550,26551,
94709 26552,26553,26554,26555,26556,26557,26558,26559,26560,26561,26562,26563,
94710 26564,26565,26566,26567,26568,26569,26570,26571,26572,26573,26574,26575,
94711 26576,26577,26578,26579,26580,26581,26582,26583,26584,26585,26586,26587,
94712 26588,26589,26590,26591,26592,26593,26594,26595,26596,26597,26598,26599,
94713 26600,26601,26602,26603,26604,26605,26606,26607,26608,26609,26610,26611,
94714 26612,26613,26614,26615,26616,26617,26618,26619,26620,26621,26622,26623,
94715 26624,26625,26626,26627,26628,26629,26630,26631,26632,26633,26634,26635,
94716 26636,26637,26638,26639,26640,26641,26642,26643,26644,26645,26646,26647,
94717 26648,26649,26650,26651,26652,26653,26654,26655,26656,26657,26658,26659,
94718 26660,26661,26662,26663,26664,26665,26666,26667,26668,26669,26670,26671,
94719 26672,26673,26674,26675,26676,26677,26678,26679,26680,26681,26682,26683,
94720 26684,26685,26686,26687,26688,26689,26690,26691,26692,26693,26694,26695,
94721 26696,26697,26698,26699,26700,26701,26702,26703,26704,26705,26706,26707,
94722 26708,26709,26710,26711,26712,26713,26714,26715,26716,26717,26718,26719,
94723 26720,26721,26722,26723,26724,26725,26726,26727,26728,26729,26730,26731,
94724 26732,26733,26734,26735,26736,26737,26738,26739,26740,26741,26742,26743,
94725 26744,26745,26746,26747,26748,26749,26750,26751,26752,26753,26754,26755,
94726 26756,26757,26758,26759,26760,26761,26762,26763,26764,26765,26766,26767,
94727 26768,26769,26770,26771,26772,26773,26774,26775,26776,26777,26778,26779,
94728 26780,26781,26782,26783,26784,26785,26786,26787,26788,26789,26790,26791,
94729 26792,26793,26794,26795,26796,26797,26798,26799,26800,26801,26802,26803,
94730 26804,26805,26806,26807,26808,26809,26810,26811,26812,26813,26814,26815,
94731 26816,26817,26818,26819,26820,26821,26822,26823,26824,26825,26826,26827,
94732 26828,26829,26830,26831,26832,26833,26834,26835,26836,26837,26838,26839,
94733 26840,26841,26842,26843,26844,26845,26846,26847,26848,26849,26850,26851,
94734 26852,26853,26854,26855,26856,26857,26858,26859,26860,26861,26862,26863,
94735 26864,26865,26866,26867,26868,26869,26870,26871,26872,26873,26874,26875,
94736 26876,26877,26878,26879,26880,26881,26882,26883,26884,26885,26886,26887,
94737 26888,26889,26890,26891,26892,26893,26894,26895,26896,26897,26898,26899,
94738 26900,26901,26902,26903,26904,26905,26906,26907,26908,26909,26910,26911,
94739 26912,26913,26914,26915,26916,26917,26918,26919,26920,26921,26922,26923,
94740 26924,26925,26926,26927,26928,26929,26930,26931,26932,26933,26934,26935,
94741 26936,26937,26938,26939,26940,26941,26942,26943,26944,26945,26946,26947,
94742 26948,26949,26950,26951,26952,26953,26954,26955,26956,26957,26958,26959,
94743 26960,26961,26962,26963,26964,26965,26966,26967,26968,26969,26970,26971,
94744 26972,26973,26974,26975,26976,26977,26978,26979,26980,26981,26982,26983,
94745 26984,26985,26986,26987,26988,26989,26990,26991,26992,26993,26994,26995,
94746 26996,26997,26998,26999,27000,27001,27002,27003,27004,27005,27006,27007,
94747 27008,27009,27010,27011,27012,27013,27014,27015,27016,27017,27018,27019,
94748 27020,27021,27022,27023,27024,27025,27026,27027,27028,27029,27030,27031,
94749 27032,27033,27034,27035,27036,27037,27038,27039,27040,27041,27042,27043,
94750 27044,27045,27046,27047,27048,27049,27050,27051,27052,27053,27054,27055,
94751 27056,27057,27058,27059,27060,27061,27062,27063,27064,27065,27066,27067,
94752 27068,27069,27070,27071,27072,27073,27074,27075,27076,27077,27078,27079,
94753 27080,27081,27082,27083,27084,27085,27086,27087,27088,27089,27090,27091,
94754 27092,27093,27094,27095,27096,27097,27098,27099,27100,27101,27102,27103,
94755 27104,27105,27106,27107,27108,27109,27110,27111,27112,27113,27114,27115,
94756 27116,27117,27118,27119,27120,27121,27122,27123,27124,27125,27126,27127,
94757 27128,27129,27130,27131,27132,27133,27134,27135,27136,27137,27138,27139,
94758 27140,27141,27142,27143,27144,27145,27146,27147,27148,27149,27150,27151,
94759 27152,27153,27154,27155,27156,27157,27158,27159,27160,27161,27162,27163,
94760 27164,27165,27166,27167,27168,27169,27170,27171,27172,27173,27174,27175,
94761 27176,27177,27178,27179,27180,27181,27182,27183,27184,27185,27186,27187,
94762 27188,27189,27190,27191,27192,27193,27194,27195,27196,27197,27198,27199,
94763 27200,27201,27202,27203,27204,27205,27206,27207,27208,27209,27210,27211,
94764 27212,27213,27214,27215,27216,27217,27218,27219,27220,27221,27222,27223,
94765 27224,27225,27226,27227,27228,27229,27230,27231,27232,27233,27234,27235,
94766 27236,27237,27238,27239,27240,27241,27242,27243,27244,27245,27246,27247,
94767 27248,27249,27250,27251,27252,27253,27254,27255,27256,27257,27258,27259,
94768 27260,27261,27262,27263,27264,27265,27266,27267,27268,27269,27270,27271,
94769 27272,27273,27274,27275,27276,27277,27278,27279,27280,27281,27282,27283,
94770 27284,27285,27286,27287,27288,27289,27290,27291,27292,27293,27294,27295,
94771 27296,27297,27298,27299,27300,27301,27302,27303,27304,27305,27306,27307,
94772 27308,27309,27310,27311,27312,27313,27314,27315,27316,27317,27318,27319,
94773 27320,27321,27322,27323,27324,27325,27326,27327,27328,27329,27330,27331,
94774 27332,27333,27334,27335,27336,27337,27338,27339,27340,27341,27342,27343,
94775 27344,27345,27346,27347,27348,27349,27350,27351,27352,27353,27354,27355,
94776 27356,27357,27358,27359,27360,27361,27362,27363,27364,27365,27366,27367,
94777 27368,27369,27370,27371,27372,27373,27374,27375,27376,27377,27378,27379,
94778 27380,27381,27382,27383,27384,27385,27386,27387,27388,27389,27390,27391,
94779 27392,27393,27394,27395,27396,27397,27398,27399,27400,27401,27402,27403,
94780 27404,27405,27406,27407,27408,27409,27410,27411,27412,27413,27414,27415,
94781 27416,27417,27418,27419,27420,27421,27422,27423,27424,27425,27426,27427,
94782 27428,27429,27430,27431,27432,27433,27434,27435,27436,27437,27438,27439,
94783 27440,27441,27442,27443,27444,27445,27446,27447,27448,27449,27450,27451,
94784 27452,27453,27454,27455,27456,27457,27458,27459,27460,27461,27462,27463,
94785 27464,27465,27466,27467,27468,27469,27470,27471,27472,27473,27474,27475,
94786 27476,27477,27478,27479,27480,27481,27482,27483,27484,27485,27486,27487,
94787 27488,27489,27490,27491,27492,27493,27494,27495,27496,27497,27498,27499,
94788 27500,27501,27502,27503,27504,27505,27506,27507,27508,27509,27510,27511,
94789 27512,27513,27514,27515,27516,27517,27518,27519,27520,27521,27522,27523,
94790 27524,27525,27526,27527,27528,27529,27530,27531,27532,27533,27534,27535,
94791 27536,27537,27538,27539,27540,27541,27542,27543,27544,27545,27546,27547,
94792 27548,27549,27550,27551,27552,27553,27554,27555,27556,27557,27558,27559,
94793 27560,27561,27562,27563,27564,27565,27566,27567,27568,27569,27570,27571,
94794 27572,27573,27574,27575,27576,27577,27578,27579,27580,27581,27582,27583,
94795 27584,27585,27586,27587,27588,27589,27590,27591,27592,27593,27594,27595,
94796 27596,27597,27598,27599,27600,27601,27602,27603,27604,27605,27606,27607,
94797 27608,27609,27610,27611,27612,27613,27614,27615,27616,27617,27618,27619,
94798 27620,27621,27622,27623,27624,27625,27626,27627,27628,27629,27630,27631,
94799 27632,27633,27634,27635,27636,27637,27638,27639,27640,27641,27642,27643,
94800 27644,27645,27646,27647,27648,27649,27650,27651,27652,27653,27654,27655,
94801 27656,27657,27658,27659,27660,27661,27662,27663,27664,27665,27666,27667,
94802 27668,27669,27670,27671,27672,27673,27674,27675,27676,27677,27678,27679,
94803 27680,27681,27682,27683,27684,27685,27686,27687,27688,27689,27690,27691,
94804 27692,27693,27694,27695,27696,27697,27698,27699,27700,27701,27702,27703,
94805 27704,27705,27706,27707,27708,27709,27710,27711,27712,27713,27714,27715,
94806 27716,27717,27718,27719,27720,27721,27722,27723,27724,27725,27726,27727,
94807 27728,27729,27730,27731,27732,27733,27734,27735,27736,27737,27738,27739,
94808 27740,27741,27742,27743,27744,27745,27746,27747,27748,27749,27750,27751,
94809 27752,27753,27754,27755,27756,27757,27758,27759,27760,27761,27762,27763,
94810 27764,27765,27766,27767,27768,27769,27770,27771,27772,27773,27774,27775,
94811 27776,27777,27778,27779,27780,27781,27782,27783,27784,27785,27786,27787,
94812 27788,27789,27790,27791,27792,27793,27794,27795,27796,27797,27798,27799,
94813 27800,27801,27802,27803,27804,27805,27806,27807,27808,27809,27810,27811,
94814 27812,27813,27814,27815,27816,27817,27818,27819,27820,27821,27822,27823,
94815 27824,27825,27826,27827,27828,27829,27830,27831,27832,27833,27834,27835,
94816 27836,27837,27838,27839,27840,27841,27842,27843,27844,27845,27846,27847,
94817 27848,27849,27850,27851,27852,27853,27854,27855,27856,27857,27858,27859,
94818 27860,27861,27862,27863,27864,27865,27866,27867,27868,27869,27870,27871,
94819 27872,27873,27874,27875,27876,27877,27878,27879,27880,27881,27882,27883,
94820 27884,27885,27886,27887,27888,27889,27890,27891,27892,27893,27894,27895,
94821 27896,27897,27898,27899,27900,27901,27902,27903,27904,27905,27906,27907,
94822 27908,27909,27910,27911,27912,27913,27914,27915,27916,27917,27918,27919,
94823 27920,27921,27922,27923,27924,27925,27926,27927,27928,27929,27930,27931,
94824 27932,27933,27934,27935,27936,27937,27938,27939,27940,27941,27942,27943,
94825 27944,27945,27946,27947,27948,27949,27950,27951,27952,27953,27954,27955,
94826 27956,27957,27958,27959,27960,27961,27962,27963,27964,27965,27966,27967,
94827 27968,27969,27970,27971,27972,27973,27974,27975,27976,27977,27978,27979,
94828 27980,27981,27982,27983,27984,27985,27986,27987,27988,27989,27990,27991,
94829 27992,27993,27994,27995,27996,27997,27998,27999,28000,28001,28002,28003,
94830 28004,28005,28006,28007,28008,28009,28010,28011,28012,28013,28014,28015,
94831 28016,28017,28018,28019,28020,28021,28022,28023,28024,28025,28026,28027,
94832 28028,28029,28030,28031,28032,28033,28034,28035,28036,28037,28038,28039,
94833 28040,28041,28042,28043,28044,28045,28046,28047,28048,28049,28050,28051,
94834 28052,28053,28054,28055,28056,28057,28058,28059,28060,28061,28062,28063,
94835 28064,28065,28066,28067,28068,28069,28070,28071,28072,28073,28074,28075,
94836 28076,28077,28078,28079,28080,28081,28082,28083,28084,28085,28086,28087,
94837 28088,28089,28090,28091,28092,28093,28094,28095,28096,28097,28098,28099,
94838 28100,28101,28102,28103,28104,28105,28106,28107,28108,28109,28110,28111,
94839 28112,28113,28114,28115,28116,28117,28118,28119,28120,28121,28122,28123,
94840 28124,28125,28126,28127,28128,28129,28130,28131,28132,28133,28134,28135,
94841 28136,28137,28138,28139,28140,28141,28142,28143,28144,28145,28146,28147,
94842 28148,28149,28150,28151,28152,28153,28154,28155,28156,28157,28158,28159,
94843 28160,28161,28162,28163,28164,28165,28166,28167,28168,28169,28170,28171,
94844 28172,28173,28174,28175,28176,28177,28178,28179,28180,28181,28182,28183,
94845 28184,28185,28186,28187,28188,28189,28190,28191,28192,28193,28194,28195,
94846 28196,28197,28198,28199,28200,28201,28202,28203,28204,28205,28206,28207,
94847 28208,28209,28210,28211,28212,28213,28214,28215,28216,28217,28218,28219,
94848 28220,28221,28222,28223,28224,28225,28226,28227,28228,28229,28230,28231,
94849 28232,28233,28234,28235,28236,28237,28238,28239,28240,28241,28242,28243,
94850 28244,28245,28246,28247,28248,28249,28250,28251,28252,28253,28254,28255,
94851 28256,28257,28258,28259,28260,28261,28262,28263,28264,28265,28266,28267,
94852 28268,28269,28270,28271,28272,28273,28274,28275,28276,28277,28278,28279,
94853 28280,28281,28282,28283,28284,28285,28286,28287,28288,28289,28290,28291,
94854 28292,28293,28294,28295,28296,28297,28298,28299,28300,28301,28302,28303,
94855 28304,28305,28306,28307,28308,28309,28310,28311,28312,28313,28314,28315,
94856 28316,28317,28318,28319,28320,28321,28322,28323,28324,28325,28326,28327,
94857 28328,28329,28330,28331,28332,28333,28334,28335,28336,28337,28338,28339,
94858 28340,28341,28342,28343,28344,28345,28346,28347,28348,28349,28350,28351,
94859 28352,28353,28354,28355,28356,28357,28358,28359,28360,28361,28362,28363,
94860 28364,28365,28366,28367,28368,28369,28370,28371,28372,28373,28374,28375,
94861 28376,28377,28378,28379,28380,28381,28382,28383,28384,28385,28386,28387,
94862 28388,28389,28390,28391,28392,28393,28394,28395,28396,28397,28398,28399,
94863 28400,28401,28402,28403,28404,28405,28406,28407,28408,28409,28410,28411,
94864 28412,28413,28414,28415,28416,28417,28418,28419,28420,28421,28422,28423,
94865 28424,28425,28426,28427,28428,28429,28430,28431,28432,28433,28434,28435,
94866 28436,28437,28438,28439,28440,28441,28442,28443,28444,28445,28446,28447,
94867 28448,28449,28450,28451,28452,28453,28454,28455,28456,28457,28458,28459,
94868 28460,28461,28462,28463,28464,28465,28466,28467,28468,28469,28470,28471,
94869 28472,28473,28474,28475,28476,28477,28478,28479,28480,28481,28482,28483,
94870 28484,28485,28486,28487,28488,28489,28490,28491,28492,28493,28494,28495,
94871 28496,28497,28498,28499,28500,28501,28502,28503,28504,28505,28506,28507,
94872 28508,28509,28510,28511,28512,28513,28514,28515,28516,28517,28518,28519,
94873 28520,28521,28522,28523,28524,28525,28526,28527,28528,28529,28530,28531,
94874 28532,28533,28534,28535,28536,28537,28538,28539,28540,28541,28542,28543,
94875 28544,28545,28546,28547,28548,28549,28550,28551,28552,28553,28554,28555,
94876 28556,28557,28558,28559,28560,28561,28562,28563,28564,28565,28566,28567,
94877 28568,28569,28570,28571,28572,28573,28574,28575,28576,28577,28578,28579,
94878 28580,28581,28582,28583,28584,28585,28586,28587,28588,28589,28590,28591,
94879 28592,28593,28594,28595,28596,28597,28598,28599,28600,28601,28602,28603,
94880 28604,28605,28606,28607,28608,28609,28610,28611,28612,28613,28614,28615,
94881 28616,28617,28618,28619,28620,28621,28622,28623,28624,28625,28626,28627,
94882 28628,28629,28630,28631,28632,28633,28634,28635,28636,28637,28638,28639,
94883 28640,28641,28642,28643,28644,28645,28646,28647,28648,28649,28650,28651,
94884 28652,28653,28654,28655,28656,28657,28658,28659,28660,28661,28662,28663,
94885 28664,28665,28666,28667,28668,28669,28670,28671,28672,28673,28674,28675,
94886 28676,28677,28678,28679,28680,28681,28682,28683,28684,28685,28686,28687,
94887 28688,28689,28690,28691,28692,28693,28694,28695,28696,28697,28698,28699,
94888 28700,28701,28702,28703,28704,28705,28706,28707,28708,28709,28710,28711,
94889 28712,28713,28714,28715,28716,28717,28718,28719,28720,28721,28722,28723,
94890 28724,28725,28726,28727,28728,28729,28730,28731,28732,28733,28734,28735,
94891 28736,28737,28738,28739,28740,28741,28742,28743,28744,28745,28746,28747,
94892 28748,28749,28750,28751,28752,28753,28754,28755,28756,28757,28758,28759,
94893 28760,28761,28762,28763,28764,28765,28766,28767,28768,28769,28770,28771,
94894 28772,28773,28774,28775,28776,28777,28778,28779,28780,28781,28782,28783,
94895 28784,28785,28786,28787,28788,28789,28790,28791,28792,28793,28794,28795,
94896 28796,28797,28798,28799,28800,28801,28802,28803,28804,28805,28806,28807,
94897 28808,28809,28810,28811,28812,28813,28814,28815,28816,28817,28818,28819,
94898 28820,28821,28822,28823,28824,28825,28826,28827,28828,28829,28830,28831,
94899 28832,28833,28834,28835,28836,28837,28838,28839,28840,28841,28842,28843,
94900 28844,28845,28846,28847,28848,28849,28850,28851,28852,28853,28854,28855,
94901 28856,28857,28858,28859,28860,28861,28862,28863,28864,28865,28866,28867,
94902 28868,28869,28870,28871,28872,28873,28874,28875,28876,28877,28878,28879,
94903 28880,28881,28882,28883,28884,28885,28886,28887,28888,28889,28890,28891,
94904 28892,28893,28894,28895,28896,28897,28898,28899,28900,28901,28902,28903,
94905 28904,28905,28906,28907,28908,28909,28910,28911,28912,28913,28914,28915,
94906 28916,28917,28918,28919,28920,28921,28922,28923,28924,28925,28926,28927,
94907 28928,28929,28930,28931,28932,28933,28934,28935,28936,28937,28938,28939,
94908 28940,28941,28942,28943,28944,28945,28946,28947,28948,28949,28950,28951,
94909 28952,28953,28954,28955,28956,28957,28958,28959,28960,28961,28962,28963,
94910 28964,28965,28966,28967,28968,28969,28970,28971,28972,28973,28974,28975,
94911 28976,28977,28978,28979,28980,28981,28982,28983,28984,28985,28986,28987,
94912 28988,28989,28990,28991,28992,28993,28994,28995,28996,28997,28998,28999,
94913 29000,29001,29002,29003,29004,29005,29006,29007,29008,29009,29010,29011,
94914 29012,29013,29014,29015,29016,29017,29018,29019,29020,29021,29022,29023,
94915 29024,29025,29026,29027,29028,29029,29030,29031,29032,29033,29034,29035,
94916 29036,29037,29038,29039,29040,29041,29042,29043,29044,29045,29046,29047,
94917 29048,29049,29050,29051,29052,29053,29054,29055,29056,29057,29058,29059,
94918 29060,29061,29062,29063,29064,29065,29066,29067,29068,29069,29070,29071,
94919 29072,29073,29074,29075,29076,29077,29078,29079,29080,29081,29082,29083,
94920 29084,29085,29086,29087,29088,29089,29090,29091,29092,29093,29094,29095,
94921 29096,29097,29098,29099,29100,29101,29102,29103,29104,29105,29106,29107,
94922 29108,29109,29110,29111,29112,29113,29114,29115,29116,29117,29118,29119,
94923 29120,29121,29122,29123,29124,29125,29126,29127,29128,29129,29130,29131,
94924 29132,29133,29134,29135,29136,29137,29138,29139,29140,29141,29142,29143,
94925 29144,29145,29146,29147,29148,29149,29150,29151,29152,29153,29154,29155,
94926 29156,29157,29158,29159,29160,29161,29162,29163,29164,29165,29166,29167,
94927 29168,29169,29170,29171,29172,29173,29174,29175,29176,29177,29178,29179,
94928 29180,29181,29182,29183,29184,29185,29186,29187,29188,29189,29190,29191,
94929 29192,29193,29194,29195,29196,29197,29198,29199,29200,29201,29202,29203,
94930 29204,29205,29206,29207,29208,29209,29210,29211,29212,29213,29214,29215,
94931 29216,29217,29218,29219,29220,29221,29222,29223,29224,29225,29226,29227,
94932 29228,29229,29230,29231,29232,29233,29234,29235,29236,29237,29238,29239,
94933 29240,29241,29242,29243,29244,29245,29246,29247,29248,29249,29250,29251,
94934 29252,29253,29254,29255,29256,29257,29258,29259,29260,29261,29262,29263,
94935 29264,29265,29266,29267,29268,29269,29270,29271,29272,29273,29274,29275,
94936 29276,29277,29278,29279,29280,29281,29282,29283,29284,29285,29286,29287,
94937 29288,29289,29290,29291,29292,29293,29294,29295,29296,29297,29298,29299,
94938 29300,29301,29302,29303,29304,29305,29306,29307,29308,29309,29310,29311,
94939 29312,29313,29314,29315,29316,29317,29318,29319,29320,29321,29322,29323,
94940 29324,29325,29326,29327,29328,29329,29330,29331,29332,29333,29334,29335,
94941 29336,29337,29338,29339,29340,29341,29342,29343,29344,29345,29346,29347,
94942 29348,29349,29350,29351,29352,29353,29354,29355,29356,29357,29358,29359,
94943 29360,29361,29362,29363,29364,29365,29366,29367,29368,29369,29370,29371,
94944 29372,29373,29374,29375,29376,29377,29378,29379,29380,29381,29382,29383,
94945 29384,29385,29386,29387,29388,29389,29390,29391,29392,29393,29394,29395,
94946 29396,29397,29398,29399,29400,29401,29402,29403,29404,29405,29406,29407,
94947 29408,29409,29410,29411,29412,29413,29414,29415,29416,29417,29418,29419,
94948 29420,29421,29422,29423,29424,29425,29426,29427,29428,29429,29430,29431,
94949 29432,29433,29434,29435,29436,29437,29438,29439,29440,29441,29442,29443,
94950 29444,29445,29446,29447,29448,29449,29450,29451,29452,29453,29454,29455,
94951 29456,29457,29458,29459,29460,29461,29462,29463,29464,29465,29466,29467,
94952 29468,29469,29470,29471,29472,29473,29474,29475,29476,29477,29478,29479,
94953 29480,29481,29482,29483,29484,29485,29486,29487,29488,29489,29490,29491,
94954 29492,29493,29494,29495,29496,29497,29498,29499,29500,29501,29502,29503,
94955 29504,29505,29506,29507,29508,29509,29510,29511,29512,29513,29514,29515,
94956 29516,29517,29518,29519,29520,29521,29522,29523,29524,29525,29526,29527,
94957 29528,29529,29530,29531,29532,29533,29534,29535,29536,29537,29538,29539,
94958 29540,29541,29542,29543,29544,29545,29546,29547,29548,29549,29550,29551,
94959 29552,29553,29554,29555,29556,29557,29558,29559,29560,29561,29562,29563,
94960 29564,29565,29566,29567,29568,29569,29570,29571,29572,29573,29574,29575,
94961 29576,29577,29578,29579,29580,29581,29582,29583,29584,29585,29586,29587,
94962 29588,29589,29590,29591,29592,29593,29594,29595,29596,29597,29598,29599,
94963 29600,29601,29602,29603,29604,29605,29606,29607,29608,29609,29610,29611,
94964 29612,29613,29614,29615,29616,29617,29618,29619,29620,29621,29622,29623,
94965 29624,29625,29626,29627,29628,29629,29630,29631,29632,29633,29634,29635,
94966 29636,29637,29638,29639,29640,29641,29642,29643,29644,29645,29646,29647,
94967 29648,29649,29650,29651,29652,29653,29654,29655,29656,29657,29658,29659,
94968 29660,29661,29662,29663,29664,29665,29666,29667,29668,29669,29670,29671,
94969 29672,29673,29674,29675,29676,29677,29678,29679,29680,29681,29682,29683,
94970 29684,29685,29686,29687,29688,29689,29690,29691,29692,29693,29694,29695,
94971 29696,29697,29698,29699,29700,29701,29702,29703,29704,29705,29706,29707,
94972 29708,29709,29710,29711,29712,29713,29714,29715,29716,29717,29718,29719,
94973 29720,29721,29722,29723,29724,29725,29726,29727,29728,29729,29730,29731,
94974 29732,29733,29734,29735,29736,29737,29738,29739,29740,29741,29742,29743,
94975 29744,29745,29746,29747,29748,29749,29750,29751,29752,29753,29754,29755,
94976 29756,29757,29758,29759,29760,29761,29762,29763,29764,29765,29766,29767,
94977 29768,29769,29770,29771,29772,29773,29774,29775,29776,29777,29778,29779,
94978 29780,29781,29782,29783,29784,29785,29786,29787,29788,29789,29790,29791,
94979 29792,29793,29794,29795,29796,29797,29798,29799,29800,29801,29802,29803,
94980 29804,29805,29806,29807,29808,29809,29810,29811,29812,29813,29814,29815,
94981 29816,29817,29818,29819,29820,29821,29822,29823,29824,29825,29826,29827,
94982 29828,29829,29830,29831,29832,29833,29834,29835,29836,29837,29838,29839,
94983 29840,29841,29842,29843,29844,29845,29846,29847,29848,29849,29850,29851,
94984 29852,29853,29854,29855,29856,29857,29858,29859,29860,29861,29862,29863,
94985 29864,29865,29866,29867,29868,29869,29870,29871,29872,29873,29874,29875,
94986 29876,29877,29878,29879,29880,29881,29882,29883,29884,29885,29886,29887,
94987 29888,29889,29890,29891,29892,29893,29894,29895,29896,29897,29898,29899,
94988 29900,29901,29902,29903,29904,29905,29906,29907,29908,29909,29910,29911,
94989 29912,29913,29914,29915,29916,29917,29918,29919,29920,29921,29922,29923,
94990 29924,29925,29926,29927,29928,29929,29930,29931,29932,29933,29934,29935,
94991 29936,29937,29938,29939,29940,29941,29942,29943,29944,29945,29946,29947,
94992 29948,29949,29950,29951,29952,29953,29954,29955,29956,29957,29958,29959,
94993 29960,29961,29962,29963,29964,29965,29966,29967,29968,29969,29970,29971,
94994 29972,29973,29974,29975,29976,29977,29978,29979,29980,29981,29982,29983,
94995 29984,29985,29986,29987,29988,29989,29990,29991,29992,29993,29994,29995,
94996 29996,29997,29998,29999,30000,30001,30002,30003,30004,30005,30006,30007,
94997 30008,30009,30010,30011,30012,30013,30014,30015,30016,30017,30018,30019,
94998 30020,30021,30022,30023,30024,30025,30026,30027,30028,30029,30030,30031,
94999 30032,30033,30034,30035,30036,30037,30038,30039,30040,30041,30042,30043,
95000 30044,30045,30046,30047,30048,30049,30050,30051,30052,30053,30054,30055,
95001 30056,30057,30058,30059,30060,30061,30062,30063,30064,30065,30066,30067,
95002 30068,30069,30070,30071,30072,30073,30074,30075,30076,30077,30078,30079,
95003 30080,30081,30082,30083,30084,30085,30086,30087,30088,30089,30090,30091,
95004 30092,30093,30094,30095,30096,30097,30098,30099,30100,30101,30102,30103,
95005 30104,30105,30106,30107,30108,30109,30110,30111,30112,30113,30114,30115,
95006 30116,30117,30118,30119,30120,30121,30122,30123,30124,30125,30126,30127,
95007 30128,30129,30130,30131,30132,30133,30134,30135,30136,30137,30138,30139,
95008 30140,30141,30142,30143,30144,30145,30146,30147,30148,30149,30150,30151,
95009 30152,30153,30154,30155,30156,30157,30158,30159,30160,30161,30162,30163,
95010 30164,30165,30166,30167,30168,30169,30170,30171,30172,30173,30174,30175,
95011 30176,30177,30178,30179,30180,30181,30182,30183,30184,30185,30186,30187,
95012 30188,30189,30190,30191,30192,30193,30194,30195,30196,30197,30198,30199,
95013 30200,30201,30202,30203,30204,30205,30206,30207,30208,30209,30210,30211,
95014 30212,30213,30214,30215,30216,30217,30218,30219,30220,30221,30222,30223,
95015 30224,30225,30226,30227,30228,30229,30230,30231,30232,30233,30234,30235,
95016 30236,30237,30238,30239,30240,30241,30242,30243,30244,30245,30246,30247,
95017 30248,30249,30250,30251,30252,30253,30254,30255,30256,30257,30258,30259,
95018 30260,30261,30262,30263,30264,30265,30266,30267,30268,30269,30270,30271,
95019 30272,30273,30274,30275,30276,30277,30278,30279,30280,30281,30282,30283,
95020 30284,30285,30286,30287,30288,30289,30290,30291,30292,30293,30294,30295,
95021 30296,30297,30298,30299,30300,30301,30302,30303,30304,30305,30306,30307,
95022 30308,30309,30310,30311,30312,30313,30314,30315,30316,30317,30318,30319,
95023 30320,30321,30322,30323,30324,30325,30326,30327,30328,30329,30330,30331,
95024 30332,30333,30334,30335,30336,30337,30338,30339,30340,30341,30342,30343,
95025 30344,30345,30346,30347,30348,30349,30350,30351,30352,30353,30354,30355,
95026 30356,30357,30358,30359,30360,30361,30362,30363,30364,30365,30366,30367,
95027 30368,30369,30370,30371,30372,30373,30374,30375,30376,30377,30378,30379,
95028 30380,30381,30382,30383,30384,30385,30386,30387,30388,30389,30390,30391,
95029 30392,30393,30394,30395,30396,30397,30398,30399,30400,30401,30402,30403,
95030 30404,30405,30406,30407,30408,30409,30410,30411,30412,30413,30414,30415,
95031 30416,30417,30418,30419,30420,30421,30422,30423,30424,30425,30426,30427,
95032 30428,30429,30430,30431,30432,30433,30434,30435,30436,30437,30438,30439,
95033 30440,30441,30442,30443,30444,30445,30446,30447,30448,30449,30450,30451,
95034 30452,30453,30454,30455,30456,30457,30458,30459,30460,30461,30462,30463,
95035 30464,30465,30466,30467,30468,30469,30470,30471,30472,30473,30474,30475,
95036 30476,30477,30478,30479,30480,30481,30482,30483,30484,30485,30486,30487,
95037 30488,30489,30490,30491,30492,30493,30494,30495,30496,30497,30498,30499,
95038 30500,30501,30502,30503,30504,30505,30506,30507,30508,30509,30510,30511,
95039 30512,30513,30514,30515,30516,30517,30518,30519,30520,30521,30522,30523,
95040 30524,30525,30526,30527,30528,30529,30530,30531,30532,30533,30534,30535,
95041 30536,30537,30538,30539,30540,30541,30542,30543,30544,30545,30546,30547,
95042 30548,30549,30550,30551,30552,30553,30554,30555,30556,30557,30558,30559,
95043 30560,30561,30562,30563,30564,30565,30566,30567,30568,30569,30570,30571,
95044 30572,30573,30574,30575,30576,30577,30578,30579,30580,30581,30582,30583,
95045 30584,30585,30586,30587,30588,30589,30590,30591,30592,30593,30594,30595,
95046 30596,30597,30598,30599,30600,30601,30602,30603,30604,30605,30606,30607,
95047 30608,30609,30610,30611,30612,30613,30614,30615,30616,30617,30618,30619,
95048 30620,30621,30622,30623,30624,30625,30626,30627,30628,30629,30630,30631,
95049 30632,30633,30634,30635,30636,30637,30638,30639,30640,30641,30642,30643,
95050 30644,30645,30646,30647,30648,30649,30650,30651,30652,30653,30654,30655,
95051 30656,30657,30658,30659,30660,30661,30662,30663,30664,30665,30666,30667,
95052 30668,30669,30670,30671,30672,30673,30674,30675,30676,30677,30678,30679,
95053 30680,30681,30682,30683,30684,30685,30686,30687,30688,30689,30690,30691,
95054 30692,30693,30694,30695,30696,30697,30698,30699,30700,30701,30702,30703,
95055 30704,30705,30706,30707,30708,30709,30710,30711,30712,30713,30714,30715,
95056 30716,30717,30718,30719,30720,30721,30722,30723,30724,30725,30726,30727,
95057 30728,30729,30730,30731,30732,30733,30734,30735,30736,30737,30738,30739,
95058 30740,30741,30742,30743,30744,30745,30746,30747,30748,30749,30750,30751,
95059 30752,30753,30754,30755,30756,30757,30758,30759,30760,30761,30762,30763,
95060 30764,30765,30766,30767,30768,30769,30770,30771,30772,30773,30774,30775,
95061 30776,30777,30778,30779,30780,30781,30782,30783,30784,30785,30786,30787,
95062 30788,30789,30790,30791,30792,30793,30794,30795,30796,30797,30798,30799,
95063 30800,30801,30802,30803,30804,30805,30806,30807,30808,30809,30810,30811,
95064 30812,30813,30814,30815,30816,30817,30818,30819,30820,30821,30822,30823,
95065 30824,30825,30826,30827,30828,30829,30830,30831,30832,30833,30834,30835,
95066 30836,30837,30838,30839,30840,30841,30842,30843,30844,30845,30846,30847,
95067 30848,30849,30850,30851,30852,30853,30854,30855,30856,30857,30858,30859,
95068 30860,30861,30862,30863,30864,30865,30866,30867,30868,30869,30870,30871,
95069 30872,30873,30874,30875,30876,30877,30878,30879,30880,30881,30882,30883,
95070 30884,30885,30886,30887,30888,30889,30890,30891,30892,30893,30894,30895,
95071 30896,30897,30898,30899,30900,30901,30902,30903,30904,30905,30906,30907,
95072 30908,30909,30910,30911,30912,30913,30914,30915,30916,30917,30918,30919,
95073 30920,30921,30922,30923,30924,30925,30926,30927,30928,30929,30930,30931,
95074 30932,30933,30934,30935,30936,30937,30938,30939,30940,30941,30942,30943,
95075 30944,30945,30946,30947,30948,30949,30950,30951,30952,30953,30954,30955,
95076 30956,30957,30958,30959,30960,30961,30962,30963,30964,30965,30966,30967,
95077 30968,30969,30970,30971,30972,30973,30974,30975,30976,30977,30978,30979,
95078 30980,30981,30982,30983,30984,30985,30986,30987,30988,30989,30990,30991,
95079 30992,30993,30994,30995,30996,30997,30998,30999,31000,31001,31002,31003,
95080 31004,31005,31006,31007,31008,31009,31010,31011,31012,31013,31014,31015,
95081 31016,31017,31018,31019,31020,31021,31022,31023,31024,31025,31026,31027,
95082 31028,31029,31030,31031,31032,31033,31034,31035,31036,31037,31038,31039,
95083 31040,31041,31042,31043,31044,31045,31046,31047,31048,31049,31050,31051,
95084 31052,31053,31054,31055,31056,31057,31058,31059,31060,31061,31062,31063,
95085 31064,31065,31066,31067,31068,31069,31070,31071,31072,31073,31074,31075,
95086 31076,31077,31078,31079,31080,31081,31082,31083,31084,31085,31086,31087,
95087 31088,31089,31090,31091,31092,31093,31094,31095,31096,31097,31098,31099,
95088 31100,31101,31102,31103,31104,31105,31106,31107,31108,31109,31110,31111,
95089 31112,31113,31114,31115,31116,31117,31118,31119,31120,31121,31122,31123,
95090 31124,31125,31126,31127,31128,31129,31130,31131,31132,31133,31134,31135,
95091 31136,31137,31138,31139,31140,31141,31142,31143,31144,31145,31146,31147,
95092 31148,31149,31150,31151,31152,31153,31154,31155,31156,31157,31158,31159,
95093 31160,31161,31162,31163,31164,31165,31166,31167,31168,31169,31170,31171,
95094 31172,31173,31174,31175,31176,31177,31178,31179,31180,31181,31182,31183,
95095 31184,31185,31186,31187,31188,31189,31190,31191,31192,31193,31194,31195,
95096 31196,31197,31198,31199,31200,31201,31202,31203,31204,31205,31206,31207,
95097 31208,31209,31210,31211,31212,31213,31214,31215,31216,31217,31218,31219,
95098 31220,31221,31222,31223,31224,31225,31226,31227,31228,31229,31230,31231,
95099 31232,31233,31234,31235,31236,31237,31238,31239,31240,31241,31242,31243,
95100 31244,31245,31246,31247,31248,31249,31250,31251,31252,31253,31254,31255,
95101 31256,31257,31258,31259,31260,31261,31262,31263,31264,31265,31266,31267,
95102 31268,31269,31270,31271,31272,31273,31274,31275,31276,31277,31278,31279,
95103 31280,31281,31282,31283,31284,31285,31286,31287,31288,31289,31290,31291,
95104 31292,31293,31294,31295,31296,31297,31298,31299,31300,31301,31302,31303,
95105 31304,31305,31306,31307,31308,31309,31310,31311,31312,31313,31314,31315,
95106 31316,31317,31318,31319,31320,31321,31322,31323,31324,31325,31326,31327,
95107 31328,31329,31330,31331,31332,31333,31334,31335,31336,31337,31338,31339,
95108 31340,31341,31342,31343,31344,31345,31346,31347,31348,31349,31350,31351,
95109 31352,31353,31354,31355,31356,31357,31358,31359,31360,31361,31362,31363,
95110 31364,31365,31366,31367,31368,31369,31370,31371,31372,31373,31374,31375,
95111 31376,31377,31378,31379,31380,31381,31382,31383,31384,31385,31386,31387,
95112 31388,31389,31390,31391,31392,31393,31394,31395,31396,31397,31398,31399,
95113 31400,31401,31402,31403,31404,31405,31406,31407,31408,31409,31410,31411,
95114 31412,31413,31414,31415,31416,31417,31418,31419,31420,31421,31422,31423,
95115 31424,31425,31426,31427,31428,31429,31430,31431,31432,31433,31434,31435,
95116 31436,31437,31438,31439,31440,31441,31442,31443,31444,31445,31446,31447,
95117 31448,31449,31450,31451,31452,31453,31454,31455,31456,31457,31458,31459,
95118 31460,31461,31462,31463,31464,31465,31466,31467,31468,31469,31470,31471,
95119 31472,31473,31474,31475,31476,31477,31478,31479,31480,31481,31482,31483,
95120 31484,31485,31486,31487,31488,31489,31490,31491,31492,31493,31494,31495,
95121 31496,31497,31498,31499,31500,31501,31502,31503,31504,31505,31506,31507,
95122 31508,31509,31510,31511,31512,31513,31514,31515,31516,31517,31518,31519,
95123 31520,31521,31522,31523,31524,31525,31526,31527,31528,31529,31530,31531,
95124 31532,31533,31534,31535,31536,31537,31538,31539,31540,31541,31542,31543,
95125 31544,31545,31546,31547,31548,31549,31550,31551,31552,31553,31554,31555,
95126 31556,31557,31558,31559,31560,31561,31562,31563,31564,31565,31566,31567,
95127 31568,31569,31570,31571,31572,31573,31574,31575,31576,31577,31578,31579,
95128 31580,31581,31582,31583,31584,31585,31586,31587,31588,31589,31590,31591,
95129 31592,31593,31594,31595,31596,31597,31598,31599,31600,31601,31602,31603,
95130 31604,31605,31606,31607,31608,31609,31610,31611,31612,31613,31614,31615,
95131 31616,31617,31618,31619,31620,31621,31622,31623,31624,31625,31626,31627,
95132 31628,31629,31630,31631,31632,31633,31634,31635,31636,31637,31638,31639,
95133 31640,31641,31642,31643,31644,31645,31646,31647,31648,31649,31650,31651,
95134 31652,31653,31654,31655,31656,31657,31658,31659,31660,31661,31662,31663,
95135 31664,31665,31666,31667,31668,31669,31670,31671,31672,31673,31674,31675,
95136 31676,31677,31678,31679,31680,31681,31682,31683,31684,31685,31686,31687,
95137 31688,31689,31690,31691,31692,31693,31694,31695,31696,31697,31698,31699,
95138 31700,31701,31702,31703,31704,31705,31706,31707,31708,31709,31710,31711,
95139 31712,31713,31714,31715,31716,31717,31718,31719,31720,31721,31722,31723,
95140 31724,31725,31726,31727,31728,31729,31730,31731,31732,31733,31734,31735,
95141 31736,31737,31738,31739,31740,31741,31742,31743,31744,31745,31746,31747,
95142 31748,31749,31750,31751,31752,31753,31754,31755,31756,31757,31758,31759,
95143 31760,31761,31762,31763,31764,31765,31766,31767,31768,31769,31770,31771,
95144 31772,31773,31774,31775,31776,31777,31778,31779,31780,31781,31782,31783,
95145 31784,31785,31786,31787,31788,31789,31790,31791,31792,31793,31794,31795,
95146 31796,31797,31798,31799,31800,31801,31802,31803,31804,31805,31806,31807,
95147 31808,31809,31810,31811,31812,31813,31814,31815,31816,31817,31818,31819,
95148 31820,31821,31822,31823,31824,31825,31826,31827,31828,31829,31830,31831,
95149 31832,31833,31834,31835,31836,31837,31838,31839,31840,31841,31842,31843,
95150 31844,31845,31846,31847,31848,31849,31850,31851,31852,31853,31854,31855,
95151 31856,31857,31858,31859,31860,31861,31862,31863,31864,31865,31866,31867,
95152 31868,31869,31870,31871,31872,31873,31874,31875,31876,31877,31878,31879,
95153 31880,31881,31882,31883,31884,31885,31886,31887,31888,31889,31890,31891,
95154 31892,31893,31894,31895,31896,31897,31898,31899,31900,31901,31902,31903,
95155 31904,31905,31906,31907,31908,31909,31910,31911,31912,31913,31914,31915,
95156 31916,31917,31918,31919,31920,31921,31922,31923,31924,31925,31926,31927,
95157 31928,31929,31930,31931,31932,31933,31934,31935,31936,31937,31938,31939,
95158 31940,31941,31942,31943,31944,31945,31946,31947,31948,31949,31950,31951,
95159 31952,31953,31954,31955,31956,31957,31958,31959,31960,31961,31962,31963,
95160 31964,31965,31966,31967,31968,31969,31970,31971,31972,31973,31974,31975,
95161 31976,31977,31978,31979,31980,31981,31982,31983,31984,31985,31986,31987,
95162 31988,31989,31990,31991,31992,31993,31994,31995,31996,31997,31998,31999,
95163 32000,32001,32002,32003,32004,32005,32006,32007,32008,32009,32010,32011,
95164 32012,32013,32014,32015,32016,32017,32018,32019,32020,32021,32022,32023,
95165 32024,32025,32026,32027,32028,32029,32030,32031,32032,32033,32034,32035,
95166 32036,32037,32038,32039,32040,32041,32042,32043,32044,32045,32046,32047,
95167 32048,32049,32050,32051,32052,32053,32054,32055,32056,32057,32058,32059,
95168 32060,32061,32062,32063,32064,32065,32066,32067,32068,32069,32070,32071,
95169 32072,32073,32074,32075,32076,32077,32078,32079,32080,32081,32082,32083,
95170 32084,32085,32086,32087,32088,32089,32090,32091,32092,32093,32094,32095,
95171 32096,32097,32098,32099,32100,32101,32102,32103,32104,32105,32106,32107,
95172 32108,32109,32110,32111,32112,32113,32114,32115,32116,32117,32118,32119,
95173 32120,32121,32122,32123,32124,32125,32126,32127,32128,32129,32130,32131,
95174 32132,32133,32134,32135,32136,32137,32138,32139,32140,32141,32142,32143,
95175 32144,32145,32146,32147,32148,32149,32150,32151,32152,32153,32154,32155,
95176 32156,32157,32158,32159,32160,32161,32162,32163,32164,32165,32166,32167,
95177 32168,32169,32170,32171,32172,32173,32174,32175,32176,32177,32178,32179,
95178 32180,32181,32182,32183,32184,32185,32186,32187,32188,32189,32190,32191,
95179 32192,32193,32194,32195,32196,32197,32198,32199,32200,32201,32202,32203,
95180 32204,32205,32206,32207,32208,32209,32210,32211,32212,32213,32214,32215,
95181 32216,32217,32218,32219,32220,32221,32222,32223,32224,32225,32226,32227,
95182 32228,32229,32230,32231,32232,32233,32234,32235,32236,32237,32238,32239,
95183 32240,32241,32242,32243,32244,32245,32246,32247,32248,32249,32250,32251,
95184 32252,32253,32254,32255,32256,32257,32258,32259,32260,32261,32262,32263,
95185 32264,32265,32266,32267,32268,32269,32270,32271,32272,32273,32274,32275,
95186 32276,32277,32278,32279,32280,32281,32282,32283,32284,32285,32286,32287,
95187 32288,32289,32290,32291,32292,32293,32294,32295,32296,32297,32298,32299,
95188 32300,32301,32302,32303,32304,32305,32306,32307,32308,32309,32310,32311,
95189 32312,32313,32314,32315,32316,32317,32318,32319,32320,32321,32322,32323,
95190 32324,32325,32326,32327,32328,32329,32330,32331,32332,32333,32334,32335,
95191 32336,32337,32338,32339,32340,32341,32342,32343,32344,32345,32346,32347,
95192 32348,32349,32350,32351,32352,32353,32354,32355,32356,32357,32358,32359,
95193 32360,32361,32362,32363,32364,32365,32366,32367,32368,32369,32370,32371,
95194 32372,32373,32374,32375,32376,32377,32378,32379,32380,32381,32382,32383,
95195 32384,32385,32386,32387,32388,32389,32390,32391,32392,32393,32394,32395,
95196 32396,32397,32398,32399,32400,32401,32402,32403,32404,32405,32406,32407,
95197 32408,32409,32410,32411,32412,32413,32414,32415,32416,32417,32418,32419,
95198 32420,32421,32422,32423,32424,32425,32426,32427,32428,32429,32430,32431,
95199 32432,32433,32434,32435,32436,32437,32438,32439,32440,32441,32442,32443,
95200 32444,32445,32446,32447,32448,32449,32450,32451,32452,32453,32454,32455,
95201 32456,32457,32458,32459,32460,32461,32462,32463,32464,32465,32466,32467,
95202 32468,32469,32470,32471,32472,32473,32474,32475,32476,32477,32478,32479,
95203 32480,32481,32482,32483,32484,32485,32486,32487,32488,32489,32490,32491,
95204 32492,32493,32494,32495,32496,32497,32498,32499,32500,32501,32502,32503,
95205 32504,32505,32506,32507,32508,32509,32510,32511,32512,32513,32514,32515,
95206 32516,32517,32518,32519,32520,32521,32522,32523,32524,32525,32526,32527,
95207 32528,32529,32530,32531,32532,32533,32534,32535,32536,32537,32538,32539,
95208 32540,32541,32542,32543,32544,32545,32546,32547,32548,32549,32550,32551,
95209 32552,32553,32554,32555,32556,32557,32558,32559,32560,32561,32562,32563,
95210 32564,32565,32566,32567,32568,32569,32570,32571,32572,32573,32574,32575,
95211 32576,32577,32578,32579,32580,32581,32582,32583,32584,32585,32586,32587,
95212 32588,32589,32590,32591,32592,32593,32594,32595,32596,32597,32598,32599,
95213 32600,32601,32602,32603,32604,32605,32606,32607,32608,32609,32610,32611,
95214 32612,32613,32614,32615,32616,32617,32618,32619,32620,32621,32622,32623,
95215 32624,32625,32626,32627,32628,32629,32630,32631,32632,32633,32634,32635,
95216 32636,32637,32638,32639,32640,32641,32642,32643,32644,32645,32646,32647,
95217 32648,32649,32650,32651,32652,32653,32654,32655,32656,32657,32658,32659,
95218 32660,32661,32662,32663,32664,32665,32666,32667,32668,32669,32670,32671,
95219 32672,32673,32674,32675,32676,32677,32678,32679,32680,32681,32682,32683,
95220 32684,32685,32686,32687,32688,32689,32690,32691,32692,32693,32694,32695,
95221 32696,32697,32698,32699,32700,32701,32702,32703,32704,32705,32706,32707,
95222 32708,32709,32710,32711,32712,32713,32714,32715,32716,32717,32718,32719,
95223 32720,32721,32722,32723,32724,32725,32726,32727,32728,32729,32730,32731,
95224 32732,32733,32734,32735,32736,32737,32738,32739,32740,32741,32742,32743,
95225 32744,32745,32746,32747,32748,32749,32750,32751,32752,32753,32754,32755,
95226 32756,32757,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,
95227 32768L,32769L,32770L,32771L,32772L,32773L,32774L,32775L,32776L,32777L,
95228 32778L,32779L,32780L,32781L,32782L,32783L,32784L,32785L,32786L,32787L,
95229 32788L,32789L,32790L,32791L,32792L,32793L,32794L,32795L,32796L,32797L,
95230 32798L,32799L,32800L,32801L,32802L,32803L,32804L,32805L,32806L,32807L,
95231 32808L,32809L,32810L,32811L,32812L,32813L,32814L,32815L,32816L,32817L,
95232 32818L,32819L,32820L,32821L,32822L,32823L,32824L,32825L,32826L,32827L,
95233 32828L,32829L,32830L,32831L,32832L,32833L,32834L,32835L,32836L,32837L,
95234 32838L,32839L,32840L,32841L,32842L,32843L,32844L,32845L,32846L,32847L,
95235 32848L,32849L,32850L,32851L,32852L,32853L,32854L,32855L,32856L,32857L,
95236 32858L,32859L,32860L,32861L,32862L,32863L,32864L,32865L,32866L,32867L,
95237 32868L,32869L,32870L,32871L,32872L,32873L,32874L,32875L,32876L,32877L,
95238 32878L,32879L,32880L,32881L,32882L,32883L,32884L,32885L,32886L,32887L,
95239 32888L,32889L,32890L,32891L,32892L,32893L,32894L,32895L,32896L,32897L,
95240 32898L,32899L,32900L,32901L,32902L,32903L,32904L,32905L,32906L,32907L,
95241 32908L,32909L,32910L,32911L,32912L,32913L,32914L,32915L,32916L,32917L,
95242 32918L,32919L,32920L,32921L,32922L,32923L,32924L,32925L,32926L,32927L,
95243 32928L,32929L,32930L,32931L,32932L,32933L,32934L,32935L,32936L,32937L,
95244 32938L,32939L,32940L,32941L,32942L,32943L,32944L,32945L,32946L,32947L,
95245 32948L,32949L,32950L,32951L,32952L,32953L,32954L,32955L,32956L,32957L,
95246 32958L,32959L,32960L,32961L,32962L,32963L,32964L,32965L,32966L,32967L,
95247 32968L,32969L,32970L,32971L,32972L,32973L,32974L,32975L,32976L,32977L,
95248 32978L,32979L,32980L,32981L,32982L,32983L,32984L,32985L,32986L,32987L,
95249 32988L,32989L,32990L,32991L,32992L,32993L,32994L,32995L,32996L,32997L,
95250 32998L,32999L,33000L,33001L,33002L,33003L,33004L,33005L,33006L,33007L,
95251 33008L,33009L,33010L,33011L,33012L,33013L,33014L,33015L,33016L,33017L,
95252 33018L,33019L,33020L,33021L,33022L,33023L,33024L,33025L,33026L,33027L,
95253 33028L,33029L,33030L,33031L,33032L,33033L,33034L,33035L,33036L,33037L,
95254 33038L,33039L,33040L,33041L,33042L,33043L,33044L,33045L,33046L,33047L,
95255 33048L,33049L,33050L,33051L,33052L,33053L,33054L,33055L,33056L,33057L,
95256 33058L,33059L,33060L,33061L,33062L,33063L,33064L,33065L,33066L,33067L,
95257 33068L,33069L,33070L,33071L,33072L,33073L,33074L,33075L,33076L,33077L,
95258 33078L,33079L,33080L,33081L,33082L,33083L,33084L,33085L,33086L,33087L,
95259 33088L,33089L,33090L,33091L,33092L,33093L,33094L,33095L,33096L,33097L,
95260 33098L,33099L,33100L,33101L,33102L,33103L,33104L,33105L,33106L,33107L,
95261 33108L,33109L,33110L,33111L,33112L,33113L,33114L,33115L,33116L,33117L,
95262 33118L,33119L,33120L,33121L,33122L,33123L,33124L,33125L,33126L,33127L,
95263 33128L,33129L,33130L,33131L,33132L,33133L,33134L,33135L,33136L,33137L,
95264 33138L,33139L,33140L,33141L,33142L,33143L,33144L,33145L,33146L,33147L,
95265 33148L,33149L,33150L,33151L,33152L,33153L,33154L,33155L,33156L,33157L,
95266 33158L,33159L,33160L,33161L,33162L,33163L,33164L,33165L,33166L,33167L,
95267 33168L,33169L,33170L,33171L,33172L,33173L,33174L,33175L,33176L,33177L,
95268 33178L,33179L,33180L,33181L,33182L,33183L,33184L,33185L,33186L,33187L,
95269 33188L,33189L,33190L,33191L,33192L,33193L,33194L,33195L,33196L,33197L,
95270 33198L,33199L,33200L,33201L,33202L,33203L,33204L,33205L,33206L,33207L,
95271 33208L,33209L,33210L,33211L,33212L,33213L,33214L,33215L,33216L,33217L,
95272 33218L,33219L,33220L,33221L,33222L,33223L,33224L,33225L,33226L,33227L,
95273 33228L,33229L,33230L,33231L,33232L,33233L,33234L,33235L,33236L,33237L,
95274 33238L,33239L,33240L,33241L,33242L,33243L,33244L,33245L,33246L,33247L,
95275 33248L,33249L,33250L,33251L,33252L,33253L,33254L,33255L,33256L,33257L,
95276 33258L,33259L,33260L,33261L,33262L,33263L,33264L,33265L,33266L,33267L,
95277 33268L,33269L,33270L,33271L,33272L,33273L,33274L,33275L,33276L,33277L,
95278 33278L,33279L,33280L,33281L,33282L,33283L,33284L,33285L,33286L,33287L,
95279 33288L,33289L,33290L,33291L,33292L,33293L,33294L,33295L,33296L,33297L,
95280 33298L,33299L,33300L,33301L,33302L,33303L,33304L,33305L,33306L,33307L,
95281 33308L,33309L,33310L,33311L,33312L,33313L,33314L,33315L,33316L,33317L,
95282 33318L,33319L,33320L,33321L,33322L,33323L,33324L,33325L,33326L,33327L,
95283 33328L,33329L,33330L,33331L,33332L,33333L,33334L,33335L,33336L,33337L,
95284 33338L,33339L,33340L,33341L,33342L,33343L,33344L,33345L,33346L,33347L,
95285 33348L,33349L,33350L,33351L,33352L,33353L,33354L,33355L,33356L,33357L,
95286 33358L,33359L,33360L,33361L,33362L,33363L,33364L,33365L,33366L,33367L,
95287 33368L,33369L,33370L,33371L,33372L,33373L,33374L,33375L,33376L,33377L,
95288 33378L,33379L,33380L,33381L,33382L,33383L,33384L,33385L,33386L,33387L,
95289 33388L,33389L,33390L,33391L,33392L,33393L,33394L,33395L,33396L,33397L,
95290 33398L,33399L,33400L,33401L,33402L,33403L,33404L,33405L,33406L,33407L,
95291 33408L,33409L,33410L,33411L,33412L,33413L,33414L,33415L,33416L,33417L,
95292 33418L,33419L,33420L,33421L,33422L,33423L,33424L,33425L,33426L,33427L,
95293 33428L,33429L,33430L,33431L,33432L,33433L,33434L,33435L,33436L,33437L,
95294 33438L,33439L,33440L,33441L,33442L,33443L,33444L,33445L,33446L,33447L,
95295 33448L,33449L,33450L,33451L,33452L,33453L,33454L,33455L,33456L,33457L,
95296 33458L,33459L,33460L,33461L,33462L,33463L,33464L,33465L,33466L,33467L,
95297 33468L,33469L,33470L,33471L,33472L,33473L,33474L,33475L,33476L,33477L,
95298 33478L,33479L,33480L,33481L,33482L,33483L,33484L,33485L,33486L,33487L,
95299 33488L,33489L,33490L,33491L,33492L,33493L,33494L,33495L,33496L,33497L,
95300 33498L,33499L,33500L,33501L,33502L,33503L,33504L,33505L,33506L,33507L,
95301 33508L,33509L,33510L,33511L,33512L,33513L,33514L,33515L,33516L,33517L,
95302 33518L,33519L,33520L,33521L,33522L,33523L,33524L,33525L,33526L,33527L,
95303 33528L,33529L,33530L,33531L,33532L,33533L,33534L,33535L,33536L,33537L,
95304 33538L,33539L,33540L,33541L,33542L,33543L,33544L,33545L,33546L,33547L,
95305 33548L,33549L,33550L,33551L,33552L,33553L,33554L,33555L,33556L,33557L,
95306 33558L,33559L,33560L,33561L,33562L,33563L,33564L,33565L,33566L,33567L,
95307 33568L,33569L,33570L,33571L,33572L,33573L,33574L,33575L,33576L,33577L,
95308 33578L,33579L,33580L,33581L,33582L,33583L,33584L,33585L,33586L,33587L,
95309 33588L,33589L,33590L,33591L,33592L,33593L,33594L,33595L,33596L,33597L,
95310 33598L,33599L,33600L,33601L,33602L,33603L,33604L,33605L,33606L,33607L,
95311 33608L,33609L,33610L,33611L,33612L,33613L,33614L,33615L,33616L,33617L,
95312 33618L,33619L,33620L,33621L,33622L,33623L,33624L,33625L,33626L,33627L,
95313 33628L,33629L,33630L,33631L,33632L,33633L,33634L,33635L,33636L,33637L,
95314 33638L,33639L,33640L,33641L,33642L,33643L,33644L,33645L,33646L,33647L,
95315 33648L,33649L,33650L,33651L,33652L,33653L,33654L,33655L,33656L,33657L,
95316 33658L,33659L,33660L,33661L,33662L,33663L,33664L,33665L,33666L,33667L,
95317 33668L,33669L,33670L,33671L,33672L,33673L,33674L,33675L,33676L,33677L,
95318 33678L,33679L,33680L,33681L,33682L,33683L,33684L,33685L,33686L,33687L,
95319 33688L,33689L,33690L,33691L,33692L,33693L,33694L,33695L,33696L,33697L,
95320 33698L,33699L,33700L,33701L,33702L,33703L,33704L,33705L,33706L,33707L,
95321 33708L,33709L,33710L,33711L,33712L,33713L,33714L,33715L,33716L,33717L,
95322 33718L,33719L,33720L,33721L,33722L,33723L,33724L,33725L,33726L,33727L,
95323 33728L,33729L,33730L,33731L,33732L,33733L,33734L,33735L,33736L,33737L,
95324 33738L,33739L,33740L,33741L,33742L,33743L,33744L,33745L,33746L,33747L,
95325 33748L,33749L,33750L,33751L,33752L,33753L,33754L,33755L,33756L,33757L,
95326 33758L,33759L,33760L,33761L,33762L,33763L,33764L,33765L,33766L,33767L,
95327 33768L,33769L,33770L,33771L,33772L,33773L,33774L,33775L,33776L,33777L,
95328 33778L,33779L,33780L,33781L,33782L,33783L,33784L,33785L,33786L,33787L,
95329 33788L,33789L,33790L,33791L,33792L,33793L,33794L,33795L,33796L,33797L,
95330 33798L,33799L,33800L,33801L,33802L,33803L,33804L,33805L,33806L,33807L,
95331 33808L,33809L,33810L,33811L,33812L,33813L,33814L,33815L,33816L,33817L,
95332 33818L,33819L,33820L,33821L,33822L,33823L,33824L,33825L,33826L,33827L,
95333 33828L,33829L,33830L,33831L,33832L,33833L,33834L,33835L,33836L,33837L,
95334 33838L,33839L,33840L,33841L,33842L,33843L,33844L,33845L,33846L,33847L,
95335 33848L,33849L,33850L,33851L,33852L,33853L,33854L,33855L,33856L,33857L,
95336 33858L,33859L,33860L,33861L,33862L,33863L,33864L,33865L,33866L,33867L,
95337 33868L,33869L,33870L,33871L,33872L,33873L,33874L,33875L,33876L,33877L,
95338 33878L,33879L,33880L,33881L,33882L,33883L,33884L,33885L,33886L,33887L,
95339 33888L,33889L,33890L,33891L,33892L,33893L,33894L,33895L,33896L,33897L,
95340 33898L,33899L,33900L,33901L,33902L,33903L,33904L,33905L,33906L,33907L,
95341 33908L,33909L,33910L,33911L,33912L,33913L,33914L,33915L,33916L,33917L,
95342 33918L,33919L,33920L,33921L,33922L,33923L,33924L,33925L,33926L,33927L,
95343 33928L,33929L,33930L,33931L,33932L,33933L,33934L,33935L,33936L,33937L,
95344 33938L,33939L,33940L,33941L,33942L,33943L,33944L,33945L,33946L,33947L,
95345 33948L,33949L,33950L,33951L,33952L,33953L,33954L,33955L,33956L,33957L,
95346 33958L,33959L,33960L,33961L,33962L,33963L,33964L,33965L,33966L,33967L,
95347 33968L,33969L,33970L,33971L,33972L,33973L,33974L,33975L,33976L,33977L,
95348 33978L,33979L,33980L,33981L,33982L,33983L,33984L,33985L,33986L,33987L,
95349 33988L,33989L,33990L,33991L,33992L,33993L,33994L,33995L,33996L,33997L,
95350 33998L,33999L,34000L,34001L,34002L,34003L,34004L,34005L,34006L,34007L,
95351 34008L,34009L,34010L,34011L,34012L,34013L,34014L,34015L,34016L,34017L,
95352 34018L,34019L,34020L,34021L,34022L,34023L,34024L,34025L,34026L,34027L,
95353 34028L,34029L,34030L,34031L,34032L,34033L,34034L,34035L,34036L,34037L,
95354 34038L,34039L,34040L,34041L,34042L,34043L,34044L,34045L,34046L,34047L,
95355 34048L,34049L,34050L,34051L,34052L,34053L,34054L,34055L,34056L,34057L,
95356 34058L,34059L,34060L,34061L,34062L,34063L,34064L,34065L,34066L,34067L,
95357 34068L,34069L,34070L,34071L,34072L,34073L,34074L,34075L,34076L,34077L,
95358 34078L,34079L,34080L,34081L,34082L,34083L,34084L,34085L,34086L,34087L,
95359 34088L,34089L,34090L,34091L,34092L,34093L,34094L,34095L,34096L,34097L,
95360 34098L,34099L,34100L,34101L,34102L,34103L,34104L,34105L,34106L,34107L,
95361 34108L,34109L,34110L,34111L,34112L,34113L,34114L,34115L,34116L,34117L,
95362 34118L,34119L,34120L,34121L,34122L,34123L,34124L,34125L,34126L,34127L,
95363 34128L,34129L,34130L,34131L,34132L,34133L,34134L,34135L,34136L,34137L,
95364 34138L,34139L,34140L,34141L,34142L,34143L,34144L,34145L,34146L,34147L,
95365 34148L,34149L,34150L,34151L,34152L,34153L,34154L,34155L,34156L,34157L,
95366 34158L,34159L,34160L,34161L,34162L,34163L,34164L,34165L,34166L,34167L,
95367 34168L,34169L,34170L,34171L,34172L,34173L,34174L,34175L,34176L,34177L,
95368 34178L,34179L,34180L,34181L,34182L,34183L,34184L,34185L,34186L,34187L,
95369 34188L,34189L,34190L,34191L,34192L,34193L,34194L,34195L,34196L,34197L,
95370 34198L,34199L,34200L,34201L,34202L,34203L,34204L,34205L,34206L,34207L,
95371 34208L,34209L,34210L,34211L,34212L,34213L,34214L,34215L,34216L,34217L,
95372 34218L,34219L,34220L,34221L,34222L,34223L,34224L,34225L,34226L,34227L,
95373 34228L,34229L,34230L,34231L,34232L,34233L,34234L,34235L,34236L,34237L,
95374 34238L,34239L,34240L,34241L,34242L,34243L,34244L,34245L,34246L,34247L,
95375 34248L,34249L,34250L,34251L,34252L,34253L,34254L,34255L,34256L,34257L,
95376 34258L,34259L,34260L,34261L,34262L,34263L,34264L,34265L,34266L,34267L,
95377 34268L,34269L,34270L,34271L,34272L,34273L,34274L,34275L,34276L,34277L,
95378 34278L,34279L,34280L,34281L,34282L,34283L,34284L,34285L,34286L,34287L,
95379 34288L,34289L,34290L,34291L,34292L,34293L,34294L,34295L,34296L,34297L,
95380 34298L,34299L,34300L,34301L,34302L,34303L,34304L,34305L,34306L,34307L,
95381 34308L,34309L,34310L,34311L,34312L,34313L,34314L,34315L,34316L,34317L,
95382 34318L,34319L,34320L,34321L,34322L,34323L,34324L,34325L,34326L,34327L,
95383 34328L,34329L,34330L,34331L,34332L,34333L,34334L,34335L,34336L,34337L,
95384 34338L,34339L,34340L,34341L,34342L,34343L,34344L,34345L,34346L,34347L,
95385 34348L,34349L,34350L,34351L,34352L,34353L,34354L,34355L,34356L,34357L,
95386 34358L,34359L,34360L,34361L,34362L,34363L,34364L,34365L,34366L,34367L,
95387 34368L,34369L,34370L,34371L,34372L,34373L,34374L,34375L,34376L,34377L,
95388 34378L,34379L,34380L,34381L,34382L,34383L,34384L,34385L,34386L,34387L,
95389 34388L,34389L,34390L,34391L,34392L,34393L,34394L,34395L,34396L,34397L,
95390 34398L,34399L,34400L,34401L,34402L,34403L,34404L,34405L,34406L,34407L,
95391 34408L,34409L,34410L,34411L,34412L,34413L,34414L,34415L,34416L,34417L,
95392 34418L,34419L,34420L,34421L,34422L,34423L,34424L,34425L,34426L,34427L,
95393 34428L,34429L,34430L,34431L,34432L,34433L,34434L,34435L,34436L,34437L,
95394 34438L,34439L,34440L,34441L,34442L,34443L,34444L,34445L,34446L,34447L,
95395 34448L,34449L,34450L,34451L,34452L,34453L,34454L,34455L,34456L,34457L,
95396 34458L,34459L,34460L,34461L,34462L,34463L,34464L,34465L,34466L,34467L,
95397 34468L,34469L,34470L,34471L,34472L,34473L,34474L,34475L,34476L,34477L,
95398 34478L,34479L,34480L,34481L,34482L,34483L,34484L,34485L,34486L,34487L,
95399 34488L,34489L,34490L,34491L,34492L,34493L,34494L,34495L,34496L,34497L,
95400 34498L,34499L,34500L,34501L,34502L,34503L,34504L,34505L,34506L,34507L,
95401 34508L,34509L,34510L,34511L,34512L,34513L,34514L,34515L,34516L,34517L,
95402 34518L,34519L,34520L,34521L,34522L,34523L,34524L,34525L,34526L,34527L,
95403 34528L,34529L,34530L,34531L,34532L,34533L,34534L,34535L,34536L,34537L,
95404 34538L,34539L,34540L,34541L,34542L,34543L,34544L,34545L,34546L,34547L,
95405 34548L,34549L,34550L,34551L,34552L,34553L,34554L,34555L,34556L,34557L,
95406 34558L,34559L,34560L,34561L,34562L,34563L,34564L,34565L,34566L,34567L,
95407 34568L,34569L,34570L,34571L,34572L,34573L,34574L,34575L,34576L,34577L,
95408 34578L,34579L,34580L,34581L,34582L,34583L,34584L,34585L,34586L,34587L,
95409 34588L,34589L,34590L,34591L,34592L,34593L,34594L,34595L,34596L,34597L,
95410 34598L,34599L,34600L,34601L,34602L,34603L,34604L,34605L,34606L,34607L,
95411 34608L,34609L,34610L,34611L,34612L,34613L,34614L,34615L,34616L,34617L,
95412 34618L,34619L,34620L,34621L,34622L,34623L,34624L,34625L,34626L,34627L,
95413 34628L,34629L,34630L,34631L,34632L,34633L,34634L,34635L,34636L,34637L,
95414 34638L,34639L,34640L,34641L,34642L,34643L,34644L,34645L,34646L,34647L,
95415 34648L,34649L,34650L,34651L,34652L,34653L,34654L,34655L,34656L,34657L,
95416 34658L,34659L,34660L,34661L,34662L,34663L,34664L,34665L,34666L,34667L,
95417 34668L,34669L,34670L,34671L,34672L,34673L,34674L,34675L,34676L,34677L,
95418 34678L,34679L,34680L,34681L,34682L,34683L,34684L,34685L,34686L,34687L,
95419 34688L,34689L,34690L,34691L,34692L,34693L,34694L,34695L,34696L,34697L,
95420 34698L,34699L,34700L,34701L,34702L,34703L,34704L,34705L,34706L,34707L,
95421 34708L,34709L,34710L,34711L,34712L,34713L,34714L,34715L,34716L,34717L,
95422 34718L,34719L,34720L,34721L,34722L,34723L,34724L,34725L,34726L,34727L,
95423 34728L,34729L,34730L,34731L,34732L,34733L,34734L,34735L,34736L,34737L,
95424 34738L,34739L,34740L,34741L,34742L,34743L,34744L,34745L,34746L,34747L,
95425 34748L,34749L,34750L,34751L,34752L,34753L,34754L,34755L,34756L,34757L,
95426 34758L,34759L,34760L,34761L,34762L,34763L,34764L,34765L,34766L,34767L,
95427 34768L,34769L,34770L,34771L,34772L,34773L,34774L,34775L,34776L,34777L,
95428 34778L,34779L,34780L,34781L,34782L,34783L,34784L,34785L,34786L,34787L,
95429 34788L,34789L,34790L,34791L,34792L,34793L,34794L,34795L,34796L,34797L,
95430 34798L,34799L,34800L,34801L,34802L,34803L,34804L,34805L,34806L,34807L,
95431 34808L,34809L,34810L,34811L,34812L,34813L,34814L,34815L,34816L,34817L,
95432 34818L,34819L,34820L,34821L,34822L,34823L,34824L,34825L,34826L,34827L,
95433 34828L,34829L,34830L,34831L,34832L,34833L,34834L,34835L,34836L,34837L,
95434 34838L,34839L,34840L,34841L,34842L,34843L,34844L,34845L,34846L,34847L,
95435 34848L,34849L,34850L,34851L,34852L,34853L,34854L,34855L,34856L,34857L,
95436 34858L,34859L,34860L,34861L,34862L,34863L,34864L,34865L,34866L,34867L,
95437 34868L,34869L,34870L,34871L,34872L,34873L,34874L,34875L,34876L,34877L,
95438 34878L,34879L,34880L,34881L,34882L,34883L,34884L,34885L,34886L,34887L,
95439 34888L,34889L,34890L,34891L,34892L,34893L,34894L,34895L,34896L,34897L,
95440 34898L,34899L,34900L,34901L,34902L,34903L,34904L,34905L,34906L,34907L,
95441 34908L,34909L,34910L,34911L,34912L,34913L,34914L,34915L,34916L,34917L,
95442 34918L,34919L,34920L,34921L,34922L,34923L,34924L,34925L,34926L,34927L,
95443 34928L,34929L,34930L,34931L,34932L,34933L,34934L,34935L,34936L,34937L,
95444 34938L,34939L,34940L,34941L,34942L,34943L,34944L,34945L,34946L,34947L,
95445 34948L,34949L,34950L,34951L,34952L,34953L,34954L,34955L,34956L,34957L,
95446 34958L,34959L,34960L,34961L,34962L,34963L,34964L,34965L,34966L,34967L,
95447 34968L,34969L,34970L,34971L,34972L,34973L,34974L,34975L,34976L,34977L,
95448 34978L,34979L,34980L,34981L,34982L,34983L,34984L,34985L,34986L,34987L,
95449 34988L,34989L,34990L,34991L,34992L,34993L,34994L,34995L,34996L,34997L,
95450 34998L,34999L,35000L,35001L,35002L,35003L,35004L,35005L,35006L,35007L,
95451 35008L,35009L,35010L,35011L,35012L,35013L,35014L,35015L,35016L,35017L,
95452 35018L,35019L,35020L,35021L,35022L,35023L,35024L,35025L,35026L,35027L,
95453 35028L,35029L,35030L,35031L,35032L,35033L,35034L,35035L,35036L,35037L,
95454 35038L,35039L,35040L,35041L,35042L,35043L,35044L,35045L,35046L,35047L,
95455 35048L,35049L,35050L,35051L,35052L,35053L,35054L,35055L,35056L,35057L,
95456 35058L,35059L,35060L,35061L,35062L,35063L,35064L,35065L,35066L,35067L,
95457 35068L,35069L,35070L,35071L,35072L,35073L,35074L,35075L,35076L,35077L,
95458 35078L,35079L,35080L,35081L,35082L,35083L,35084L,35085L,35086L,35087L,
95459 35088L,35089L,35090L,35091L,35092L,35093L,35094L,35095L,35096L,35097L,
95460 35098L,35099L,35100L,35101L,35102L,35103L,35104L,35105L,35106L,35107L,
95461 35108L,35109L,35110L,35111L,35112L,35113L,35114L,35115L,35116L,35117L,
95462 35118L,35119L,35120L,35121L,35122L,35123L,35124L,35125L,35126L,35127L,
95463 35128L,35129L,35130L,35131L,35132L,35133L,35134L,35135L,35136L,35137L,
95464 35138L,35139L,35140L,35141L,35142L,35143L,35144L,35145L,35146L,35147L,
95465 35148L,35149L,35150L,35151L,35152L,35153L,35154L,35155L,35156L,35157L,
95466 35158L,35159L,35160L,35161L,35162L,35163L,35164L,35165L,35166L,35167L,
95467 35168L,35169L,35170L,35171L,35172L,35173L,35174L,35175L,35176L,35177L,
95468 35178L,35179L,35180L,35181L,35182L,35183L,35184L,35185L,35186L,35187L,
95469 35188L,35189L,35190L,35191L,35192L,35193L,35194L,35195L,35196L,35197L,
95470 35198L,35199L,35200L,35201L,35202L,35203L,35204L,35205L,35206L,35207L,
95471 35208L,35209L,35210L,35211L,35212L,35213L,35214L,35215L,35216L,35217L,
95472 35218L,35219L,35220L,35221L,35222L,35223L,35224L,35225L,35226L,35227L,
95473 35228L,35229L,35230L,35231L,35232L,35233L,35234L,35235L,35236L,35237L,
95474 35238L,35239L,35240L,35241L,35242L,35243L,35244L,35245L,35246L,35247L,
95475 35248L,35249L,35250L,35251L,35252L,35253L,35254L,35255L,35256L,35257L,
95476 35258L,35259L,35260L,35261L,35262L,35263L,35264L,35265L,35266L,35267L,
95477 35268L,35269L,35270L,35271L,35272L,35273L,35274L,35275L,35276L,35277L,
95478 35278L,35279L,35280L,35281L,35282L,35283L,35284L,35285L,35286L,35287L,
95479 35288L,35289L,35290L,35291L,35292L,35293L,35294L,35295L,35296L,35297L,
95480 35298L,35299L,35300L,35301L,35302L,35303L,35304L,35305L,35306L,35307L,
95481 35308L,35309L,35310L,35311L,35312L,35313L,35314L,35315L,35316L,35317L,
95482 35318L,35319L,35320L,35321L,35322L,35323L,35324L,35325L,35326L,35327L,
95483 35328L,35329L,35330L,35331L,35332L,35333L,35334L,35335L,35336L,35337L,
95484 35338L,35339L,35340L,35341L,35342L,35343L,35344L,35345L,35346L,35347L,
95485 35348L,35349L,35350L,35351L,35352L,35353L,35354L,35355L,35356L,35357L,
95486 35358L,35359L,35360L,35361L,35362L,35363L,35364L,35365L,35366L,35367L,
95487 35368L,35369L,35370L,35371L,35372L,35373L,35374L,35375L,35376L,35377L,
95488 35378L,35379L,35380L,35381L,35382L,35383L,35384L,35385L,35386L,35387L,
95489 35388L,35389L,35390L,35391L,35392L,35393L,35394L,35395L,35396L,35397L,
95490 35398L,35399L,35400L,35401L,35402L,35403L,35404L,35405L,35406L,35407L,
95491 35408L,35409L,35410L,35411L,35412L,35413L,35414L,35415L,35416L,35417L,
95492 35418L,35419L,35420L,35421L,35422L,35423L,35424L,35425L,35426L,35427L,
95493 35428L,35429L,35430L,35431L,35432L,35433L,35434L,35435L,35436L,35437L,
95494 35438L,35439L,35440L,35441L,35442L,35443L,35444L,35445L,35446L,35447L,
95495 35448L,35449L,35450L,35451L,35452L,35453L,35454L,35455L,35456L,35457L,
95496 35458L,35459L,35460L,35461L,35462L,35463L,35464L,35465L,35466L,35467L,
95497 35468L,35469L,35470L,35471L,35472L,35473L,35474L,35475L,35476L,35477L,
95498 35478L,35479L,35480L,35481L,35482L,35483L,35484L,35485L,35486L,35487L,
95499 35488L,35489L,35490L,35491L,35492L,35493L,35494L,35495L,35496L,35497L,
95500 35498L,35499L,35500L,35501L,35502L,35503L,35504L,35505L,35506L,35507L,
95501 35508L,35509L,35510L,35511L,35512L,35513L,35514L,35515L,35516L,35517L,
95502 35518L,35519L,35520L,35521L,35522L,35523L,35524L,35525L,35526L,35527L,
95503 35528L,35529L,35530L,35531L,35532L,35533L,35534L,35535L,35536L,35537L,
95504 35538L,35539L,35540L,35541L,35542L,35543L,35544L,35545L,35546L,35547L,
95505 35548L,35549L,35550L,35551L,35552L,35553L,35554L,35555L,35556L,35557L,
95506 35558L,35559L,35560L,35561L,35562L,35563L,35564L,35565L,35566L,35567L,
95507 35568L,35569L,35570L,35571L,35572L,35573L,35574L,35575L,35576L,35577L,
95508 35578L,35579L,35580L,35581L,35582L,35583L,35584L,35585L,35586L,35587L,
95509 35588L,35589L,35590L,35591L,35592L,35593L,35594L,35595L,35596L,35597L,
95510 35598L,35599L,35600L,35601L,35602L,35603L,35604L,35605L,35606L,35607L,
95511 35608L,35609L,35610L,35611L,35612L,35613L,35614L,35615L,35616L,35617L,
95512 35618L,35619L,35620L,35621L,35622L,35623L,35624L,35625L,35626L,35627L,
95513 35628L,35629L,35630L,35631L,35632L,35633L,35634L,35635L,35636L,35637L,
95514 35638L,35639L,35640L,35641L,35642L,35643L,35644L,35645L,35646L,35647L,
95515 35648L,35649L,35650L,35651L,35652L,35653L,35654L,35655L,35656L,35657L,
95516 35658L,35659L,35660L,35661L,35662L,35663L,35664L,35665L,35666L,35667L,
95517 35668L,35669L,35670L,35671L,35672L,35673L,35674L,35675L,35676L,35677L,
95518 35678L,35679L,35680L,35681L,35682L,35683L,35684L,35685L,35686L,35687L,
95519 35688L,35689L,35690L,35691L,35692L,35693L,35694L,35695L,35696L,35697L,
95520 35698L,35699L,35700L,35701L,35702L,35703L,35704L,35705L,35706L,35707L,
95521 35708L,35709L,35710L,35711L,35712L,35713L,35714L,35715L,35716L,35717L,
95522 35718L,35719L,35720L,35721L,35722L,35723L,35724L,35725L,35726L,35727L,
95523 35728L,35729L,35730L,35731L,35732L,35733L,35734L,35735L,35736L,35737L,
95524 35738L,35739L,35740L,35741L,35742L,35743L,35744L,35745L,35746L,35747L,
95525 35748L,35749L,35750L,35751L,35752L,35753L,35754L,35755L,35756L,35757L,
95526 35758L,35759L,35760L,35761L,35762L,35763L,35764L,35765L,35766L,35767L,
95527 35768L,35769L,35770L,35771L,35772L,35773L,35774L,35775L,35776L,35777L,
95528 35778L,35779L,35780L,35781L,35782L,35783L,35784L,35785L,35786L,35787L,
95529 35788L,35789L,35790L,35791L,35792L,35793L,35794L,35795L,35796L,35797L,
95530 35798L,35799L,35800L,35801L,35802L,35803L,35804L,35805L,35806L,35807L,
95531 35808L,35809L,35810L,35811L,35812L,35813L,35814L,35815L,35816L,35817L,
95532 35818L,35819L,35820L,35821L,35822L,35823L,35824L,35825L,35826L,35827L,
95533 35828L,35829L,35830L,35831L,35832L,35833L,35834L,35835L,35836L,35837L,
95534 35838L,35839L,35840L,35841L,35842L,35843L,35844L,35845L,35846L,35847L,
95535 35848L,35849L,35850L,35851L,35852L,35853L,35854L,35855L,35856L,35857L,
95536 35858L,35859L,35860L,35861L,35862L,35863L,35864L,35865L,35866L,35867L,
95537 35868L,35869L,35870L,35871L,35872L,35873L,35874L,35875L,35876L,35877L,
95538 35878L,35879L,35880L,35881L,35882L,35883L,35884L,35885L,35886L,35887L,
95539 35888L,35889L,35890L,35891L,35892L,35893L,35894L,35895L,35896L,35897L,
95540 35898L,35899L,35900L,35901L,35902L,35903L,35904L,35905L,35906L,35907L,
95541 35908L,35909L,35910L,35911L,35912L,35913L,35914L,35915L,35916L,35917L,
95542 35918L,35919L,35920L,35921L,35922L,35923L,35924L,35925L,35926L,35927L,
95543 35928L,35929L,35930L,35931L,35932L,35933L,35934L,35935L,35936L,35937L,
95544 35938L,35939L,35940L,35941L,35942L,35943L,35944L,35945L,35946L,35947L,
95545 35948L,35949L,35950L,35951L,35952L,35953L,35954L,35955L,35956L,35957L,
95546 35958L,35959L,35960L,35961L,35962L,35963L,35964L,35965L,35966L,35967L,
95547 35968L,35969L,35970L,35971L,35972L,35973L,35974L,35975L,35976L,35977L,
95548 35978L,35979L,35980L,35981L,35982L,35983L,35984L,35985L,35986L,35987L,
95549 35988L,35989L,35990L,35991L,35992L,35993L,35994L,35995L,35996L,35997L,
95550 35998L,35999L,36000L,36001L,36002L,36003L,36004L,36005L,36006L,36007L,
95551 36008L,36009L,36010L,36011L,36012L,36013L,36014L,36015L,36016L,36017L,
95552 36018L,36019L,36020L,36021L,36022L,36023L,36024L,36025L,36026L,36027L,
95553 36028L,36029L,36030L,36031L,36032L,36033L,36034L,36035L,36036L,36037L,
95554 36038L,36039L,36040L,36041L,36042L,36043L,36044L,36045L,36046L,36047L,
95555 36048L,36049L,36050L,36051L,36052L,36053L,36054L,36055L,36056L,36057L,
95556 36058L,36059L,36060L,36061L,36062L,36063L,36064L,36065L,36066L,36067L,
95557 36068L,36069L,36070L,36071L,36072L,36073L,36074L,36075L,36076L,36077L,
95558 36078L,36079L,36080L,36081L,36082L,36083L,36084L,36085L,36086L,36087L,
95559 36088L,36089L,36090L,36091L,36092L,36093L,36094L,36095L,36096L,36097L,
95560 36098L,36099L,36100L,36101L,36102L,36103L,36104L,36105L,36106L,36107L,
95561 36108L,36109L,36110L,36111L,36112L,36113L,36114L,36115L,36116L,36117L,
95562 36118L,36119L,36120L,36121L,36122L,36123L,36124L,36125L,36126L,36127L,
95563 36128L,36129L,36130L,36131L,36132L,36133L,36134L,36135L,36136L,36137L,
95564 36138L,36139L,36140L,36141L,36142L,36143L,36144L,36145L,36146L,36147L,
95565 36148L,36149L,36150L,36151L,36152L,36153L,36154L,36155L,36156L,36157L,
95566 36158L,36159L,36160L,36161L,36162L,36163L,36164L,36165L,36166L,36167L,
95567 36168L,36169L,36170L,36171L,36172L,36173L,36174L,36175L,36176L,36177L,
95568 36178L,36179L,36180L,36181L,36182L,36183L,36184L,36185L,36186L,36187L,
95569 36188L,36189L,36190L,36191L,36192L,36193L,36194L,36195L,36196L,36197L,
95570 36198L,36199L,36200L,36201L,36202L,36203L,36204L,36205L,36206L,36207L,
95571 36208L,36209L,36210L,36211L,36212L,36213L,36214L,36215L,36216L,36217L,
95572 36218L,36219L,36220L,36221L,36222L,36223L,36224L,36225L,36226L,36227L,
95573 36228L,36229L,36230L,36231L,36232L,36233L,36234L,36235L,36236L,36237L,
95574 36238L,36239L,36240L,36241L,36242L,36243L,36244L,36245L,36246L,36247L,
95575 36248L,36249L,36250L,36251L,36252L,36253L,36254L,36255L,36256L,36257L,
95576 36258L,36259L,36260L,36261L,36262L,36263L,36264L,36265L,36266L,36267L,
95577 36268L,36269L,36270L,36271L,36272L,36273L,36274L,36275L,36276L,36277L,
95578 36278L,36279L,36280L,36281L,36282L,36283L,36284L,36285L,36286L,36287L,
95579 36288L,36289L,36290L,36291L,36292L,36293L,36294L,36295L,36296L,36297L,
95580 36298L,36299L,36300L,36301L,36302L,36303L,36304L,36305L,36306L,36307L,
95581 36308L,36309L,36310L,36311L,36312L,36313L,36314L,36315L,36316L,36317L,
95582 36318L,36319L,36320L,36321L,36322L,36323L,36324L,36325L,36326L,36327L,
95583 36328L,36329L,36330L,36331L,36332L,36333L,36334L,36335L,36336L,36337L,
95584 36338L,36339L,36340L,36341L,36342L,36343L,36344L,36345L,36346L,36347L,
95585 36348L,36349L,36350L,36351L,36352L,36353L,36354L,36355L,36356L,36357L,
95586 36358L,36359L,36360L,36361L,36362L,36363L,36364L,36365L,36366L,36367L,
95587 36368L,36369L,36370L,36371L,36372L,36373L,36374L,36375L,36376L,36377L,
95588 36378L,36379L,36380L,36381L,36382L,36383L,36384L,36385L,36386L,36387L,
95589 36388L,36389L,36390L,36391L,36392L,36393L,36394L,36395L,36396L,36397L,
95590 36398L,36399L,36400L,36401L,36402L,36403L,36404L,36405L,36406L,36407L,
95591 36408L,36409L,36410L,36411L,36412L,36413L,36414L,36415L,36416L,36417L,
95592 36418L,36419L,36420L,36421L,36422L,36423L,36424L,36425L,36426L,36427L,
95593 36428L,36429L,36430L,36431L,36432L,36433L,36434L,36435L,36436L,36437L,
95594 36438L,36439L,36440L,36441L,36442L,36443L,36444L,36445L,36446L,36447L,
95595 36448L,36449L,36450L,36451L,36452L,36453L,36454L,36455L,36456L,36457L,
95596 36458L,36459L,36460L,36461L,36462L,36463L,36464L,36465L,36466L,36467L,
95597 36468L,36469L,36470L,36471L,36472L,36473L,36474L,36475L,36476L,36477L,
95598 36478L,36479L,36480L,36481L,36482L,36483L,36484L,36485L,36486L,36487L,
95599 36488L,36489L,36490L,36491L,36492L,36493L,36494L,36495L,36496L,36497L,
95600 36498L,36499L,36500L,36501L,36502L,36503L,36504L,36505L,36506L,36507L,
95601 36508L,36509L,36510L,36511L,36512L,36513L,36514L,36515L,36516L,36517L,
95602 36518L,36519L,36520L,36521L,36522L,36523L,36524L,36525L,36526L,36527L,
95603 36528L,36529L,36530L,36531L,36532L,36533L,36534L,36535L,36536L,36537L,
95604 36538L,36539L,36540L,36541L,36542L,36543L,36544L,36545L,36546L,36547L,
95605 36548L,36549L,36550L,36551L,36552L,36553L,36554L,36555L,36556L,36557L,
95606 36558L,36559L,36560L,36561L,36562L,36563L,36564L,36565L,36566L,36567L,
95607 36568L,36569L,36570L,36571L,36572L,36573L,36574L,36575L,36576L,36577L,
95608 36578L,36579L,36580L,36581L,36582L,36583L,36584L,36585L,36586L,36587L,
95609 36588L,36589L,36590L,36591L,36592L,36593L,36594L,36595L,36596L,36597L,
95610 36598L,36599L,36600L,36601L,36602L,36603L,36604L,36605L,36606L,36607L,
95611 36608L,36609L,36610L,36611L,36612L,36613L,36614L,36615L,36616L,36617L,
95612 36618L,36619L,36620L,36621L,36622L,36623L,36624L,36625L,36626L,36627L,
95613 36628L,36629L,36630L,36631L,36632L,36633L,36634L,36635L,36636L,36637L,
95614 36638L,36639L,36640L,36641L,36642L,36643L,36644L,36645L,36646L,36647L,
95615 36648L,36649L,36650L,36651L,36652L,36653L,36654L,36655L,36656L,36657L,
95616 36658L,36659L,36660L,36661L,36662L,36663L,36664L,36665L,36666L,36667L,
95617 36668L,36669L,36670L,36671L,36672L,36673L,36674L,36675L,36676L,36677L,
95618 36678L,36679L,36680L,36681L,36682L,36683L,36684L,36685L,36686L,36687L,
95619 36688L,36689L,36690L,36691L,36692L,36693L,36694L,36695L,36696L,36697L,
95620 36698L,36699L,36700L,36701L,36702L,36703L,36704L,36705L,36706L,36707L,
95621 36708L,36709L,36710L,36711L,36712L,36713L,36714L,36715L,36716L,36717L,
95622 36718L,36719L,36720L,36721L,36722L,36723L,36724L,36725L,36726L,36727L,
95623 36728L,36729L,36730L,36731L,36732L,36733L,36734L,36735L,36736L,36737L,
95624 36738L,36739L,36740L,36741L,36742L,36743L,36744L,36745L,36746L,36747L,
95625 36748L,36749L,36750L,36751L,36752L,36753L,36754L,36755L,36756L,36757L,
95626 36758L,36759L,36760L,36761L,36762L,36763L,36764L,36765L,36766L,36767L,
95627 36768L,36769L,36770L,36771L,36772L,36773L,36774L,36775L,36776L,36777L,
95628 36778L,36779L,36780L,36781L,36782L,36783L,36784L,36785L,36786L,36787L,
95629 36788L,36789L,36790L,36791L,36792L,36793L,36794L,36795L,36796L,36797L,
95630 36798L,36799L,36800L,36801L,36802L,36803L,36804L,36805L,36806L,36807L,
95631 36808L,36809L,36810L,36811L,36812L,36813L,36814L,36815L,36816L,36817L,
95632 36818L,36819L,36820L,36821L,36822L,36823L,36824L,36825L,36826L,36827L,
95633 36828L,36829L,36830L,36831L,36832L,36833L,36834L,36835L,36836L,36837L,
95634 36838L,36839L,36840L,36841L,36842L,36843L,36844L,36845L,36846L,36847L,
95635 36848L,36849L,36850L,36851L,36852L,36853L,36854L,36855L,36856L,36857L,
95636 36858L,36859L,36860L,36861L,36862L,36863L,36864L,36865L,36866L,36867L,
95637 36868L,36869L,36870L,36871L,36872L,36873L,36874L,36875L,36876L,36877L,
95638 36878L,36879L,36880L,36881L,36882L,36883L,36884L,36885L,36886L,36887L,
95639 36888L,36889L,36890L,36891L,36892L,36893L,36894L,36895L,36896L,36897L,
95640 36898L,36899L,36900L,36901L,36902L,36903L,36904L,36905L,36906L,36907L,
95641 36908L,36909L,36910L,36911L,36912L,36913L,36914L,36915L,36916L,36917L,
95642 36918L,36919L,36920L,36921L,36922L,36923L,36924L,36925L,36926L,36927L,
95643 36928L,36929L,36930L,36931L,36932L,36933L,36934L,36935L,36936L,36937L,
95644 36938L,36939L,36940L,36941L,36942L,36943L,36944L,36945L,36946L,36947L,
95645 36948L,36949L,36950L,36951L,36952L,36953L,36954L,36955L,36956L,36957L,
95646 36958L,36959L,36960L,36961L,36962L,36963L,36964L,36965L,36966L,36967L,
95647 36968L,36969L,36970L,36971L,36972L,36973L,36974L,36975L,36976L,36977L,
95648 36978L,36979L,36980L,36981L,36982L,36983L,36984L,36985L,36986L,36987L,
95649 36988L,36989L,36990L,36991L,36992L,36993L,36994L,36995L,36996L,36997L,
95650 36998L,36999L,37000L,37001L,37002L,37003L,37004L,37005L,37006L,37007L,
95651 37008L,37009L,37010L,37011L,37012L,37013L,37014L,37015L,37016L,37017L,
95652 37018L,37019L,37020L,37021L,37022L,37023L,37024L,37025L,37026L,37027L,
95653 37028L,37029L,37030L,37031L,37032L,37033L,37034L,37035L,37036L,37037L,
95654 37038L,37039L,37040L,37041L,37042L,37043L,37044L,37045L,37046L,37047L,
95655 37048L,37049L,37050L,37051L,37052L,37053L,37054L,37055L,37056L,37057L,
95656 37058L,37059L,37060L,37061L,37062L,37063L,37064L,37065L,37066L,37067L,
95657 37068L,37069L,37070L,37071L,37072L,37073L,37074L,37075L,37076L,37077L,
95658 37078L,37079L,37080L,37081L,37082L,37083L,37084L,37085L,37086L,37087L,
95659 37088L,37089L,37090L,37091L,37092L,37093L,37094L,37095L,37096L,37097L,
95660 37098L,37099L,37100L,37101L,37102L,37103L,37104L,37105L,37106L,37107L,
95661 37108L,37109L,37110L,37111L,37112L,37113L,37114L,37115L,37116L,37117L,
95662 37118L,37119L,37120L,37121L,37122L,37123L,37124L,37125L,37126L,37127L,
95663 37128L,37129L,37130L,37131L,37132L,37133L,37134L,37135L,37136L,37137L,
95664 37138L,37139L,37140L,37141L,37142L,37143L,37144L,37145L,37146L,37147L,
95665 37148L,37149L,37150L,37151L,37152L,37153L,37154L,37155L,37156L,37157L,
95666 37158L,37159L,37160L,37161L,37162L,37163L,37164L,37165L,37166L,37167L,
95667 37168L,37169L,37170L,37171L,37172L,37173L,37174L,37175L,37176L,37177L,
95668 37178L,37179L,37180L,37181L,37182L,37183L,37184L,37185L,37186L,37187L,
95669 37188L,37189L,37190L,37191L,37192L,37193L,37194L,37195L,37196L,37197L,
95670 37198L,37199L,37200L,37201L,37202L,37203L,37204L,37205L,37206L,37207L,
95671 37208L,37209L,37210L,37211L,37212L,37213L,37214L,37215L,37216L,37217L,
95672 37218L,37219L,37220L,37221L,37222L,37223L,37224L,37225L,37226L,37227L,
95673 37228L,37229L,37230L,37231L,37232L,37233L,37234L,37235L,37236L,37237L,
95674 37238L,37239L,37240L,37241L,37242L,37243L,37244L,37245L,37246L,37247L,
95675 37248L,37249L,37250L,37251L,37252L,37253L,37254L,37255L,37256L,37257L,
95676 37258L,37259L,37260L,37261L,37262L,37263L,37264L,37265L,37266L,37267L,
95677 37268L,37269L,37270L,37271L,37272L,37273L,37274L,37275L,37276L,37277L,
95678 37278L,37279L,37280L,37281L,37282L,37283L,37284L,37285L,37286L,37287L,
95679 37288L,37289L,37290L,37291L,37292L,37293L,37294L,37295L,37296L,37297L,
95680 37298L,37299L,37300L,37301L,37302L,37303L,37304L,37305L,37306L,37307L,
95681 37308L,37309L,37310L,37311L,37312L,37313L,37314L,37315L,37316L,37317L,
95682 37318L,37319L,37320L,37321L,37322L,37323L,37324L,37325L,37326L,37327L,
95683 37328L,37329L,37330L,37331L,37332L,37333L,37334L,37335L,37336L,37337L,
95684 37338L,37339L,37340L,37341L,37342L,37343L,37344L,37345L,37346L,37347L,
95685 37348L,37349L,37350L,37351L,37352L,37353L,37354L,37355L,37356L,37357L,
95686 37358L,37359L,37360L,37361L,37362L,37363L,37364L,37365L,37366L,37367L,
95687 37368L,37369L,37370L,37371L,37372L,37373L,37374L,37375L,37376L,37377L,
95688 37378L,37379L,37380L,37381L,37382L,37383L,37384L,37385L,37386L,37387L,
95689 37388L,37389L,37390L,37391L,37392L,37393L,37394L,37395L,37396L,37397L,
95690 37398L,37399L,37400L,37401L,37402L,37403L,37404L,37405L,37406L,37407L,
95691 37408L,37409L,37410L,37411L,37412L,37413L,37414L,37415L,37416L,37417L,
95692 37418L,37419L,37420L,37421L,37422L,37423L,37424L,37425L,37426L,37427L,
95693 37428L,37429L,37430L,37431L,37432L,37433L,37434L,37435L,37436L,37437L,
95694 37438L,37439L,37440L,37441L,37442L,37443L,37444L,37445L,37446L,37447L,
95695 37448L,37449L,37450L,37451L,37452L,37453L,37454L,37455L,37456L,37457L,
95696 37458L,37459L,37460L,37461L,37462L,37463L,37464L,37465L,37466L,37467L,
95697 37468L,37469L,37470L,37471L,37472L,37473L,37474L,37475L,37476L,37477L,
95698 37478L,37479L,37480L,37481L,37482L,37483L,37484L,37485L,37486L,37487L,
95699 37488L,37489L,37490L,37491L,37492L,37493L,37494L,37495L,37496L,37497L,
95700 37498L,37499L,37500L,37501L,37502L,37503L,37504L,37505L,37506L,37507L,
95701 37508L,37509L,37510L,37511L,37512L,37513L,37514L,37515L,37516L,37517L,
95702 37518L,37519L,37520L,37521L,37522L,37523L,37524L,37525L,37526L,37527L,
95703 37528L,37529L,37530L,37531L,37532L,37533L,37534L,37535L,37536L,37537L,
95704 37538L,37539L,37540L,37541L,37542L,37543L,37544L,37545L,37546L,37547L,
95705 37548L,37549L,37550L,37551L,37552L,37553L,37554L,37555L,37556L,37557L,
95706 37558L,37559L,37560L,37561L,37562L,37563L,37564L,37565L,37566L,37567L,
95707 37568L,37569L,37570L,37571L,37572L,37573L,37574L,37575L,37576L,37577L,
95708 37578L,37579L,37580L,37581L,37582L,37583L,37584L,37585L,37586L,37587L,
95709 37588L,37589L,37590L,37591L,37592L,37593L,37594L,37595L,37596L,37597L,
95710 37598L,37599L,37600L,37601L,37602L,37603L,37604L,37605L,37606L,37607L,
95711 37608L,37609L,37610L,37611L,37612L,37613L,37614L,37615L,37616L,37617L,
95712 37618L,37619L,37620L,37621L,37622L,37623L,37624L,37625L,37626L,37627L,
95713 37628L,37629L,37630L,37631L,37632L,37633L,37634L,37635L,37636L,37637L,
95714 37638L,37639L,37640L,37641L,37642L,37643L,37644L,37645L,37646L,37647L,
95715 37648L,37649L,37650L,37651L,37652L,37653L,37654L,37655L,37656L,37657L,
95716 37658L,37659L,37660L,37661L,37662L,37663L,37664L,37665L,37666L,37667L,
95717 37668L,37669L,37670L,37671L,37672L,37673L,37674L,37675L,37676L,37677L,
95718 37678L,37679L,37680L,37681L,37682L,37683L,37684L,37685L,37686L,37687L,
95719 37688L,37689L,37690L,37691L,37692L,37693L,37694L,37695L,37696L,37697L,
95720 37698L,37699L,37700L,37701L,37702L,37703L,37704L,37705L,37706L,37707L,
95721 37708L,37709L,37710L,37711L,37712L,37713L,37714L,37715L,37716L,37717L,
95722 37718L,37719L,37720L,37721L,37722L,37723L,37724L,37725L,37726L,37727L,
95723 37728L,37729L,37730L,37731L,37732L,37733L,37734L,37735L,37736L,37737L,
95724 37738L,37739L,37740L,37741L,37742L,37743L,37744L,37745L,37746L,37747L,
95725 37748L,37749L,37750L,37751L,37752L,37753L,37754L,37755L,37756L,37757L,
95726 37758L,37759L,37760L,37761L,37762L,37763L,37764L,37765L,37766L,37767L,
95727 37768L,37769L,37770L,37771L,37772L,37773L,37774L,37775L,37776L,37777L,
95728 37778L,37779L,37780L,37781L,37782L,37783L,37784L,37785L,37786L,37787L,
95729 37788L,37789L,37790L,37791L,37792L,37793L,37794L,37795L,37796L,37797L,
95730 37798L,37799L,37800L,37801L,37802L,37803L,37804L,37805L,37806L,37807L,
95731 37808L,37809L,37810L,37811L,37812L,37813L,37814L,37815L,37816L,37817L,
95732 37818L,37819L,37820L,37821L,37822L,37823L,37824L,37825L,37826L,37827L,
95733 37828L,37829L,37830L,37831L,37832L,37833L,37834L,37835L,37836L,37837L,
95734 37838L,37839L,37840L,37841L,37842L,37843L,37844L,37845L,37846L,37847L,
95735 37848L,37849L,37850L,37851L,37852L,37853L,37854L,37855L,37856L,37857L,
95736 37858L,37859L,37860L,37861L,37862L,37863L,37864L,37865L,37866L,37867L,
95737 37868L,37869L,37870L,37871L,37872L,37873L,37874L,37875L,37876L,37877L,
95738 37878L,37879L,37880L,37881L,37882L,37883L,37884L,37885L,37886L,37887L,
95739 37888L,37889L,37890L,37891L,37892L,37893L,37894L,37895L,37896L,37897L,
95740 37898L,37899L,37900L,37901L,37902L,37903L,37904L,37905L,37906L,37907L,
95741 37908L,37909L,37910L,37911L,37912L,37913L,37914L,37915L,37916L,37917L,
95742 37918L,37919L,37920L,37921L,37922L,37923L,37924L,37925L,37926L,37927L,
95743 37928L,37929L,37930L,37931L,37932L,37933L,37934L,37935L,37936L,37937L,
95744 37938L,37939L,37940L,37941L,37942L,37943L,37944L,37945L,37946L,37947L,
95745 37948L,37949L,37950L,37951L,37952L,37953L,37954L,37955L,37956L,37957L,
95746 37958L,37959L,37960L,37961L,37962L,37963L,37964L,37965L,37966L,37967L,
95747 37968L,37969L,37970L,37971L,37972L,37973L,37974L,37975L,37976L,37977L,
95748 37978L,37979L,37980L,37981L,37982L,37983L,37984L,37985L,37986L,37987L,
95749 37988L,37989L,37990L,37991L,37992L,37993L,37994L,37995L,37996L,37997L,
95750 37998L,37999L,38000L,38001L,38002L,38003L,38004L,38005L,38006L,38007L,
95751 38008L,38009L,38010L,38011L,38012L,38013L,38014L,38015L,38016L,38017L,
95752 38018L,38019L,38020L,38021L,38022L,38023L,38024L,38025L,38026L,38027L,
95753 38028L,38029L,38030L,38031L,38032L,38033L,38034L,38035L,38036L,38037L,
95754 38038L,38039L,38040L,38041L,38042L,38043L,38044L,38045L,38046L,38047L,
95755 38048L,38049L,38050L,38051L,38052L,38053L,38054L,38055L,38056L,38057L,
95756 38058L,38059L,38060L,38061L,38062L,38063L,38064L,38065L,38066L,38067L,
95757 38068L,38069L,38070L,38071L,38072L,38073L,38074L,38075L,38076L,38077L,
95758 38078L,38079L,38080L,38081L,38082L,38083L,38084L,38085L,38086L,38087L,
95759 38088L,38089L,38090L,38091L,38092L,38093L,38094L,38095L,38096L,38097L,
95760 38098L,38099L,38100L,38101L,38102L,38103L,38104L,38105L,38106L,38107L,
95761 38108L,38109L,38110L,38111L,38112L,38113L,38114L,38115L,38116L,38117L,
95762 38118L,38119L,38120L,38121L,38122L,38123L,38124L,38125L,38126L,38127L,
95763 38128L,38129L,38130L,38131L,38132L,38133L,38134L,38135L,38136L,38137L,
95764 38138L,38139L,38140L,38141L,38142L,38143L,38144L,38145L,38146L,38147L,
95765 38148L,38149L,38150L,38151L,38152L,38153L,38154L,38155L,38156L,38157L,
95766 38158L,38159L,38160L,38161L,38162L,38163L,38164L,38165L,38166L,38167L,
95767 38168L,38169L,38170L,38171L,38172L,38173L,38174L,38175L,38176L,38177L,
95768 38178L,38179L,38180L,38181L,38182L,38183L,38184L,38185L,38186L,38187L,
95769 38188L,38189L,38190L,38191L,38192L,38193L,38194L,38195L,38196L,38197L,
95770 38198L,38199L,38200L,38201L,38202L,38203L,38204L,38205L,38206L,38207L,
95771 38208L,38209L,38210L,38211L,38212L,38213L,38214L,38215L,38216L,38217L,
95772 38218L,38219L,38220L,38221L,38222L,38223L,38224L,38225L,38226L,38227L,
95773 38228L,38229L,38230L,38231L,38232L,38233L,38234L,38235L,38236L,38237L,
95774 38238L,38239L,38240L,38241L,38242L,38243L,38244L,38245L,38246L,38247L,
95775 38248L,38249L,38250L,38251L,38252L,38253L,38254L,38255L,38256L,38257L,
95776 38258L,38259L,38260L,38261L,38262L,38263L,38264L,38265L,38266L,38267L,
95777 38268L,38269L,38270L,38271L,38272L,38273L,38274L,38275L,38276L,38277L,
95778 38278L,38279L,38280L,38281L,38282L,38283L,38284L,38285L,38286L,38287L,
95779 38288L,38289L,38290L,38291L,38292L,38293L,38294L,38295L,38296L,38297L,
95780 38298L,38299L,38300L,38301L,38302L,38303L,38304L,38305L,38306L,38307L,
95781 38308L,38309L,38310L,38311L,38312L,38313L,38314L,38315L,38316L,38317L,
95782 38318L,38319L,38320L,38321L,38322L,38323L,38324L,38325L,38326L,38327L,
95783 38328L,38329L,38330L,38331L,38332L,38333L,38334L,38335L,38336L,38337L,
95784 38338L,38339L,38340L,38341L,38342L,38343L,38344L,38345L,38346L,38347L,
95785 38348L,38349L,38350L,38351L,38352L,38353L,38354L,38355L,38356L,38357L,
95786 38358L,38359L,38360L,38361L,38362L,38363L,38364L,38365L,38366L,38367L,
95787 38368L,38369L,38370L,38371L,38372L,38373L,38374L,38375L,38376L,38377L,
95788 38378L,38379L,38380L,38381L,38382L,38383L,38384L,38385L,38386L,38387L,
95789 38388L,38389L,38390L,38391L,38392L,38393L,38394L,38395L,38396L,38397L,
95790 38398L,38399L,38400L,38401L,38402L,38403L,38404L,38405L,38406L,38407L,
95791 38408L,38409L,38410L,38411L,38412L,38413L,38414L,38415L,38416L,38417L,
95792 38418L,38419L,38420L,38421L,38422L,38423L,38424L,38425L,38426L,38427L,
95793 38428L,38429L,38430L,38431L,38432L,38433L,38434L,38435L,38436L,38437L,
95794 38438L,38439L,38440L,38441L,38442L,38443L,38444L,38445L,38446L,38447L,
95795 38448L,38449L,38450L,38451L,38452L,38453L,38454L,38455L,38456L,38457L,
95796 38458L,38459L,38460L,38461L,38462L,38463L,38464L,38465L,38466L,38467L,
95797 38468L,38469L,38470L,38471L,38472L,38473L,38474L,38475L,38476L,38477L,
95798 38478L,38479L,38480L,38481L,38482L,38483L,38484L,38485L,38486L,38487L,
95799 38488L,38489L,38490L,38491L,38492L,38493L,38494L,38495L,38496L,38497L,
95800 38498L,38499L,38500L,38501L,38502L,38503L,38504L,38505L,38506L,38507L,
95801 38508L,38509L,38510L,38511L,38512L,38513L,38514L,38515L,38516L,38517L,
95802 38518L,38519L,38520L,38521L,38522L,38523L,38524L,38525L,38526L,38527L,
95803 38528L,38529L,38530L,38531L,38532L,38533L,38534L,38535L,38536L,38537L,
95804 38538L,38539L,38540L,38541L,38542L,38543L,38544L,38545L,38546L,38547L,
95805 38548L,38549L,38550L,38551L,38552L,38553L,38554L,38555L,38556L,38557L,
95806 38558L,38559L,38560L,38561L,38562L,38563L,38564L,38565L,38566L,38567L,
95807 38568L,38569L,38570L,38571L,38572L,38573L,38574L,38575L,38576L,38577L,
95808 38578L,38579L,38580L,38581L,38582L,38583L,38584L,38585L,38586L,38587L,
95809 38588L,38589L,38590L,38591L,38592L,38593L,38594L,38595L,38596L,38597L,
95810 38598L,38599L,38600L,38601L,38602L,38603L,38604L,38605L,38606L,38607L,
95811 38608L,38609L,38610L,38611L,38612L,38613L,38614L,38615L,38616L,38617L,
95812 38618L,38619L,38620L,38621L,38622L,38623L,38624L,38625L,38626L,38627L,
95813 38628L,38629L,38630L,38631L,38632L,38633L,38634L,38635L,38636L,38637L,
95814 38638L,38639L,38640L,38641L,38642L,38643L,38644L,38645L,38646L,38647L,
95815 38648L,38649L,38650L,38651L,38652L,38653L,38654L,38655L,38656L,38657L,
95816 38658L,38659L,38660L,38661L,38662L,38663L,38664L,38665L,38666L,38667L,
95817 38668L,38669L,38670L,38671L,38672L,38673L,38674L,38675L,38676L,38677L,
95818 38678L,38679L,38680L,38681L,38682L,38683L,38684L,38685L,38686L,38687L,
95819 38688L,38689L,38690L,38691L,38692L,38693L,38694L,38695L,38696L,38697L,
95820 38698L,38699L,38700L,38701L,38702L,38703L,38704L,38705L,38706L,38707L,
95821 38708L,38709L,38710L,38711L,38712L,38713L,38714L,38715L,38716L,38717L,
95822 38718L,38719L,38720L,38721L,38722L,38723L,38724L,38725L,38726L,38727L,
95823 38728L,38729L,38730L,38731L,38732L,38733L,38734L,38735L,38736L,38737L,
95824 38738L,38739L,38740L,38741L,38742L,38743L,38744L,38745L,38746L,38747L,
95825 38748L,38749L,38750L,38751L,38752L,38753L,38754L,38755L,38756L,38757L,
95826 38758L,38759L,38760L,38761L,38762L,38763L,38764L,38765L,38766L,38767L,
95827 38768L,38769L,38770L,38771L,38772L,38773L,38774L,38775L,38776L,38777L,
95828 38778L,38779L,38780L,38781L,38782L,38783L,38784L,38785L,38786L,38787L,
95829 38788L,38789L,38790L,38791L,38792L,38793L,38794L,38795L,38796L,38797L,
95830 38798L,38799L,38800L,38801L,38802L,38803L,38804L,38805L,38806L,38807L,
95831 38808L,38809L,38810L,38811L,38812L,38813L,38814L,38815L,38816L,38817L,
95832 38818L,38819L,38820L,38821L,38822L,38823L,38824L,38825L,38826L,38827L,
95833 38828L,38829L,38830L,38831L,38832L,38833L,38834L,38835L,38836L,38837L,
95834 38838L,38839L,38840L,38841L,38842L,38843L,38844L,38845L,38846L,38847L,
95835 38848L,38849L,38850L,38851L,38852L,38853L,38854L,38855L,38856L,38857L,
95836 38858L,38859L,38860L,38861L,38862L,38863L,38864L,38865L,38866L,38867L,
95837 38868L,38869L,38870L,38871L,38872L,38873L,38874L,38875L,38876L,38877L,
95838 38878L,38879L,38880L,38881L,38882L,38883L,38884L,38885L,38886L,38887L,
95839 38888L,38889L,38890L,38891L,38892L,38893L,38894L,38895L,38896L,38897L,
95840 38898L,38899L,38900L,38901L,38902L,38903L,38904L,38905L,38906L,38907L,
95841 38908L,38909L,38910L,38911L,38912L,38913L,38914L,38915L,38916L,38917L,
95842 38918L,38919L,38920L,38921L,38922L,38923L,38924L,38925L,38926L,38927L,
95843 38928L,38929L,38930L,38931L,38932L,38933L,38934L,38935L,38936L,38937L,
95844 38938L,38939L,38940L,38941L,38942L,38943L,38944L,38945L,38946L,38947L,
95845 38948L,38949L,38950L,38951L,38952L,38953L,38954L,38955L,38956L,38957L,
95846 38958L,38959L,38960L,38961L,38962L,38963L,38964L,38965L,38966L,38967L,
95847 38968L,38969L,38970L,38971L,38972L,38973L,38974L,38975L,38976L,38977L,
95848 38978L,38979L,38980L,38981L,38982L,38983L,38984L,38985L,38986L,38987L,
95849 38988L,38989L,38990L,38991L,38992L,38993L,38994L,38995L,38996L,38997L,
95850 38998L,38999L,39000L,39001L,39002L,39003L,39004L,39005L,39006L,39007L,
95851 39008L,39009L,39010L,39011L,39012L,39013L,39014L,39015L,39016L,39017L,
95852 39018L,39019L,39020L,39021L,39022L,39023L,39024L,39025L,39026L,39027L,
95853 39028L,39029L,39030L,39031L,39032L,39033L,39034L,39035L,39036L,39037L,
95854 39038L,39039L,39040L,39041L,39042L,39043L,39044L,39045L,39046L,39047L,
95855 39048L,39049L,39050L,39051L,39052L,39053L,39054L,39055L,39056L,39057L,
95856 39058L,39059L,39060L,39061L,39062L,39063L,39064L,39065L,39066L,39067L,
95857 39068L,39069L,39070L,39071L,39072L,39073L,39074L,39075L,39076L,39077L,
95858 39078L,39079L,39080L,39081L,39082L,39083L,39084L,39085L,39086L,39087L,
95859 39088L,39089L,39090L,39091L,39092L,39093L,39094L,39095L,39096L,39097L,
95860 39098L,39099L,39100L,39101L,39102L,39103L,39104L,39105L,39106L,39107L,
95861 39108L,39109L,39110L,39111L,39112L,39113L,39114L,39115L,39116L,39117L,
95862 39118L,39119L,39120L,39121L,39122L,39123L,39124L,39125L,39126L,39127L,
95863 39128L,39129L,39130L,39131L,39132L,39133L,39134L,39135L,39136L,39137L,
95864 39138L,39139L,39140L,39141L,39142L,39143L,39144L,39145L,39146L,39147L,
95865 39148L,39149L,39150L,39151L,39152L,39153L,39154L,39155L,39156L,39157L,
95866 39158L,39159L,39160L,39161L,39162L,39163L,39164L,39165L,39166L,39167L,
95867 39168L,39169L,39170L,39171L,39172L,39173L,39174L,39175L,39176L,39177L,
95868 39178L,39179L,39180L,39181L,39182L,39183L,39184L,39185L,39186L,39187L,
95869 39188L,39189L,39190L,39191L,39192L,39193L,39194L,39195L,39196L,39197L,
95870 39198L,39199L,39200L,39201L,39202L,39203L,39204L,39205L,39206L,39207L,
95871 39208L,39209L,39210L,39211L,39212L,39213L,39214L,39215L,39216L,39217L,
95872 39218L,39219L,39220L,39221L,39222L,39223L,39224L,39225L,39226L,39227L,
95873 39228L,39229L,39230L,39231L,39232L,39233L,39234L,39235L,39236L,39237L,
95874 39238L,39239L,39240L,39241L,39242L,39243L,39244L,39245L,39246L,39247L,
95875 39248L,39249L,39250L,39251L,39252L,39253L,39254L,39255L,39256L,39257L,
95876 39258L,39259L,39260L,39261L,39262L,39263L,39264L,39265L,39266L,39267L,
95877 39268L,39269L,39270L,39271L,39272L,39273L,39274L,39275L,39276L,39277L,
95878 39278L,39279L,39280L,39281L,39282L,39283L,39284L,39285L,39286L,39287L,
95879 39288L,39289L,39290L,39291L,39292L,39293L,39294L,39295L,39296L,39297L,
95880 39298L,39299L,39300L,39301L,39302L,39303L,39304L,39305L,39306L,39307L,
95881 39308L,39309L,39310L,39311L,39312L,39313L,39314L,39315L,39316L,39317L,
95882 39318L,39319L,39320L,39321L,39322L,39323L,39324L,39325L,39326L,39327L,
95883 39328L,39329L,39330L,39331L,39332L,39333L,39334L,39335L,39336L,39337L,
95884 39338L,39339L,39340L,39341L,39342L,39343L,39344L,39345L,39346L,39347L,
95885 39348L,39349L,39350L,39351L,39352L,39353L,39354L,39355L,39356L,39357L,
95886 39358L,39359L,39360L,39361L,39362L,39363L,39364L,39365L,39366L,39367L,
95887 39368L,39369L,39370L,39371L,39372L,39373L,39374L,39375L,39376L,39377L,
95888 39378L,39379L,39380L,39381L,39382L,39383L,39384L,39385L,39386L,39387L,
95889 39388L,39389L,39390L,39391L,39392L,39393L,39394L,39395L,39396L,39397L,
95890 39398L,39399L,39400L,39401L,39402L,39403L,39404L,39405L,39406L,39407L,
95891 39408L,39409L,39410L,39411L,39412L,39413L,39414L,39415L,39416L,39417L,
95892 39418L,39419L,39420L,39421L,39422L,39423L,39424L,39425L,39426L,39427L,
95893 39428L,39429L,39430L,39431L,39432L,39433L,39434L,39435L,39436L,39437L,
95894 39438L,39439L,39440L,39441L,39442L,39443L,39444L,39445L,39446L,39447L,
95895 39448L,39449L,39450L,39451L,39452L,39453L,39454L,39455L,39456L,39457L,
95896 39458L,39459L,39460L,39461L,39462L,39463L,39464L,39465L,39466L,39467L,
95897 39468L,39469L,39470L,39471L,39472L,39473L,39474L,39475L,39476L,39477L,
95898 39478L,39479L,39480L,39481L,39482L,39483L,39484L,39485L,39486L,39487L,
95899 39488L,39489L,39490L,39491L,39492L,39493L,39494L,39495L,39496L,39497L,
95900 39498L,39499L,39500L,39501L,39502L,39503L,39504L,39505L,39506L,39507L,
95901 39508L,39509L,39510L,39511L,39512L,39513L,39514L,39515L,39516L,39517L,
95902 39518L,39519L,39520L,39521L,39522L,39523L,39524L,39525L,39526L,39527L,
95903 39528L,39529L,39530L,39531L,39532L,39533L,39534L,39535L,39536L,39537L,
95904 39538L,39539L,39540L,39541L,39542L,39543L,39544L,39545L,39546L,39547L,
95905 39548L,39549L,39550L,39551L,39552L,39553L,39554L,39555L,39556L,39557L,
95906 39558L,39559L,39560L,39561L,39562L,39563L,39564L,39565L,39566L,39567L,
95907 39568L,39569L,39570L,39571L,39572L,39573L,39574L,39575L,39576L,39577L,
95908 39578L,39579L,39580L,39581L,39582L,39583L,39584L,39585L,39586L,39587L,
95909 39588L,39589L,39590L,39591L,39592L,39593L,39594L,39595L,39596L,39597L,
95910 39598L,39599L,39600L,39601L,39602L,39603L,39604L,39605L,39606L,39607L,
95911 39608L,39609L,39610L,39611L,39612L,39613L,39614L,39615L,39616L,39617L,
95912 39618L,39619L,39620L,39621L,39622L,39623L,39624L,39625L,39626L,39627L,
95913 39628L,39629L,39630L,39631L,39632L,39633L,39634L,39635L,39636L,39637L,
95914 39638L,39639L,39640L,39641L,39642L,39643L,39644L,39645L,39646L,39647L,
95915 39648L,39649L,39650L,39651L,39652L,39653L,39654L,39655L,39656L,39657L,
95916 39658L,39659L,39660L,39661L,39662L,39663L,39664L,39665L,39666L,39667L,
95917 39668L,39669L,39670L,39671L,39672L,39673L,39674L,39675L,39676L,39677L,
95918 39678L,39679L,39680L,39681L,39682L,39683L,39684L,39685L,39686L,39687L,
95919 39688L,39689L,39690L,39691L,39692L,39693L,39694L,39695L,39696L,39697L,
95920 39698L,39699L,39700L,39701L,39702L,39703L,39704L,39705L,39706L,39707L,
95921 39708L,39709L,39710L,39711L,39712L,39713L,39714L,39715L,39716L,39717L,
95922 39718L,39719L,39720L,39721L,39722L,39723L,39724L,39725L,39726L,39727L,
95923 39728L,39729L,39730L,39731L,39732L,39733L,39734L,39735L,39736L,39737L,
95924 39738L,39739L,39740L,39741L,39742L,39743L,39744L,39745L,39746L,39747L,
95925 39748L,39749L,39750L,39751L,39752L,39753L,39754L,39755L,39756L,39757L,
95926 39758L,39759L,39760L,39761L,39762L,39763L,39764L,39765L,39766L,39767L,
95927 39768L,39769L,39770L,39771L,39772L,39773L,39774L,39775L,39776L,39777L,
95928 39778L,39779L,39780L,39781L,39782L,39783L,39784L,39785L,39786L,39787L,
95929 39788L,39789L,39790L,39791L,39792L,39793L,39794L,39795L,39796L,39797L,
95930 39798L,39799L,39800L,39801L,39802L,39803L,39804L,39805L,39806L,39807L,
95931 39808L,39809L,39810L,39811L,39812L,39813L,39814L,39815L,39816L,39817L,
95932 39818L,39819L,39820L,39821L,39822L,39823L,39824L,39825L,39826L,39827L,
95933 39828L,39829L,39830L,39831L,39832L,39833L,39834L,39835L,39836L,39837L,
95934 39838L,39839L,39840L,39841L,39842L,39843L,39844L,39845L,39846L,39847L,
95935 39848L,39849L,39850L,39851L,39852L,39853L,39854L,39855L,39856L,39857L,
95936 39858L,39859L,39860L,39861L,39862L,39863L,39864L,39865L,39866L,39867L,
95937 39868L,39869L,39870L,39871L,39872L,39873L,39874L,39875L,39876L,39877L,
95938 39878L,39879L,39880L,39881L,39882L,39883L,39884L,39885L,39886L,39887L,
95939 39888L,39889L,39890L,39891L,39892L,39893L,39894L,39895L,39896L,39897L,
95940 39898L,39899L,39900L,39901L,39902L,39903L,39904L,39905L,39906L,39907L,
95941 39908L,39909L,39910L,39911L,39912L,39913L,39914L,39915L,39916L,39917L,
95942 39918L,39919L,39920L,39921L,39922L,39923L,39924L,39925L,39926L,39927L,
95943 39928L,39929L,39930L,39931L,39932L,39933L,39934L,39935L,39936L,39937L,
95944 39938L,39939L,39940L,39941L,39942L,39943L,39944L,39945L,39946L,39947L,
95945 39948L,39949L,39950L,39951L,39952L,39953L,39954L,39955L,39956L,39957L,
95946 39958L,39959L,39960L,39961L,39962L,39963L,39964L,39965L,39966L,39967L,
95947 39968L,39969L,39970L,39971L,39972L,39973L,39974L,39975L,39976L,39977L,
95948 39978L,39979L,39980L,39981L,39982L,39983L,39984L,39985L,39986L,39987L,
95949 39988L,39989L,39990L,39991L,39992L,39993L,39994L,39995L,39996L,39997L,
95950 39998L,39999L,40000L,40001L,40002L,40003L,40004L,40005L,40006L,40007L,
95951 40008L,40009L,40010L,40011L,40012L,40013L,40014L,40015L,40016L,40017L,
95952 40018L,40019L,40020L,40021L,40022L,40023L,40024L,40025L,40026L,40027L,
95953 40028L,40029L,40030L,40031L,40032L,40033L,40034L,40035L,40036L,40037L,
95954 40038L,40039L,40040L,40041L,40042L,40043L,40044L,40045L,40046L,40047L,
95955 40048L,40049L,40050L,40051L,40052L,40053L,40054L,40055L,40056L,40057L,
95956 40058L,40059L,40060L,40061L,40062L,40063L,40064L,40065L,40066L,40067L,
95957 40068L,40069L,40070L,40071L,40072L,40073L,40074L,40075L,40076L,40077L,
95958 40078L,40079L,40080L,40081L,40082L,40083L,40084L,40085L,40086L,40087L,
95959 40088L,40089L,40090L,40091L,40092L,40093L,40094L,40095L,40096L,40097L,
95960 40098L,40099L,40100L,40101L,40102L,40103L,40104L,40105L,40106L,40107L,
95961 40108L,40109L,40110L,40111L,40112L,40113L,40114L,40115L,40116L,40117L,
95962 40118L,40119L,40120L,40121L,40122L,40123L,40124L,40125L,40126L,40127L,
95963 40128L,40129L,40130L,40131L,40132L,40133L,40134L,40135L,40136L,40137L,
95964 40138L,40139L,40140L,40141L,40142L,40143L,40144L,40145L,40146L,40147L,
95965 40148L,40149L,40150L,40151L,40152L,40153L,40154L,40155L,40156L,40157L,
95966 40158L,40159L,40160L,40161L,40162L,40163L,40164L,40165L,40166L,40167L,
95967 40168L,40169L,40170L,40171L,40172L,40173L,40174L,40175L,40176L,40177L,
95968 40178L,40179L,40180L,40181L,40182L,40183L,40184L,40185L,40186L,40187L,
95969 40188L,40189L,40190L,40191L,40192L,40193L,40194L,40195L,40196L,40197L,
95970 40198L,40199L,40200L,40201L,40202L,40203L,40204L,40205L,40206L,40207L,
95971 40208L,40209L,40210L,40211L,40212L,40213L,40214L,40215L,40216L,40217L,
95972 40218L,40219L,40220L,40221L,40222L,40223L,40224L,40225L,40226L,40227L,
95973 40228L,40229L,40230L,40231L,40232L,40233L,40234L,40235L,40236L,40237L,
95974 40238L,40239L,40240L,40241L,40242L,40243L,40244L,40245L,40246L,40247L,
95975 40248L,40249L,40250L,40251L,40252L,40253L,40254L,40255L,40256L,40257L,
95976 40258L,40259L,40260L,40261L,40262L,40263L,40264L,40265L,40266L,40267L,
95977 40268L,40269L,40270L,40271L,40272L,40273L,40274L,40275L,40276L,40277L,
95978 40278L,40279L,40280L,40281L,40282L,40283L,40284L,40285L,40286L,40287L,
95979 40288L,40289L,40290L,40291L,40292L,40293L,40294L,40295L,40296L,40297L,
95980 40298L,40299L,40300L,40301L,40302L,40303L,40304L,40305L,40306L,40307L,
95981 40308L,40309L,40310L,40311L,40312L,40313L,40314L,40315L,40316L,40317L,
95982 40318L,40319L,40320L,40321L,40322L,40323L,40324L,40325L,40326L,40327L,
95983 40328L,40329L,40330L,40331L,40332L,40333L,40334L,40335L,40336L,40337L,
95984 40338L,40339L,40340L,40341L,40342L,40343L,40344L,40345L,40346L,40347L,
95985 40348L,40349L,40350L,40351L,40352L,40353L,40354L,40355L,40356L,40357L,
95986 40358L,40359L,40360L,40361L,40362L,40363L,40364L,40365L,40366L,40367L,
95987 40368L,40369L,40370L,40371L,40372L,40373L,40374L,40375L,40376L,40377L,
95988 40378L,40379L,40380L,40381L,40382L,40383L,40384L,40385L,40386L,40387L,
95989 40388L,40389L,40390L,40391L,40392L,40393L,40394L,40395L,40396L,40397L,
95990 40398L,40399L,40400L,40401L,40402L,40403L,40404L,40405L,40406L,40407L,
95991 40408L,40409L,40410L,40411L,40412L,40413L,40414L,40415L,40416L,40417L,
95992 40418L,40419L,40420L,40421L,40422L,40423L,40424L,40425L,40426L,40427L,
95993 40428L,40429L,40430L,40431L,40432L,40433L,40434L,40435L,40436L,40437L,
95994 40438L,40439L,40440L,40441L,40442L,40443L,40444L,40445L,40446L,40447L,
95995 40448L,40449L,40450L,40451L,40452L,40453L,40454L,40455L,40456L,40457L,
95996 40458L,40459L,40460L,40461L,40462L,40463L,40464L,40465L,40466L,40467L,
95997 40468L,40469L,40470L,40471L,40472L,40473L,40474L,40475L,40476L,40477L,
95998 40478L,40479L,40480L,40481L,40482L,40483L,40484L,40485L,40486L,40487L,
95999 40488L,40489L,40490L,40491L,40492L,40493L,40494L,40495L,40496L,40497L,
96000 40498L,40499L,40500L,40501L,40502L,40503L,40504L,40505L,40506L,40507L,
96001 40508L,40509L,40510L,40511L,40512L,40513L,40514L,40515L,40516L,40517L,
96002 40518L,40519L,40520L,40521L,40522L,40523L,40524L,40525L,40526L,40527L,
96003 40528L,40529L,40530L,40531L,40532L,40533L,40534L,40535L,40536L,40537L,
96004 40538L,40539L,40540L,40541L,40542L,40543L,40544L,40545L,40546L,40547L,
96005 40548L,40549L,40550L,40551L,40552L,40553L,40554L,40555L,40556L,40557L,
96006 40558L,40559L,40560L,40561L,40562L,40563L,40564L,40565L,40566L,40567L,
96007 40568L,40569L,40570L,40571L,40572L,40573L,40574L,40575L,40576L,40577L,
96008 40578L,40579L,40580L,40581L,40582L,40583L,40584L,40585L,40586L,40587L,
96009 40588L,40589L,40590L,40591L,40592L,40593L,40594L,40595L,40596L,40597L,
96010 40598L,40599L,40600L,40601L,40602L,40603L,40604L,40605L,40606L,40607L,
96011 40608L,40609L,40610L,40611L,40612L,40613L,40614L,40615L,40616L,40617L,
96012 40618L,40619L,40620L,40621L,40622L,40623L,40624L,40625L,40626L,40627L,
96013 40628L,40629L,40630L,40631L,40632L,40633L,40634L,40635L,40636L,40637L,
96014 40638L,40639L,40640L,40641L,40642L,40643L,40644L,40645L,40646L,40647L,
96015 40648L,40649L,40650L,40651L,40652L,40653L,40654L,40655L,40656L,40657L,
96016 40658L,40659L,40660L,40661L,40662L,40663L,40664L,40665L,40666L,40667L,
96017 40668L,40669L,40670L,40671L,40672L,40673L,40674L,40675L,40676L,40677L,
96018 40678L,40679L,40680L,40681L,40682L,40683L,40684L,40685L,40686L,40687L,
96019 40688L,40689L,40690L,40691L,40692L,40693L,40694L,40695L,40696L,40697L,
96020 40698L,40699L,40700L,40701L,40702L,40703L,40704L,40705L,40706L,40707L,
96021 40708L,40709L,40710L,40711L,40712L,40713L,40714L,40715L,40716L,40717L,
96022 40718L,40719L,40720L,40721L,40722L,40723L,40724L,40725L,40726L,40727L,
96023 40728L,40729L,40730L,40731L,40732L,40733L,40734L,40735L,40736L,40737L,
96024 40738L,40739L,40740L,40741L,40742L,40743L,40744L,40745L,40746L,40747L,
96025 40748L,40749L,40750L,40751L,40752L,40753L,40754L,40755L,40756L,40757L,
96026 40758L,40759L,40760L,40761L,40762L,40763L,40764L,40765L,40766L,40767L,
96027 40768L,40769L,40770L,40771L,40772L,40773L,40774L,40775L,40776L,40777L,
96028 40778L,40779L,40780L,40781L,40782L,40783L,40784L,40785L,40786L,40787L,
96029 40788L,40789L,40790L,40791L,40792L,40793L,40794L,40795L,40796L,40797L,
96030 40798L,40799L,40800L,40801L,40802L,40803L,40804L,40805L,40806L,40807L,
96031 40808L,40809L,40810L,40811L,40812L,40813L,40814L,40815L,40816L,40817L,
96032 40818L,40819L,40820L,40821L,40822L,40823L,40824L,40825L,40826L,40827L,
96033 40828L,40829L,40830L,40831L,40832L,40833L,40834L,40835L,40836L,40837L,
96034 40838L,40839L,40840L,40841L,40842L,40843L,40844L,40845L,40846L,40847L,
96035 40848L,40849L,40850L,40851L,40852L,40853L,40854L,40855L,40856L,40857L,
96036 40858L,40859L,40860L,40861L,40862L,40863L,40864L,40865L,40866L,40867L,
96037 40868L,40869L,40870L,40871L,40872L,40873L,40874L,40875L,40876L,40877L,
96038 40878L,40879L,40880L,40881L,40882L,40883L,40884L,40885L,40886L,40887L,
96039 40888L,40889L,40890L,40891L,40892L,40893L,40894L,40895L,40896L,40897L,
96040 40898L,40899L,40900L,40901L,40902L,40903L,40904L,40905L,40906L,40907L,
96041 40908L,40909L,40910L,40911L,40912L,40913L,40914L,40915L,40916L,40917L,
96042 40918L,40919L,40920L,40921L,40922L,40923L,40924L,40925L,40926L,40927L,
96043 40928L,40929L,40930L,40931L,40932L,40933L,40934L,40935L,40936L,40937L,
96044 40938L,40939L,40940L,40941L,40942L,40943L,40944L,40945L,40946L,40947L,
96045 40948L,40949L,40950L,40951L,40952L,40953L,40954L,40955L,40956L,40957L,
96046 40958L,40959L,40960L,40961L,40962L,40963L,40964L,40965L,40966L,40967L,
96047 40968L,40969L,40970L,40971L,40972L,40973L,40974L,40975L,40976L,40977L,
96048 40978L,40979L,40980L,40981L,40982L,40983L,40984L,40985L,40986L,40987L,
96049 40988L,40989L,40990L,40991L,40992L,40993L,40994L,40995L,40996L,40997L,
96050 40998L,40999L,41000L,41001L,41002L,41003L,41004L,41005L,41006L,41007L,
96051 41008L,41009L,41010L,41011L,41012L,41013L,41014L,41015L,41016L,41017L,
96052 41018L,41019L,41020L,41021L,41022L,41023L,41024L,41025L,41026L,41027L,
96053 41028L,41029L,41030L,41031L,41032L,41033L,41034L,41035L,41036L,41037L,
96054 41038L,41039L,41040L,41041L,41042L,41043L,41044L,41045L,41046L,41047L,
96055 41048L,41049L,41050L,41051L,41052L,41053L,41054L,41055L,41056L,41057L,
96056 41058L,41059L,41060L,41061L,41062L,41063L,41064L,41065L,41066L,41067L,
96057 41068L,41069L,41070L,41071L,41072L,41073L,41074L,41075L,41076L,41077L,
96058 41078L,41079L,41080L,41081L,41082L,41083L,41084L,41085L,41086L,41087L,
96059 41088L,41089L,41090L,41091L,41092L,41093L,41094L,41095L,41096L,41097L,
96060 41098L,41099L,41100L,41101L,41102L,41103L,41104L,41105L,41106L,41107L,
96061 41108L,41109L,41110L,41111L,41112L,41113L,41114L,41115L,41116L,41117L,
96062 41118L,41119L,41120L,41121L,41122L,41123L,41124L,41125L,41126L,41127L,
96063 41128L,41129L,41130L,41131L,41132L,41133L,41134L,41135L,41136L,41137L,
96064 41138L,41139L,41140L,41141L,41142L,41143L,41144L,41145L,41146L,41147L,
96065 41148L,41149L,41150L,41151L,41152L,41153L,41154L,41155L,41156L,41157L,
96066 41158L,41159L,41160L,41161L,41162L,41163L,41164L,41165L,41166L,41167L,
96067 41168L,41169L,41170L,41171L,41172L,41173L,41174L,41175L,41176L,41177L,
96068 41178L,41179L,41180L,41181L,41182L,41183L,41184L,41185L,41186L,41187L,
96069 41188L,41189L,41190L,41191L,41192L,41193L,41194L,41195L,41196L,41197L,
96070 41198L,41199L,41200L,41201L,41202L,41203L,41204L,41205L,41206L,41207L,
96071 41208L,41209L,41210L,41211L,41212L,41213L,41214L,41215L,41216L,41217L,
96072 41218L,41219L,41220L,41221L,41222L,41223L,41224L,41225L,41226L,41227L,
96073 41228L,41229L,41230L,41231L,41232L,41233L,41234L,41235L,41236L,41237L,
96074 41238L,41239L,41240L,41241L,41242L,41243L,41244L,41245L,41246L,41247L,
96075 41248L,41249L,41250L,41251L,41252L,41253L,41254L,41255L,41256L,41257L,
96076 41258L,41259L,41260L,41261L,41262L,41263L,41264L,41265L,41266L,41267L,
96077 41268L,41269L,41270L,41271L,41272L,41273L,41274L,41275L,41276L,41277L,
96078 41278L,41279L,41280L,41281L,41282L,41283L,41284L,41285L,41286L,41287L,
96079 41288L,41289L,41290L,41291L,41292L,41293L,41294L,41295L,41296L,41297L,
96080 41298L,41299L,41300L,41301L,41302L,41303L,41304L,41305L,41306L,41307L,
96081 41308L,41309L,41310L,41311L,41312L,41313L,41314L,41315L,41316L,41317L,
96082 41318L,41319L,41320L,41321L,41322L,41323L,41324L,41325L,41326L,41327L,
96083 41328L,41329L,41330L,41331L,41332L,41333L,41334L,41335L,41336L,41337L,
96084 41338L,41339L,41340L,41341L,41342L,41343L,41344L,41345L,41346L,41347L,
96085 41348L,41349L,41350L,41351L,41352L,41353L,41354L,41355L,41356L,41357L,
96086 41358L,41359L,41360L,41361L,41362L,41363L,41364L,41365L,41366L,41367L,
96087 41368L,41369L,41370L,41371L,41372L,41373L,41374L,41375L,41376L,41377L,
96088 41378L,41379L,41380L,41381L,41382L,41383L,41384L,41385L,41386L,41387L,
96089 41388L,41389L,41390L,41391L,41392L,41393L,41394L,41395L,41396L,41397L,
96090 41398L,41399L,41400L,41401L,41402L,41403L,41404L,41405L,41406L,41407L,
96091 41408L,41409L,41410L,41411L,41412L,41413L,41414L,41415L,41416L,41417L,
96092 41418L,41419L,41420L,41421L,41422L,41423L,41424L,41425L,41426L,41427L,
96093 41428L,41429L,41430L,41431L,41432L,41433L,41434L,41435L,41436L,41437L,
96094 41438L,41439L,41440L,41441L,41442L,41443L,41444L,41445L,41446L,41447L,
96095 41448L,41449L,41450L,41451L,41452L,41453L,41454L,41455L,41456L,41457L,
96096 41458L,41459L,41460L,41461L,41462L,41463L,41464L,41465L,41466L,41467L,
96097 41468L,41469L,41470L,41471L,41472L,41473L,41474L,41475L,41476L,41477L,
96098 41478L,41479L,41480L,41481L,41482L,41483L,41484L,41485L,41486L,41487L,
96099 41488L,41489L,41490L,41491L,41492L,41493L,41494L,41495L,41496L,41497L,
96100 41498L,41499L,41500L,41501L,41502L,41503L,41504L,41505L,41506L,41507L,
96101 41508L,41509L,41510L,41511L,41512L,41513L,41514L,41515L,41516L,41517L,
96102 41518L,41519L,41520L,41521L,41522L,41523L,41524L,41525L,41526L,41527L,
96103 41528L,41529L,41530L,41531L,41532L,41533L,41534L,41535L,41536L,41537L,
96104 41538L,41539L,41540L,41541L,41542L,41543L,41544L,41545L,41546L,41547L,
96105 41548L,41549L,41550L,41551L,41552L,41553L,41554L,41555L,41556L,41557L,
96106 41558L,41559L,41560L,41561L,41562L,41563L,41564L,41565L,41566L,41567L,
96107 41568L,41569L,41570L,41571L,41572L,41573L,41574L,41575L,41576L,41577L,
96108 41578L,41579L,41580L,41581L,41582L,41583L,41584L,41585L,41586L,41587L,
96109 41588L,41589L,41590L,41591L,41592L,41593L,41594L,41595L,41596L,41597L,
96110 41598L,41599L,41600L,41601L,41602L,41603L,41604L,41605L,41606L,41607L,
96111 41608L,41609L,41610L,41611L,41612L,41613L,41614L,41615L,41616L,41617L,
96112 41618L,41619L,41620L,41621L,41622L,41623L,41624L,41625L,41626L,41627L,
96113 41628L,41629L,41630L,41631L,41632L,41633L,41634L,41635L,41636L,41637L,
96114 41638L,41639L,41640L,41641L,41642L,41643L,41644L,41645L,41646L,41647L,
96115 41648L,41649L,41650L,41651L,41652L,41653L,41654L,41655L,41656L,41657L,
96116 41658L,41659L,41660L,41661L,41662L,41663L,41664L,41665L,41666L,41667L,
96117 41668L,41669L,41670L,41671L,41672L,41673L,41674L,41675L,41676L,41677L,
96118 41678L,41679L,41680L,41681L,41682L,41683L,41684L,41685L,41686L,41687L,
96119 41688L,41689L,41690L,41691L,41692L,41693L,41694L,41695L,41696L,41697L,
96120 41698L,41699L,41700L,41701L,41702L,41703L,41704L,41705L,41706L,41707L,
96121 41708L,41709L,41710L,41711L,41712L,41713L,41714L,41715L,41716L,41717L,
96122 41718L,41719L,41720L,41721L,41722L,41723L,41724L,41725L,41726L,41727L,
96123 41728L,41729L,41730L,41731L,41732L,41733L,41734L,41735L,41736L,41737L,
96124 41738L,41739L,41740L,41741L,41742L,41743L,41744L,41745L,41746L,41747L,
96125 41748L,41749L,41750L,41751L,41752L,41753L,41754L,41755L,41756L,41757L,
96126 41758L,41759L,41760L,41761L,41762L,41763L,41764L,41765L,41766L,41767L,
96127 41768L,41769L,41770L,41771L,41772L,41773L,41774L,41775L,41776L,41777L,
96128 41778L,41779L,41780L,41781L,41782L,41783L,41784L,41785L,41786L,41787L,
96129 41788L,41789L,41790L,41791L,41792L,41793L,41794L,41795L,41796L,41797L,
96130 41798L,41799L,41800L,41801L,41802L,41803L,41804L,41805L,41806L,41807L,
96131 41808L,41809L,41810L,41811L,41812L,41813L,41814L,41815L,41816L,41817L,
96132 41818L,41819L,41820L,41821L,41822L,41823L,41824L,41825L,41826L,41827L,
96133 41828L,41829L,41830L,41831L,41832L,41833L,41834L,41835L,41836L,41837L,
96134 41838L,41839L,41840L,41841L,41842L,41843L,41844L,41845L,41846L,41847L,
96135 41848L,41849L,41850L,41851L,41852L,41853L,41854L,41855L,41856L,41857L,
96136 41858L,41859L,41860L,41861L,41862L,41863L,41864L,41865L,41866L,41867L,
96137 41868L,41869L,41870L,41871L,41872L,41873L,41874L,41875L,41876L,41877L,
96138 41878L,41879L,41880L,41881L,41882L,41883L,41884L,41885L,41886L,41887L,
96139 41888L,41889L,41890L,41891L,41892L,41893L,41894L,41895L,41896L,41897L,
96140 41898L,41899L,41900L,41901L,41902L,41903L,41904L,41905L,41906L,41907L,
96141 41908L,41909L,41910L,41911L,41912L,41913L,41914L,41915L,41916L,41917L,
96142 41918L,41919L,41920L,41921L,41922L,41923L,41924L,41925L,41926L,41927L,
96143 41928L,41929L,41930L,41931L,41932L,41933L,41934L,41935L,41936L,41937L,
96144 41938L,41939L,41940L,41941L,41942L,41943L,41944L,41945L,41946L,41947L,
96145 41948L,41949L,41950L,41951L,41952L,41953L,41954L,41955L,41956L,41957L,
96146 41958L,41959L,41960L,41961L,41962L,41963L,41964L,41965L,41966L,41967L,
96147 41968L,41969L,41970L,41971L,41972L,41973L,41974L,41975L,41976L,41977L,
96148 41978L,41979L,41980L,41981L,41982L,41983L,41984L,41985L,41986L,41987L,
96149 41988L,41989L,41990L,41991L,41992L,41993L,41994L,41995L,41996L,41997L,
96150 41998L,41999L,42000L,42001L,42002L,42003L,42004L,42005L,42006L,42007L,
96151 42008L,42009L,42010L,42011L,42012L,42013L,42014L,42015L,42016L,42017L,
96152 42018L,42019L,42020L,42021L,42022L,42023L,42024L,42025L,42026L,42027L,
96153 42028L,42029L,42030L,42031L,42032L,42033L,42034L,42035L,42036L,42037L,
96154 42038L,42039L,42040L,42041L,42042L,42043L,42044L,42045L,42046L,42047L,
96155 42048L,42049L,42050L,42051L,42052L,42053L,42054L,42055L,42056L,42057L,
96156 42058L,42059L,42060L,42061L,42062L,42063L,42064L,42065L,42066L,42067L,
96157 42068L,42069L,42070L,42071L,42072L,42073L,42074L,42075L,42076L,42077L,
96158 42078L,42079L,42080L,42081L,42082L,42083L,42084L,42085L,42086L,42087L,
96159 42088L,42089L,42090L,42091L,42092L,42093L,42094L,42095L,42096L,42097L,
96160 42098L,42099L,42100L,42101L,42102L,42103L,42104L,42105L,42106L,42107L,
96161 42108L,42109L,42110L,42111L,42112L,42113L,42114L,42115L,42116L,42117L,
96162 42118L,42119L,42120L,42121L,42122L,42123L,42124L,42125L,42126L,42127L,
96163 42128L,42129L,42130L,42131L,42132L,42133L,42134L,42135L,42136L,42137L,
96164 42138L,42139L,42140L,42141L,42142L,42143L,42144L,42145L,42146L,42147L,
96165 42148L,42149L,42150L,42151L,42152L,42153L,42154L,42155L,42156L,42157L,
96166 42158L,42159L,42160L,42161L,42162L,42163L,42164L,42165L,42166L,42167L,
96167 42168L,42169L,42170L,42171L,42172L,42173L,42174L,42175L,42176L,42177L,
96168 42178L,42179L,42180L,42181L,42182L,42183L,42184L,42185L,42186L,42187L,
96169 42188L,42189L,42190L,42191L,42192L,42193L,42194L,42195L,42196L,42197L,
96170 42198L,42199L,42200L,42201L,42202L,42203L,42204L,42205L,42206L,42207L,
96171 42208L,42209L,42210L,42211L,42212L,42213L,42214L,42215L,42216L,42217L,
96172 42218L,42219L,42220L,42221L,42222L,42223L,42224L,42225L,42226L,42227L,
96173 42228L,42229L,42230L,42231L,42232L,42233L,42234L,42235L,42236L,42237L,
96174 42238L,42239L,42240L,42241L,42242L,42243L,42244L,42245L,42246L,42247L,
96175 42248L,42249L,42250L,42251L,42252L,42253L,42254L,42255L,42256L,42257L,
96176 42258L,42259L,42260L,42261L,42262L,42263L,42264L,42265L,42266L,42267L,
96177 42268L,42269L,42270L,42271L,42272L,42273L,42274L,42275L,42276L,42277L,
96178 42278L,42279L,42280L,42281L,42282L,42283L,42284L,42285L,42286L,42287L,
96179 42288L,42289L,42290L,42291L,42292L,42293L,42294L,42295L,42296L,42297L,
96180 42298L,42299L,42300L,42301L,42302L,42303L,42304L,42305L,42306L,42307L,
96181 42308L,42309L,42310L,42311L,42312L,42313L,42314L,42315L,42316L,42317L,
96182 42318L,42319L,42320L,42321L,42322L,42323L,42324L,42325L,42326L,42327L,
96183 42328L,42329L,42330L,42331L,42332L,42333L,42334L,42335L,42336L,42337L,
96184 42338L,42339L,42340L,42341L,42342L,42343L,42344L,42345L,42346L,42347L,
96185 42348L,42349L,42350L,42351L,42352L,42353L,42354L,42355L,42356L,42357L,
96186 42358L,42359L,42360L,42361L,42362L,42363L,42364L,42365L,42366L,42367L,
96187 42368L,42369L,42370L,42371L,42372L,42373L,42374L,42375L,42376L,42377L,
96188 42378L,42379L,42380L,42381L,42382L,42383L,42384L,42385L,42386L,42387L,
96189 42388L,42389L,42390L,42391L,42392L,42393L,42394L,42395L,42396L,42397L,
96190 42398L,42399L,42400L,42401L,42402L,42403L,42404L,42405L,42406L,42407L,
96191 42408L,42409L,42410L,42411L,42412L,42413L,42414L,42415L,42416L,42417L,
96192 42418L,42419L,42420L,42421L,42422L,42423L,42424L,42425L,42426L,42427L,
96193 42428L,42429L,42430L,42431L,42432L,42433L,42434L,42435L,42436L,42437L,
96194 42438L,42439L,42440L,42441L,42442L,42443L,42444L,42445L,42446L,42447L,
96195 42448L,42449L,42450L,42451L,42452L,42453L,42454L,42455L,42456L,42457L,
96196 42458L,42459L,42460L,42461L,42462L,42463L,42464L,42465L,42466L,42467L,
96197 42468L,42469L,42470L,42471L,42472L,42473L,42474L,42475L,42476L,42477L,
96198 42478L,42479L,42480L,42481L,42482L,42483L,42484L,42485L,42486L,42487L,
96199 42488L,42489L,42490L,42491L,42492L,42493L,42494L,42495L,42496L,42497L,
96200 42498L,42499L,42500L,42501L,42502L,42503L,42504L,42505L,42506L,42507L,
96201 42508L,42509L,42510L,42511L,42512L,42513L,42514L,42515L,42516L,42517L,
96202 42518L,42519L,42520L,42521L,42522L,42523L,42524L,42525L,42526L,42527L,
96203 42528L,42529L,42530L,42531L,42532L,42533L,42534L,42535L,42536L,42537L,
96204 42538L,42539L,42540L,42541L,42542L,42543L,42544L,42545L,42546L,42547L,
96205 42548L,42549L,42550L,42551L,42552L,42553L,42554L,42555L,42556L,42557L,
96206 42558L,42559L,42560L,42560L,42562L,42562L,42564L,42564L,42566L,42566L,
96207 42568L,42568L,42570L,42570L,42572L,42572L,42574L,42574L,42576L,42576L,
96208 42578L,42578L,42580L,42580L,42582L,42582L,42584L,42584L,42586L,42586L,
96209 42588L,42588L,42590L,42590L,42592L,42592L,42594L,42594L,42596L,42596L,
96210 42598L,42598L,42600L,42600L,42602L,42602L,42604L,42604L,42606L,42607L,
96211 42608L,42609L,42610L,42611L,42612L,42613L,42614L,42615L,42616L,42617L,
96212 42618L,42619L,42620L,42621L,42622L,42623L,42624L,42624L,42626L,42626L,
96213 42628L,42628L,42630L,42630L,42632L,42632L,42634L,42634L,42636L,42636L,
96214 42638L,42638L,42640L,42640L,42642L,42642L,42644L,42644L,42646L,42646L,
96215 42648L,42648L,42650L,42650L,42652L,42653L,42654L,42655L,42656L,42657L,
96216 42658L,42659L,42660L,42661L,42662L,42663L,42664L,42665L,42666L,42667L,
96217 42668L,42669L,42670L,42671L,42672L,42673L,42674L,42675L,42676L,42677L,
96218 42678L,42679L,42680L,42681L,42682L,42683L,42684L,42685L,42686L,42687L,
96219 42688L,42689L,42690L,42691L,42692L,42693L,42694L,42695L,42696L,42697L,
96220 42698L,42699L,42700L,42701L,42702L,42703L,42704L,42705L,42706L,42707L,
96221 42708L,42709L,42710L,42711L,42712L,42713L,42714L,42715L,42716L,42717L,
96222 42718L,42719L,42720L,42721L,42722L,42723L,42724L,42725L,42726L,42727L,
96223 42728L,42729L,42730L,42731L,42732L,42733L,42734L,42735L,42736L,42737L,
96224 42738L,42739L,42740L,42741L,42742L,42743L,42744L,42745L,42746L,42747L,
96225 42748L,42749L,42750L,42751L,42752L,42753L,42754L,42755L,42756L,42757L,
96226 42758L,42759L,42760L,42761L,42762L,42763L,42764L,42765L,42766L,42767L,
96227 42768L,42769L,42770L,42771L,42772L,42773L,42774L,42775L,42776L,42777L,
96228 42778L,42779L,42780L,42781L,42782L,42783L,42784L,42785L,42786L,42786L,
96229 42788L,42788L,42790L,42790L,42792L,42792L,42794L,42794L,42796L,42796L,
96230 42798L,42798L,42800L,42801L,42802L,42802L,42804L,42804L,42806L,42806L,
96231 42808L,42808L,42810L,42810L,42812L,42812L,42814L,42814L,42816L,42816L,
96232 42818L,42818L,42820L,42820L,42822L,42822L,42824L,42824L,42826L,42826L,
96233 42828L,42828L,42830L,42830L,42832L,42832L,42834L,42834L,42836L,42836L,
96234 42838L,42838L,42840L,42840L,42842L,42842L,42844L,42844L,42846L,42846L,
96235 42848L,42848L,42850L,42850L,42852L,42852L,42854L,42854L,42856L,42856L,
96236 42858L,42858L,42860L,42860L,42862L,42862L,42864L,42865L,42866L,42867L,
96237 42868L,42869L,42870L,42871L,42872L,42873L,42873L,42875L,42875L,42877L,
96238 42878L,42878L,42880L,42880L,42882L,42882L,42884L,42884L,42886L,42886L,
96239 42888L,42889L,42890L,42891L,42891L,42893L,42894L,42895L,42896L,42896L,
96240 42898L,42898L,42948L,42901L,42902L,42902L,42904L,42904L,42906L,42906L,
96241 42908L,42908L,42910L,42910L,42912L,42912L,42914L,42914L,42916L,42916L,
96242 42918L,42918L,42920L,42920L,42922L,42923L,42924L,42925L,42926L,42927L,
96243 42928L,42929L,42930L,42931L,42932L,42932L,42934L,42934L,42936L,42936L,
96244 42938L,42938L,42940L,42940L,42942L,42942L,42944L,42945L,42946L,42946L,
96245 42948L,42949L,42950L,42951L,42952L,42953L,42954L,42955L,42956L,42957L,
96246 42958L,42959L,42960L,42961L,42962L,42963L,42964L,42965L,42966L,42967L,
96247 42968L,42969L,42970L,42971L,42972L,42973L,42974L,42975L,42976L,42977L,
96248 42978L,42979L,42980L,42981L,42982L,42983L,42984L,42985L,42986L,42987L,
96249 42988L,42989L,42990L,42991L,42992L,42993L,42994L,42995L,42996L,42997L,
96250 42998L,42999L,43000L,43001L,43002L,43003L,43004L,43005L,43006L,43007L,
96251 43008L,43009L,43010L,43011L,43012L,43013L,43014L,43015L,43016L,43017L,
96252 43018L,43019L,43020L,43021L,43022L,43023L,43024L,43025L,43026L,43027L,
96253 43028L,43029L,43030L,43031L,43032L,43033L,43034L,43035L,43036L,43037L,
96254 43038L,43039L,43040L,43041L,43042L,43043L,43044L,43045L,43046L,43047L,
96255 43048L,43049L,43050L,43051L,43052L,43053L,43054L,43055L,43056L,43057L,
96256 43058L,43059L,43060L,43061L,43062L,43063L,43064L,43065L,43066L,43067L,
96257 43068L,43069L,43070L,43071L,43072L,43073L,43074L,43075L,43076L,43077L,
96258 43078L,43079L,43080L,43081L,43082L,43083L,43084L,43085L,43086L,43087L,
96259 43088L,43089L,43090L,43091L,43092L,43093L,43094L,43095L,43096L,43097L,
96260 43098L,43099L,43100L,43101L,43102L,43103L,43104L,43105L,43106L,43107L,
96261 43108L,43109L,43110L,43111L,43112L,43113L,43114L,43115L,43116L,43117L,
96262 43118L,43119L,43120L,43121L,43122L,43123L,43124L,43125L,43126L,43127L,
96263 43128L,43129L,43130L,43131L,43132L,43133L,43134L,43135L,43136L,43137L,
96264 43138L,43139L,43140L,43141L,43142L,43143L,43144L,43145L,43146L,43147L,
96265 43148L,43149L,43150L,43151L,43152L,43153L,43154L,43155L,43156L,43157L,
96266 43158L,43159L,43160L,43161L,43162L,43163L,43164L,43165L,43166L,43167L,
96267 43168L,43169L,43170L,43171L,43172L,43173L,43174L,43175L,43176L,43177L,
96268 43178L,43179L,43180L,43181L,43182L,43183L,43184L,43185L,43186L,43187L,
96269 43188L,43189L,43190L,43191L,43192L,43193L,43194L,43195L,43196L,43197L,
96270 43198L,43199L,43200L,43201L,43202L,43203L,43204L,43205L,43206L,43207L,
96271 43208L,43209L,43210L,43211L,43212L,43213L,43214L,43215L,43216L,43217L,
96272 43218L,43219L,43220L,43221L,43222L,43223L,43224L,43225L,43226L,43227L,
96273 43228L,43229L,43230L,43231L,43232L,43233L,43234L,43235L,43236L,43237L,
96274 43238L,43239L,43240L,43241L,43242L,43243L,43244L,43245L,43246L,43247L,
96275 43248L,43249L,43250L,43251L,43252L,43253L,43254L,43255L,43256L,43257L,
96276 43258L,43259L,43260L,43261L,43262L,43263L,43264L,43265L,43266L,43267L,
96277 43268L,43269L,43270L,43271L,43272L,43273L,43274L,43275L,43276L,43277L,
96278 43278L,43279L,43280L,43281L,43282L,43283L,43284L,43285L,43286L,43287L,
96279 43288L,43289L,43290L,43291L,43292L,43293L,43294L,43295L,43296L,43297L,
96280 43298L,43299L,43300L,43301L,43302L,43303L,43304L,43305L,43306L,43307L,
96281 43308L,43309L,43310L,43311L,43312L,43313L,43314L,43315L,43316L,43317L,
96282 43318L,43319L,43320L,43321L,43322L,43323L,43324L,43325L,43326L,43327L,
96283 43328L,43329L,43330L,43331L,43332L,43333L,43334L,43335L,43336L,43337L,
96284 43338L,43339L,43340L,43341L,43342L,43343L,43344L,43345L,43346L,43347L,
96285 43348L,43349L,43350L,43351L,43352L,43353L,43354L,43355L,43356L,43357L,
96286 43358L,43359L,43360L,43361L,43362L,43363L,43364L,43365L,43366L,43367L,
96287 43368L,43369L,43370L,43371L,43372L,43373L,43374L,43375L,43376L,43377L,
96288 43378L,43379L,43380L,43381L,43382L,43383L,43384L,43385L,43386L,43387L,
96289 43388L,43389L,43390L,43391L,43392L,43393L,43394L,43395L,43396L,43397L,
96290 43398L,43399L,43400L,43401L,43402L,43403L,43404L,43405L,43406L,43407L,
96291 43408L,43409L,43410L,43411L,43412L,43413L,43414L,43415L,43416L,43417L,
96292 43418L,43419L,43420L,43421L,43422L,43423L,43424L,43425L,43426L,43427L,
96293 43428L,43429L,43430L,43431L,43432L,43433L,43434L,43435L,43436L,43437L,
96294 43438L,43439L,43440L,43441L,43442L,43443L,43444L,43445L,43446L,43447L,
96295 43448L,43449L,43450L,43451L,43452L,43453L,43454L,43455L,43456L,43457L,
96296 43458L,43459L,43460L,43461L,43462L,43463L,43464L,43465L,43466L,43467L,
96297 43468L,43469L,43470L,43471L,43472L,43473L,43474L,43475L,43476L,43477L,
96298 43478L,43479L,43480L,43481L,43482L,43483L,43484L,43485L,43486L,43487L,
96299 43488L,43489L,43490L,43491L,43492L,43493L,43494L,43495L,43496L,43497L,
96300 43498L,43499L,43500L,43501L,43502L,43503L,43504L,43505L,43506L,43507L,
96301 43508L,43509L,43510L,43511L,43512L,43513L,43514L,43515L,43516L,43517L,
96302 43518L,43519L,43520L,43521L,43522L,43523L,43524L,43525L,43526L,43527L,
96303 43528L,43529L,43530L,43531L,43532L,43533L,43534L,43535L,43536L,43537L,
96304 43538L,43539L,43540L,43541L,43542L,43543L,43544L,43545L,43546L,43547L,
96305 43548L,43549L,43550L,43551L,43552L,43553L,43554L,43555L,43556L,43557L,
96306 43558L,43559L,43560L,43561L,43562L,43563L,43564L,43565L,43566L,43567L,
96307 43568L,43569L,43570L,43571L,43572L,43573L,43574L,43575L,43576L,43577L,
96308 43578L,43579L,43580L,43581L,43582L,43583L,43584L,43585L,43586L,43587L,
96309 43588L,43589L,43590L,43591L,43592L,43593L,43594L,43595L,43596L,43597L,
96310 43598L,43599L,43600L,43601L,43602L,43603L,43604L,43605L,43606L,43607L,
96311 43608L,43609L,43610L,43611L,43612L,43613L,43614L,43615L,43616L,43617L,
96312 43618L,43619L,43620L,43621L,43622L,43623L,43624L,43625L,43626L,43627L,
96313 43628L,43629L,43630L,43631L,43632L,43633L,43634L,43635L,43636L,43637L,
96314 43638L,43639L,43640L,43641L,43642L,43643L,43644L,43645L,43646L,43647L,
96315 43648L,43649L,43650L,43651L,43652L,43653L,43654L,43655L,43656L,43657L,
96316 43658L,43659L,43660L,43661L,43662L,43663L,43664L,43665L,43666L,43667L,
96317 43668L,43669L,43670L,43671L,43672L,43673L,43674L,43675L,43676L,43677L,
96318 43678L,43679L,43680L,43681L,43682L,43683L,43684L,43685L,43686L,43687L,
96319 43688L,43689L,43690L,43691L,43692L,43693L,43694L,43695L,43696L,43697L,
96320 43698L,43699L,43700L,43701L,43702L,43703L,43704L,43705L,43706L,43707L,
96321 43708L,43709L,43710L,43711L,43712L,43713L,43714L,43715L,43716L,43717L,
96322 43718L,43719L,43720L,43721L,43722L,43723L,43724L,43725L,43726L,43727L,
96323 43728L,43729L,43730L,43731L,43732L,43733L,43734L,43735L,43736L,43737L,
96324 43738L,43739L,43740L,43741L,43742L,43743L,43744L,43745L,43746L,43747L,
96325 43748L,43749L,43750L,43751L,43752L,43753L,43754L,43755L,43756L,43757L,
96326 43758L,43759L,43760L,43761L,43762L,43763L,43764L,43765L,43766L,43767L,
96327 43768L,43769L,43770L,43771L,43772L,43773L,43774L,43775L,43776L,43777L,
96328 43778L,43779L,43780L,43781L,43782L,43783L,43784L,43785L,43786L,43787L,
96329 43788L,43789L,43790L,43791L,43792L,43793L,43794L,43795L,43796L,43797L,
96330 43798L,43799L,43800L,43801L,43802L,43803L,43804L,43805L,43806L,43807L,
96331 43808L,43809L,43810L,43811L,43812L,43813L,43814L,43815L,43816L,43817L,
96332 43818L,43819L,43820L,43821L,43822L,43823L,43824L,43825L,43826L,43827L,
96333 43828L,43829L,43830L,43831L,43832L,43833L,43834L,43835L,43836L,43837L,
96334 43838L,43839L,43840L,43841L,43842L,43843L,43844L,43845L,43846L,43847L,
96335 43848L,43849L,43850L,43851L,43852L,43853L,43854L,43855L,43856L,43857L,
96336 43858L,42931L,43860L,43861L,43862L,43863L,43864L,43865L,43866L,43867L,
96337 43868L,43869L,43870L,43871L,43872L,43873L,43874L,43875L,43876L,43877L,
96338 43878L,43879L,43880L,43881L,43882L,43883L,43884L,43885L,43886L,43887L,5024,
96339 5025,5026,5027,5028,5029,5030,5031,5032,5033,5034,5035,5036,5037,5038,5039,
96340 5040,5041,5042,5043,5044,5045,5046,5047,5048,5049,5050,5051,5052,5053,5054,
96341 5055,5056,5057,5058,5059,5060,5061,5062,5063,5064,5065,5066,5067,5068,5069,
96342 5070,5071,5072,5073,5074,5075,5076,5077,5078,5079,5080,5081,5082,5083,5084,
96343 5085,5086,5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,
96344 5100,5101,5102,5103,43968L,43969L,43970L,43971L,43972L,43973L,43974L,
96345 43975L,43976L,43977L,43978L,43979L,43980L,43981L,43982L,43983L,43984L,
96346 43985L,43986L,43987L,43988L,43989L,43990L,43991L,43992L,43993L,43994L,
96347 43995L,43996L,43997L,43998L,43999L,44000L,44001L,44002L,44003L,44004L,
96348 44005L,44006L,44007L,44008L,44009L,44010L,44011L,44012L,44013L,44014L,
96349 44015L,44016L,44017L,44018L,44019L,44020L,44021L,44022L,44023L,44024L,
96350 44025L,44026L,44027L,44028L,44029L,44030L,44031L,44032L,44033L,44034L,
96351 44035L,44036L,44037L,44038L,44039L,44040L,44041L,44042L,44043L,44044L,
96352 44045L,44046L,44047L,44048L,44049L,44050L,44051L,44052L,44053L,44054L,
96353 44055L,44056L,44057L,44058L,44059L,44060L,44061L,44062L,44063L,44064L,
96354 44065L,44066L,44067L,44068L,44069L,44070L,44071L,44072L,44073L,44074L,
96355 44075L,44076L,44077L,44078L,44079L,44080L,44081L,44082L,44083L,44084L,
96356 44085L,44086L,44087L,44088L,44089L,44090L,44091L,44092L,44093L,44094L,
96357 44095L,44096L,44097L,44098L,44099L,44100L,44101L,44102L,44103L,44104L,
96358 44105L,44106L,44107L,44108L,44109L,44110L,44111L,44112L,44113L,44114L,
96359 44115L,44116L,44117L,44118L,44119L,44120L,44121L,44122L,44123L,44124L,
96360 44125L,44126L,44127L,44128L,44129L,44130L,44131L,44132L,44133L,44134L,
96361 44135L,44136L,44137L,44138L,44139L,44140L,44141L,44142L,44143L,44144L,
96362 44145L,44146L,44147L,44148L,44149L,44150L,44151L,44152L,44153L,44154L,
96363 44155L,44156L,44157L,44158L,44159L,44160L,44161L,44162L,44163L,44164L,
96364 44165L,44166L,44167L,44168L,44169L,44170L,44171L,44172L,44173L,44174L,
96365 44175L,44176L,44177L,44178L,44179L,44180L,44181L,44182L,44183L,44184L,
96366 44185L,44186L,44187L,44188L,44189L,44190L,44191L,44192L,44193L,44194L,
96367 44195L,44196L,44197L,44198L,44199L,44200L,44201L,44202L,44203L,44204L,
96368 44205L,44206L,44207L,44208L,44209L,44210L,44211L,44212L,44213L,44214L,
96369 44215L,44216L,44217L,44218L,44219L,44220L,44221L,44222L,44223L,44224L,
96370 44225L,44226L,44227L,44228L,44229L,44230L,44231L,44232L,44233L,44234L,
96371 44235L,44236L,44237L,44238L,44239L,44240L,44241L,44242L,44243L,44244L,
96372 44245L,44246L,44247L,44248L,44249L,44250L,44251L,44252L,44253L,44254L,
96373 44255L,44256L,44257L,44258L,44259L,44260L,44261L,44262L,44263L,44264L,
96374 44265L,44266L,44267L,44268L,44269L,44270L,44271L,44272L,44273L,44274L,
96375 44275L,44276L,44277L,44278L,44279L,44280L,44281L,44282L,44283L,44284L,
96376 44285L,44286L,44287L,44288L,44289L,44290L,44291L,44292L,44293L,44294L,
96377 44295L,44296L,44297L,44298L,44299L,44300L,44301L,44302L,44303L,44304L,
96378 44305L,44306L,44307L,44308L,44309L,44310L,44311L,44312L,44313L,44314L,
96379 44315L,44316L,44317L,44318L,44319L,44320L,44321L,44322L,44323L,44324L,
96380 44325L,44326L,44327L,44328L,44329L,44330L,44331L,44332L,44333L,44334L,
96381 44335L,44336L,44337L,44338L,44339L,44340L,44341L,44342L,44343L,44344L,
96382 44345L,44346L,44347L,44348L,44349L,44350L,44351L,44352L,44353L,44354L,
96383 44355L,44356L,44357L,44358L,44359L,44360L,44361L,44362L,44363L,44364L,
96384 44365L,44366L,44367L,44368L,44369L,44370L,44371L,44372L,44373L,44374L,
96385 44375L,44376L,44377L,44378L,44379L,44380L,44381L,44382L,44383L,44384L,
96386 44385L,44386L,44387L,44388L,44389L,44390L,44391L,44392L,44393L,44394L,
96387 44395L,44396L,44397L,44398L,44399L,44400L,44401L,44402L,44403L,44404L,
96388 44405L,44406L,44407L,44408L,44409L,44410L,44411L,44412L,44413L,44414L,
96389 44415L,44416L,44417L,44418L,44419L,44420L,44421L,44422L,44423L,44424L,
96390 44425L,44426L,44427L,44428L,44429L,44430L,44431L,44432L,44433L,44434L,
96391 44435L,44436L,44437L,44438L,44439L,44440L,44441L,44442L,44443L,44444L,
96392 44445L,44446L,44447L,44448L,44449L,44450L,44451L,44452L,44453L,44454L,
96393 44455L,44456L,44457L,44458L,44459L,44460L,44461L,44462L,44463L,44464L,
96394 44465L,44466L,44467L,44468L,44469L,44470L,44471L,44472L,44473L,44474L,
96395 44475L,44476L,44477L,44478L,44479L,44480L,44481L,44482L,44483L,44484L,
96396 44485L,44486L,44487L,44488L,44489L,44490L,44491L,44492L,44493L,44494L,
96397 44495L,44496L,44497L,44498L,44499L,44500L,44501L,44502L,44503L,44504L,
96398 44505L,44506L,44507L,44508L,44509L,44510L,44511L,44512L,44513L,44514L,
96399 44515L,44516L,44517L,44518L,44519L,44520L,44521L,44522L,44523L,44524L,
96400 44525L,44526L,44527L,44528L,44529L,44530L,44531L,44532L,44533L,44534L,
96401 44535L,44536L,44537L,44538L,44539L,44540L,44541L,44542L,44543L,44544L,
96402 44545L,44546L,44547L,44548L,44549L,44550L,44551L,44552L,44553L,44554L,
96403 44555L,44556L,44557L,44558L,44559L,44560L,44561L,44562L,44563L,44564L,
96404 44565L,44566L,44567L,44568L,44569L,44570L,44571L,44572L,44573L,44574L,
96405 44575L,44576L,44577L,44578L,44579L,44580L,44581L,44582L,44583L,44584L,
96406 44585L,44586L,44587L,44588L,44589L,44590L,44591L,44592L,44593L,44594L,
96407 44595L,44596L,44597L,44598L,44599L,44600L,44601L,44602L,44603L,44604L,
96408 44605L,44606L,44607L,44608L,44609L,44610L,44611L,44612L,44613L,44614L,
96409 44615L,44616L,44617L,44618L,44619L,44620L,44621L,44622L,44623L,44624L,
96410 44625L,44626L,44627L,44628L,44629L,44630L,44631L,44632L,44633L,44634L,
96411 44635L,44636L,44637L,44638L,44639L,44640L,44641L,44642L,44643L,44644L,
96412 44645L,44646L,44647L,44648L,44649L,44650L,44651L,44652L,44653L,44654L,
96413 44655L,44656L,44657L,44658L,44659L,44660L,44661L,44662L,44663L,44664L,
96414 44665L,44666L,44667L,44668L,44669L,44670L,44671L,44672L,44673L,44674L,
96415 44675L,44676L,44677L,44678L,44679L,44680L,44681L,44682L,44683L,44684L,
96416 44685L,44686L,44687L,44688L,44689L,44690L,44691L,44692L,44693L,44694L,
96417 44695L,44696L,44697L,44698L,44699L,44700L,44701L,44702L,44703L,44704L,
96418 44705L,44706L,44707L,44708L,44709L,44710L,44711L,44712L,44713L,44714L,
96419 44715L,44716L,44717L,44718L,44719L,44720L,44721L,44722L,44723L,44724L,
96420 44725L,44726L,44727L,44728L,44729L,44730L,44731L,44732L,44733L,44734L,
96421 44735L,44736L,44737L,44738L,44739L,44740L,44741L,44742L,44743L,44744L,
96422 44745L,44746L,44747L,44748L,44749L,44750L,44751L,44752L,44753L,44754L,
96423 44755L,44756L,44757L,44758L,44759L,44760L,44761L,44762L,44763L,44764L,
96424 44765L,44766L,44767L,44768L,44769L,44770L,44771L,44772L,44773L,44774L,
96425 44775L,44776L,44777L,44778L,44779L,44780L,44781L,44782L,44783L,44784L,
96426 44785L,44786L,44787L,44788L,44789L,44790L,44791L,44792L,44793L,44794L,
96427 44795L,44796L,44797L,44798L,44799L,44800L,44801L,44802L,44803L,44804L,
96428 44805L,44806L,44807L,44808L,44809L,44810L,44811L,44812L,44813L,44814L,
96429 44815L,44816L,44817L,44818L,44819L,44820L,44821L,44822L,44823L,44824L,
96430 44825L,44826L,44827L,44828L,44829L,44830L,44831L,44832L,44833L,44834L,
96431 44835L,44836L,44837L,44838L,44839L,44840L,44841L,44842L,44843L,44844L,
96432 44845L,44846L,44847L,44848L,44849L,44850L,44851L,44852L,44853L,44854L,
96433 44855L,44856L,44857L,44858L,44859L,44860L,44861L,44862L,44863L,44864L,
96434 44865L,44866L,44867L,44868L,44869L,44870L,44871L,44872L,44873L,44874L,
96435 44875L,44876L,44877L,44878L,44879L,44880L,44881L,44882L,44883L,44884L,
96436 44885L,44886L,44887L,44888L,44889L,44890L,44891L,44892L,44893L,44894L,
96437 44895L,44896L,44897L,44898L,44899L,44900L,44901L,44902L,44903L,44904L,
96438 44905L,44906L,44907L,44908L,44909L,44910L,44911L,44912L,44913L,44914L,
96439 44915L,44916L,44917L,44918L,44919L,44920L,44921L,44922L,44923L,44924L,
96440 44925L,44926L,44927L,44928L,44929L,44930L,44931L,44932L,44933L,44934L,
96441 44935L,44936L,44937L,44938L,44939L,44940L,44941L,44942L,44943L,44944L,
96442 44945L,44946L,44947L,44948L,44949L,44950L,44951L,44952L,44953L,44954L,
96443 44955L,44956L,44957L,44958L,44959L,44960L,44961L,44962L,44963L,44964L,
96444 44965L,44966L,44967L,44968L,44969L,44970L,44971L,44972L,44973L,44974L,
96445 44975L,44976L,44977L,44978L,44979L,44980L,44981L,44982L,44983L,44984L,
96446 44985L,44986L,44987L,44988L,44989L,44990L,44991L,44992L,44993L,44994L,
96447 44995L,44996L,44997L,44998L,44999L,45000L,45001L,45002L,45003L,45004L,
96448 45005L,45006L,45007L,45008L,45009L,45010L,45011L,45012L,45013L,45014L,
96449 45015L,45016L,45017L,45018L,45019L,45020L,45021L,45022L,45023L,45024L,
96450 45025L,45026L,45027L,45028L,45029L,45030L,45031L,45032L,45033L,45034L,
96451 45035L,45036L,45037L,45038L,45039L,45040L,45041L,45042L,45043L,45044L,
96452 45045L,45046L,45047L,45048L,45049L,45050L,45051L,45052L,45053L,45054L,
96453 45055L,45056L,45057L,45058L,45059L,45060L,45061L,45062L,45063L,45064L,
96454 45065L,45066L,45067L,45068L,45069L,45070L,45071L,45072L,45073L,45074L,
96455 45075L,45076L,45077L,45078L,45079L,45080L,45081L,45082L,45083L,45084L,
96456 45085L,45086L,45087L,45088L,45089L,45090L,45091L,45092L,45093L,45094L,
96457 45095L,45096L,45097L,45098L,45099L,45100L,45101L,45102L,45103L,45104L,
96458 45105L,45106L,45107L,45108L,45109L,45110L,45111L,45112L,45113L,45114L,
96459 45115L,45116L,45117L,45118L,45119L,45120L,45121L,45122L,45123L,45124L,
96460 45125L,45126L,45127L,45128L,45129L,45130L,45131L,45132L,45133L,45134L,
96461 45135L,45136L,45137L,45138L,45139L,45140L,45141L,45142L,45143L,45144L,
96462 45145L,45146L,45147L,45148L,45149L,45150L,45151L,45152L,45153L,45154L,
96463 45155L,45156L,45157L,45158L,45159L,45160L,45161L,45162L,45163L,45164L,
96464 45165L,45166L,45167L,45168L,45169L,45170L,45171L,45172L,45173L,45174L,
96465 45175L,45176L,45177L,45178L,45179L,45180L,45181L,45182L,45183L,45184L,
96466 45185L,45186L,45187L,45188L,45189L,45190L,45191L,45192L,45193L,45194L,
96467 45195L,45196L,45197L,45198L,45199L,45200L,45201L,45202L,45203L,45204L,
96468 45205L,45206L,45207L,45208L,45209L,45210L,45211L,45212L,45213L,45214L,
96469 45215L,45216L,45217L,45218L,45219L,45220L,45221L,45222L,45223L,45224L,
96470 45225L,45226L,45227L,45228L,45229L,45230L,45231L,45232L,45233L,45234L,
96471 45235L,45236L,45237L,45238L,45239L,45240L,45241L,45242L,45243L,45244L,
96472 45245L,45246L,45247L,45248L,45249L,45250L,45251L,45252L,45253L,45254L,
96473 45255L,45256L,45257L,45258L,45259L,45260L,45261L,45262L,45263L,45264L,
96474 45265L,45266L,45267L,45268L,45269L,45270L,45271L,45272L,45273L,45274L,
96475 45275L,45276L,45277L,45278L,45279L,45280L,45281L,45282L,45283L,45284L,
96476 45285L,45286L,45287L,45288L,45289L,45290L,45291L,45292L,45293L,45294L,
96477 45295L,45296L,45297L,45298L,45299L,45300L,45301L,45302L,45303L,45304L,
96478 45305L,45306L,45307L,45308L,45309L,45310L,45311L,45312L,45313L,45314L,
96479 45315L,45316L,45317L,45318L,45319L,45320L,45321L,45322L,45323L,45324L,
96480 45325L,45326L,45327L,45328L,45329L,45330L,45331L,45332L,45333L,45334L,
96481 45335L,45336L,45337L,45338L,45339L,45340L,45341L,45342L,45343L,45344L,
96482 45345L,45346L,45347L,45348L,45349L,45350L,45351L,45352L,45353L,45354L,
96483 45355L,45356L,45357L,45358L,45359L,45360L,45361L,45362L,45363L,45364L,
96484 45365L,45366L,45367L,45368L,45369L,45370L,45371L,45372L,45373L,45374L,
96485 45375L,45376L,45377L,45378L,45379L,45380L,45381L,45382L,45383L,45384L,
96486 45385L,45386L,45387L,45388L,45389L,45390L,45391L,45392L,45393L,45394L,
96487 45395L,45396L,45397L,45398L,45399L,45400L,45401L,45402L,45403L,45404L,
96488 45405L,45406L,45407L,45408L,45409L,45410L,45411L,45412L,45413L,45414L,
96489 45415L,45416L,45417L,45418L,45419L,45420L,45421L,45422L,45423L,45424L,
96490 45425L,45426L,45427L,45428L,45429L,45430L,45431L,45432L,45433L,45434L,
96491 45435L,45436L,45437L,45438L,45439L,45440L,45441L,45442L,45443L,45444L,
96492 45445L,45446L,45447L,45448L,45449L,45450L,45451L,45452L,45453L,45454L,
96493 45455L,45456L,45457L,45458L,45459L,45460L,45461L,45462L,45463L,45464L,
96494 45465L,45466L,45467L,45468L,45469L,45470L,45471L,45472L,45473L,45474L,
96495 45475L,45476L,45477L,45478L,45479L,45480L,45481L,45482L,45483L,45484L,
96496 45485L,45486L,45487L,45488L,45489L,45490L,45491L,45492L,45493L,45494L,
96497 45495L,45496L,45497L,45498L,45499L,45500L,45501L,45502L,45503L,45504L,
96498 45505L,45506L,45507L,45508L,45509L,45510L,45511L,45512L,45513L,45514L,
96499 45515L,45516L,45517L,45518L,45519L,45520L,45521L,45522L,45523L,45524L,
96500 45525L,45526L,45527L,45528L,45529L,45530L,45531L,45532L,45533L,45534L,
96501 45535L,45536L,45537L,45538L,45539L,45540L,45541L,45542L,45543L,45544L,
96502 45545L,45546L,45547L,45548L,45549L,45550L,45551L,45552L,45553L,45554L,
96503 45555L,45556L,45557L,45558L,45559L,45560L,45561L,45562L,45563L,45564L,
96504 45565L,45566L,45567L,45568L,45569L,45570L,45571L,45572L,45573L,45574L,
96505 45575L,45576L,45577L,45578L,45579L,45580L,45581L,45582L,45583L,45584L,
96506 45585L,45586L,45587L,45588L,45589L,45590L,45591L,45592L,45593L,45594L,
96507 45595L,45596L,45597L,45598L,45599L,45600L,45601L,45602L,45603L,45604L,
96508 45605L,45606L,45607L,45608L,45609L,45610L,45611L,45612L,45613L,45614L,
96509 45615L,45616L,45617L,45618L,45619L,45620L,45621L,45622L,45623L,45624L,
96510 45625L,45626L,45627L,45628L,45629L,45630L,45631L,45632L,45633L,45634L,
96511 45635L,45636L,45637L,45638L,45639L,45640L,45641L,45642L,45643L,45644L,
96512 45645L,45646L,45647L,45648L,45649L,45650L,45651L,45652L,45653L,45654L,
96513 45655L,45656L,45657L,45658L,45659L,45660L,45661L,45662L,45663L,45664L,
96514 45665L,45666L,45667L,45668L,45669L,45670L,45671L,45672L,45673L,45674L,
96515 45675L,45676L,45677L,45678L,45679L,45680L,45681L,45682L,45683L,45684L,
96516 45685L,45686L,45687L,45688L,45689L,45690L,45691L,45692L,45693L,45694L,
96517 45695L,45696L,45697L,45698L,45699L,45700L,45701L,45702L,45703L,45704L,
96518 45705L,45706L,45707L,45708L,45709L,45710L,45711L,45712L,45713L,45714L,
96519 45715L,45716L,45717L,45718L,45719L,45720L,45721L,45722L,45723L,45724L,
96520 45725L,45726L,45727L,45728L,45729L,45730L,45731L,45732L,45733L,45734L,
96521 45735L,45736L,45737L,45738L,45739L,45740L,45741L,45742L,45743L,45744L,
96522 45745L,45746L,45747L,45748L,45749L,45750L,45751L,45752L,45753L,45754L,
96523 45755L,45756L,45757L,45758L,45759L,45760L,45761L,45762L,45763L,45764L,
96524 45765L,45766L,45767L,45768L,45769L,45770L,45771L,45772L,45773L,45774L,
96525 45775L,45776L,45777L,45778L,45779L,45780L,45781L,45782L,45783L,45784L,
96526 45785L,45786L,45787L,45788L,45789L,45790L,45791L,45792L,45793L,45794L,
96527 45795L,45796L,45797L,45798L,45799L,45800L,45801L,45802L,45803L,45804L,
96528 45805L,45806L,45807L,45808L,45809L,45810L,45811L,45812L,45813L,45814L,
96529 45815L,45816L,45817L,45818L,45819L,45820L,45821L,45822L,45823L,45824L,
96530 45825L,45826L,45827L,45828L,45829L,45830L,45831L,45832L,45833L,45834L,
96531 45835L,45836L,45837L,45838L,45839L,45840L,45841L,45842L,45843L,45844L,
96532 45845L,45846L,45847L,45848L,45849L,45850L,45851L,45852L,45853L,45854L,
96533 45855L,45856L,45857L,45858L,45859L,45860L,45861L,45862L,45863L,45864L,
96534 45865L,45866L,45867L,45868L,45869L,45870L,45871L,45872L,45873L,45874L,
96535 45875L,45876L,45877L,45878L,45879L,45880L,45881L,45882L,45883L,45884L,
96536 45885L,45886L,45887L,45888L,45889L,45890L,45891L,45892L,45893L,45894L,
96537 45895L,45896L,45897L,45898L,45899L,45900L,45901L,45902L,45903L,45904L,
96538 45905L,45906L,45907L,45908L,45909L,45910L,45911L,45912L,45913L,45914L,
96539 45915L,45916L,45917L,45918L,45919L,45920L,45921L,45922L,45923L,45924L,
96540 45925L,45926L,45927L,45928L,45929L,45930L,45931L,45932L,45933L,45934L,
96541 45935L,45936L,45937L,45938L,45939L,45940L,45941L,45942L,45943L,45944L,
96542 45945L,45946L,45947L,45948L,45949L,45950L,45951L,45952L,45953L,45954L,
96543 45955L,45956L,45957L,45958L,45959L,45960L,45961L,45962L,45963L,45964L,
96544 45965L,45966L,45967L,45968L,45969L,45970L,45971L,45972L,45973L,45974L,
96545 45975L,45976L,45977L,45978L,45979L,45980L,45981L,45982L,45983L,45984L,
96546 45985L,45986L,45987L,45988L,45989L,45990L,45991L,45992L,45993L,45994L,
96547 45995L,45996L,45997L,45998L,45999L,46000L,46001L,46002L,46003L,46004L,
96548 46005L,46006L,46007L,46008L,46009L,46010L,46011L,46012L,46013L,46014L,
96549 46015L,46016L,46017L,46018L,46019L,46020L,46021L,46022L,46023L,46024L,
96550 46025L,46026L,46027L,46028L,46029L,46030L,46031L,46032L,46033L,46034L,
96551 46035L,46036L,46037L,46038L,46039L,46040L,46041L,46042L,46043L,46044L,
96552 46045L,46046L,46047L,46048L,46049L,46050L,46051L,46052L,46053L,46054L,
96553 46055L,46056L,46057L,46058L,46059L,46060L,46061L,46062L,46063L,46064L,
96554 46065L,46066L,46067L,46068L,46069L,46070L,46071L,46072L,46073L,46074L,
96555 46075L,46076L,46077L,46078L,46079L,46080L,46081L,46082L,46083L,46084L,
96556 46085L,46086L,46087L,46088L,46089L,46090L,46091L,46092L,46093L,46094L,
96557 46095L,46096L,46097L,46098L,46099L,46100L,46101L,46102L,46103L,46104L,
96558 46105L,46106L,46107L,46108L,46109L,46110L,46111L,46112L,46113L,46114L,
96559 46115L,46116L,46117L,46118L,46119L,46120L,46121L,46122L,46123L,46124L,
96560 46125L,46126L,46127L,46128L,46129L,46130L,46131L,46132L,46133L,46134L,
96561 46135L,46136L,46137L,46138L,46139L,46140L,46141L,46142L,46143L,46144L,
96562 46145L,46146L,46147L,46148L,46149L,46150L,46151L,46152L,46153L,46154L,
96563 46155L,46156L,46157L,46158L,46159L,46160L,46161L,46162L,46163L,46164L,
96564 46165L,46166L,46167L,46168L,46169L,46170L,46171L,46172L,46173L,46174L,
96565 46175L,46176L,46177L,46178L,46179L,46180L,46181L,46182L,46183L,46184L,
96566 46185L,46186L,46187L,46188L,46189L,46190L,46191L,46192L,46193L,46194L,
96567 46195L,46196L,46197L,46198L,46199L,46200L,46201L,46202L,46203L,46204L,
96568 46205L,46206L,46207L,46208L,46209L,46210L,46211L,46212L,46213L,46214L,
96569 46215L,46216L,46217L,46218L,46219L,46220L,46221L,46222L,46223L,46224L,
96570 46225L,46226L,46227L,46228L,46229L,46230L,46231L,46232L,46233L,46234L,
96571 46235L,46236L,46237L,46238L,46239L,46240L,46241L,46242L,46243L,46244L,
96572 46245L,46246L,46247L,46248L,46249L,46250L,46251L,46252L,46253L,46254L,
96573 46255L,46256L,46257L,46258L,46259L,46260L,46261L,46262L,46263L,46264L,
96574 46265L,46266L,46267L,46268L,46269L,46270L,46271L,46272L,46273L,46274L,
96575 46275L,46276L,46277L,46278L,46279L,46280L,46281L,46282L,46283L,46284L,
96576 46285L,46286L,46287L,46288L,46289L,46290L,46291L,46292L,46293L,46294L,
96577 46295L,46296L,46297L,46298L,46299L,46300L,46301L,46302L,46303L,46304L,
96578 46305L,46306L,46307L,46308L,46309L,46310L,46311L,46312L,46313L,46314L,
96579 46315L,46316L,46317L,46318L,46319L,46320L,46321L,46322L,46323L,46324L,
96580 46325L,46326L,46327L,46328L,46329L,46330L,46331L,46332L,46333L,46334L,
96581 46335L,46336L,46337L,46338L,46339L,46340L,46341L,46342L,46343L,46344L,
96582 46345L,46346L,46347L,46348L,46349L,46350L,46351L,46352L,46353L,46354L,
96583 46355L,46356L,46357L,46358L,46359L,46360L,46361L,46362L,46363L,46364L,
96584 46365L,46366L,46367L,46368L,46369L,46370L,46371L,46372L,46373L,46374L,
96585 46375L,46376L,46377L,46378L,46379L,46380L,46381L,46382L,46383L,46384L,
96586 46385L,46386L,46387L,46388L,46389L,46390L,46391L,46392L,46393L,46394L,
96587 46395L,46396L,46397L,46398L,46399L,46400L,46401L,46402L,46403L,46404L,
96588 46405L,46406L,46407L,46408L,46409L,46410L,46411L,46412L,46413L,46414L,
96589 46415L,46416L,46417L,46418L,46419L,46420L,46421L,46422L,46423L,46424L,
96590 46425L,46426L,46427L,46428L,46429L,46430L,46431L,46432L,46433L,46434L,
96591 46435L,46436L,46437L,46438L,46439L,46440L,46441L,46442L,46443L,46444L,
96592 46445L,46446L,46447L,46448L,46449L,46450L,46451L,46452L,46453L,46454L,
96593 46455L,46456L,46457L,46458L,46459L,46460L,46461L,46462L,46463L,46464L,
96594 46465L,46466L,46467L,46468L,46469L,46470L,46471L,46472L,46473L,46474L,
96595 46475L,46476L,46477L,46478L,46479L,46480L,46481L,46482L,46483L,46484L,
96596 46485L,46486L,46487L,46488L,46489L,46490L,46491L,46492L,46493L,46494L,
96597 46495L,46496L,46497L,46498L,46499L,46500L,46501L,46502L,46503L,46504L,
96598 46505L,46506L,46507L,46508L,46509L,46510L,46511L,46512L,46513L,46514L,
96599 46515L,46516L,46517L,46518L,46519L,46520L,46521L,46522L,46523L,46524L,
96600 46525L,46526L,46527L,46528L,46529L,46530L,46531L,46532L,46533L,46534L,
96601 46535L,46536L,46537L,46538L,46539L,46540L,46541L,46542L,46543L,46544L,
96602 46545L,46546L,46547L,46548L,46549L,46550L,46551L,46552L,46553L,46554L,
96603 46555L,46556L,46557L,46558L,46559L,46560L,46561L,46562L,46563L,46564L,
96604 46565L,46566L,46567L,46568L,46569L,46570L,46571L,46572L,46573L,46574L,
96605 46575L,46576L,46577L,46578L,46579L,46580L,46581L,46582L,46583L,46584L,
96606 46585L,46586L,46587L,46588L,46589L,46590L,46591L,46592L,46593L,46594L,
96607 46595L,46596L,46597L,46598L,46599L,46600L,46601L,46602L,46603L,46604L,
96608 46605L,46606L,46607L,46608L,46609L,46610L,46611L,46612L,46613L,46614L,
96609 46615L,46616L,46617L,46618L,46619L,46620L,46621L,46622L,46623L,46624L,
96610 46625L,46626L,46627L,46628L,46629L,46630L,46631L,46632L,46633L,46634L,
96611 46635L,46636L,46637L,46638L,46639L,46640L,46641L,46642L,46643L,46644L,
96612 46645L,46646L,46647L,46648L,46649L,46650L,46651L,46652L,46653L,46654L,
96613 46655L,46656L,46657L,46658L,46659L,46660L,46661L,46662L,46663L,46664L,
96614 46665L,46666L,46667L,46668L,46669L,46670L,46671L,46672L,46673L,46674L,
96615 46675L,46676L,46677L,46678L,46679L,46680L,46681L,46682L,46683L,46684L,
96616 46685L,46686L,46687L,46688L,46689L,46690L,46691L,46692L,46693L,46694L,
96617 46695L,46696L,46697L,46698L,46699L,46700L,46701L,46702L,46703L,46704L,
96618 46705L,46706L,46707L,46708L,46709L,46710L,46711L,46712L,46713L,46714L,
96619 46715L,46716L,46717L,46718L,46719L,46720L,46721L,46722L,46723L,46724L,
96620 46725L,46726L,46727L,46728L,46729L,46730L,46731L,46732L,46733L,46734L,
96621 46735L,46736L,46737L,46738L,46739L,46740L,46741L,46742L,46743L,46744L,
96622 46745L,46746L,46747L,46748L,46749L,46750L,46751L,46752L,46753L,46754L,
96623 46755L,46756L,46757L,46758L,46759L,46760L,46761L,46762L,46763L,46764L,
96624 46765L,46766L,46767L,46768L,46769L,46770L,46771L,46772L,46773L,46774L,
96625 46775L,46776L,46777L,46778L,46779L,46780L,46781L,46782L,46783L,46784L,
96626 46785L,46786L,46787L,46788L,46789L,46790L,46791L,46792L,46793L,46794L,
96627 46795L,46796L,46797L,46798L,46799L,46800L,46801L,46802L,46803L,46804L,
96628 46805L,46806L,46807L,46808L,46809L,46810L,46811L,46812L,46813L,46814L,
96629 46815L,46816L,46817L,46818L,46819L,46820L,46821L,46822L,46823L,46824L,
96630 46825L,46826L,46827L,46828L,46829L,46830L,46831L,46832L,46833L,46834L,
96631 46835L,46836L,46837L,46838L,46839L,46840L,46841L,46842L,46843L,46844L,
96632 46845L,46846L,46847L,46848L,46849L,46850L,46851L,46852L,46853L,46854L,
96633 46855L,46856L,46857L,46858L,46859L,46860L,46861L,46862L,46863L,46864L,
96634 46865L,46866L,46867L,46868L,46869L,46870L,46871L,46872L,46873L,46874L,
96635 46875L,46876L,46877L,46878L,46879L,46880L,46881L,46882L,46883L,46884L,
96636 46885L,46886L,46887L,46888L,46889L,46890L,46891L,46892L,46893L,46894L,
96637 46895L,46896L,46897L,46898L,46899L,46900L,46901L,46902L,46903L,46904L,
96638 46905L,46906L,46907L,46908L,46909L,46910L,46911L,46912L,46913L,46914L,
96639 46915L,46916L,46917L,46918L,46919L,46920L,46921L,46922L,46923L,46924L,
96640 46925L,46926L,46927L,46928L,46929L,46930L,46931L,46932L,46933L,46934L,
96641 46935L,46936L,46937L,46938L,46939L,46940L,46941L,46942L,46943L,46944L,
96642 46945L,46946L,46947L,46948L,46949L,46950L,46951L,46952L,46953L,46954L,
96643 46955L,46956L,46957L,46958L,46959L,46960L,46961L,46962L,46963L,46964L,
96644 46965L,46966L,46967L,46968L,46969L,46970L,46971L,46972L,46973L,46974L,
96645 46975L,46976L,46977L,46978L,46979L,46980L,46981L,46982L,46983L,46984L,
96646 46985L,46986L,46987L,46988L,46989L,46990L,46991L,46992L,46993L,46994L,
96647 46995L,46996L,46997L,46998L,46999L,47000L,47001L,47002L,47003L,47004L,
96648 47005L,47006L,47007L,47008L,47009L,47010L,47011L,47012L,47013L,47014L,
96649 47015L,47016L,47017L,47018L,47019L,47020L,47021L,47022L,47023L,47024L,
96650 47025L,47026L,47027L,47028L,47029L,47030L,47031L,47032L,47033L,47034L,
96651 47035L,47036L,47037L,47038L,47039L,47040L,47041L,47042L,47043L,47044L,
96652 47045L,47046L,47047L,47048L,47049L,47050L,47051L,47052L,47053L,47054L,
96653 47055L,47056L,47057L,47058L,47059L,47060L,47061L,47062L,47063L,47064L,
96654 47065L,47066L,47067L,47068L,47069L,47070L,47071L,47072L,47073L,47074L,
96655 47075L,47076L,47077L,47078L,47079L,47080L,47081L,47082L,47083L,47084L,
96656 47085L,47086L,47087L,47088L,47089L,47090L,47091L,47092L,47093L,47094L,
96657 47095L,47096L,47097L,47098L,47099L,47100L,47101L,47102L,47103L,47104L,
96658 47105L,47106L,47107L,47108L,47109L,47110L,47111L,47112L,47113L,47114L,
96659 47115L,47116L,47117L,47118L,47119L,47120L,47121L,47122L,47123L,47124L,
96660 47125L,47126L,47127L,47128L,47129L,47130L,47131L,47132L,47133L,47134L,
96661 47135L,47136L,47137L,47138L,47139L,47140L,47141L,47142L,47143L,47144L,
96662 47145L,47146L,47147L,47148L,47149L,47150L,47151L,47152L,47153L,47154L,
96663 47155L,47156L,47157L,47158L,47159L,47160L,47161L,47162L,47163L,47164L,
96664 47165L,47166L,47167L,47168L,47169L,47170L,47171L,47172L,47173L,47174L,
96665 47175L,47176L,47177L,47178L,47179L,47180L,47181L,47182L,47183L,47184L,
96666 47185L,47186L,47187L,47188L,47189L,47190L,47191L,47192L,47193L,47194L,
96667 47195L,47196L,47197L,47198L,47199L,47200L,47201L,47202L,47203L,47204L,
96668 47205L,47206L,47207L,47208L,47209L,47210L,47211L,47212L,47213L,47214L,
96669 47215L,47216L,47217L,47218L,47219L,47220L,47221L,47222L,47223L,47224L,
96670 47225L,47226L,47227L,47228L,47229L,47230L,47231L,47232L,47233L,47234L,
96671 47235L,47236L,47237L,47238L,47239L,47240L,47241L,47242L,47243L,47244L,
96672 47245L,47246L,47247L,47248L,47249L,47250L,47251L,47252L,47253L,47254L,
96673 47255L,47256L,47257L,47258L,47259L,47260L,47261L,47262L,47263L,47264L,
96674 47265L,47266L,47267L,47268L,47269L,47270L,47271L,47272L,47273L,47274L,
96675 47275L,47276L,47277L,47278L,47279L,47280L,47281L,47282L,47283L,47284L,
96676 47285L,47286L,47287L,47288L,47289L,47290L,47291L,47292L,47293L,47294L,
96677 47295L,47296L,47297L,47298L,47299L,47300L,47301L,47302L,47303L,47304L,
96678 47305L,47306L,47307L,47308L,47309L,47310L,47311L,47312L,47313L,47314L,
96679 47315L,47316L,47317L,47318L,47319L,47320L,47321L,47322L,47323L,47324L,
96680 47325L,47326L,47327L,47328L,47329L,47330L,47331L,47332L,47333L,47334L,
96681 47335L,47336L,47337L,47338L,47339L,47340L,47341L,47342L,47343L,47344L,
96682 47345L,47346L,47347L,47348L,47349L,47350L,47351L,47352L,47353L,47354L,
96683 47355L,47356L,47357L,47358L,47359L,47360L,47361L,47362L,47363L,47364L,
96684 47365L,47366L,47367L,47368L,47369L,47370L,47371L,47372L,47373L,47374L,
96685 47375L,47376L,47377L,47378L,47379L,47380L,47381L,47382L,47383L,47384L,
96686 47385L,47386L,47387L,47388L,47389L,47390L,47391L,47392L,47393L,47394L,
96687 47395L,47396L,47397L,47398L,47399L,47400L,47401L,47402L,47403L,47404L,
96688 47405L,47406L,47407L,47408L,47409L,47410L,47411L,47412L,47413L,47414L,
96689 47415L,47416L,47417L,47418L,47419L,47420L,47421L,47422L,47423L,47424L,
96690 47425L,47426L,47427L,47428L,47429L,47430L,47431L,47432L,47433L,47434L,
96691 47435L,47436L,47437L,47438L,47439L,47440L,47441L,47442L,47443L,47444L,
96692 47445L,47446L,47447L,47448L,47449L,47450L,47451L,47452L,47453L,47454L,
96693 47455L,47456L,47457L,47458L,47459L,47460L,47461L,47462L,47463L,47464L,
96694 47465L,47466L,47467L,47468L,47469L,47470L,47471L,47472L,47473L,47474L,
96695 47475L,47476L,47477L,47478L,47479L,47480L,47481L,47482L,47483L,47484L,
96696 47485L,47486L,47487L,47488L,47489L,47490L,47491L,47492L,47493L,47494L,
96697 47495L,47496L,47497L,47498L,47499L,47500L,47501L,47502L,47503L,47504L,
96698 47505L,47506L,47507L,47508L,47509L,47510L,47511L,47512L,47513L,47514L,
96699 47515L,47516L,47517L,47518L,47519L,47520L,47521L,47522L,47523L,47524L,
96700 47525L,47526L,47527L,47528L,47529L,47530L,47531L,47532L,47533L,47534L,
96701 47535L,47536L,47537L,47538L,47539L,47540L,47541L,47542L,47543L,47544L,
96702 47545L,47546L,47547L,47548L,47549L,47550L,47551L,47552L,47553L,47554L,
96703 47555L,47556L,47557L,47558L,47559L,47560L,47561L,47562L,47563L,47564L,
96704 47565L,47566L,47567L,47568L,47569L,47570L,47571L,47572L,47573L,47574L,
96705 47575L,47576L,47577L,47578L,47579L,47580L,47581L,47582L,47583L,47584L,
96706 47585L,47586L,47587L,47588L,47589L,47590L,47591L,47592L,47593L,47594L,
96707 47595L,47596L,47597L,47598L,47599L,47600L,47601L,47602L,47603L,47604L,
96708 47605L,47606L,47607L,47608L,47609L,47610L,47611L,47612L,47613L,47614L,
96709 47615L,47616L,47617L,47618L,47619L,47620L,47621L,47622L,47623L,47624L,
96710 47625L,47626L,47627L,47628L,47629L,47630L,47631L,47632L,47633L,47634L,
96711 47635L,47636L,47637L,47638L,47639L,47640L,47641L,47642L,47643L,47644L,
96712 47645L,47646L,47647L,47648L,47649L,47650L,47651L,47652L,47653L,47654L,
96713 47655L,47656L,47657L,47658L,47659L,47660L,47661L,47662L,47663L,47664L,
96714 47665L,47666L,47667L,47668L,47669L,47670L,47671L,47672L,47673L,47674L,
96715 47675L,47676L,47677L,47678L,47679L,47680L,47681L,47682L,47683L,47684L,
96716 47685L,47686L,47687L,47688L,47689L,47690L,47691L,47692L,47693L,47694L,
96717 47695L,47696L,47697L,47698L,47699L,47700L,47701L,47702L,47703L,47704L,
96718 47705L,47706L,47707L,47708L,47709L,47710L,47711L,47712L,47713L,47714L,
96719 47715L,47716L,47717L,47718L,47719L,47720L,47721L,47722L,47723L,47724L,
96720 47725L,47726L,47727L,47728L,47729L,47730L,47731L,47732L,47733L,47734L,
96721 47735L,47736L,47737L,47738L,47739L,47740L,47741L,47742L,47743L,47744L,
96722 47745L,47746L,47747L,47748L,47749L,47750L,47751L,47752L,47753L,47754L,
96723 47755L,47756L,47757L,47758L,47759L,47760L,47761L,47762L,47763L,47764L,
96724 47765L,47766L,47767L,47768L,47769L,47770L,47771L,47772L,47773L,47774L,
96725 47775L,47776L,47777L,47778L,47779L,47780L,47781L,47782L,47783L,47784L,
96726 47785L,47786L,47787L,47788L,47789L,47790L,47791L,47792L,47793L,47794L,
96727 47795L,47796L,47797L,47798L,47799L,47800L,47801L,47802L,47803L,47804L,
96728 47805L,47806L,47807L,47808L,47809L,47810L,47811L,47812L,47813L,47814L,
96729 47815L,47816L,47817L,47818L,47819L,47820L,47821L,47822L,47823L,47824L,
96730 47825L,47826L,47827L,47828L,47829L,47830L,47831L,47832L,47833L,47834L,
96731 47835L,47836L,47837L,47838L,47839L,47840L,47841L,47842L,47843L,47844L,
96732 47845L,47846L,47847L,47848L,47849L,47850L,47851L,47852L,47853L,47854L,
96733 47855L,47856L,47857L,47858L,47859L,47860L,47861L,47862L,47863L,47864L,
96734 47865L,47866L,47867L,47868L,47869L,47870L,47871L,47872L,47873L,47874L,
96735 47875L,47876L,47877L,47878L,47879L,47880L,47881L,47882L,47883L,47884L,
96736 47885L,47886L,47887L,47888L,47889L,47890L,47891L,47892L,47893L,47894L,
96737 47895L,47896L,47897L,47898L,47899L,47900L,47901L,47902L,47903L,47904L,
96738 47905L,47906L,47907L,47908L,47909L,47910L,47911L,47912L,47913L,47914L,
96739 47915L,47916L,47917L,47918L,47919L,47920L,47921L,47922L,47923L,47924L,
96740 47925L,47926L,47927L,47928L,47929L,47930L,47931L,47932L,47933L,47934L,
96741 47935L,47936L,47937L,47938L,47939L,47940L,47941L,47942L,47943L,47944L,
96742 47945L,47946L,47947L,47948L,47949L,47950L,47951L,47952L,47953L,47954L,
96743 47955L,47956L,47957L,47958L,47959L,47960L,47961L,47962L,47963L,47964L,
96744 47965L,47966L,47967L,47968L,47969L,47970L,47971L,47972L,47973L,47974L,
96745 47975L,47976L,47977L,47978L,47979L,47980L,47981L,47982L,47983L,47984L,
96746 47985L,47986L,47987L,47988L,47989L,47990L,47991L,47992L,47993L,47994L,
96747 47995L,47996L,47997L,47998L,47999L,48000L,48001L,48002L,48003L,48004L,
96748 48005L,48006L,48007L,48008L,48009L,48010L,48011L,48012L,48013L,48014L,
96749 48015L,48016L,48017L,48018L,48019L,48020L,48021L,48022L,48023L,48024L,
96750 48025L,48026L,48027L,48028L,48029L,48030L,48031L,48032L,48033L,48034L,
96751 48035L,48036L,48037L,48038L,48039L,48040L,48041L,48042L,48043L,48044L,
96752 48045L,48046L,48047L,48048L,48049L,48050L,48051L,48052L,48053L,48054L,
96753 48055L,48056L,48057L,48058L,48059L,48060L,48061L,48062L,48063L,48064L,
96754 48065L,48066L,48067L,48068L,48069L,48070L,48071L,48072L,48073L,48074L,
96755 48075L,48076L,48077L,48078L,48079L,48080L,48081L,48082L,48083L,48084L,
96756 48085L,48086L,48087L,48088L,48089L,48090L,48091L,48092L,48093L,48094L,
96757 48095L,48096L,48097L,48098L,48099L,48100L,48101L,48102L,48103L,48104L,
96758 48105L,48106L,48107L,48108L,48109L,48110L,48111L,48112L,48113L,48114L,
96759 48115L,48116L,48117L,48118L,48119L,48120L,48121L,48122L,48123L,48124L,
96760 48125L,48126L,48127L,48128L,48129L,48130L,48131L,48132L,48133L,48134L,
96761 48135L,48136L,48137L,48138L,48139L,48140L,48141L,48142L,48143L,48144L,
96762 48145L,48146L,48147L,48148L,48149L,48150L,48151L,48152L,48153L,48154L,
96763 48155L,48156L,48157L,48158L,48159L,48160L,48161L,48162L,48163L,48164L,
96764 48165L,48166L,48167L,48168L,48169L,48170L,48171L,48172L,48173L,48174L,
96765 48175L,48176L,48177L,48178L,48179L,48180L,48181L,48182L,48183L,48184L,
96766 48185L,48186L,48187L,48188L,48189L,48190L,48191L,48192L,48193L,48194L,
96767 48195L,48196L,48197L,48198L,48199L,48200L,48201L,48202L,48203L,48204L,
96768 48205L,48206L,48207L,48208L,48209L,48210L,48211L,48212L,48213L,48214L,
96769 48215L,48216L,48217L,48218L,48219L,48220L,48221L,48222L,48223L,48224L,
96770 48225L,48226L,48227L,48228L,48229L,48230L,48231L,48232L,48233L,48234L,
96771 48235L,48236L,48237L,48238L,48239L,48240L,48241L,48242L,48243L,48244L,
96772 48245L,48246L,48247L,48248L,48249L,48250L,48251L,48252L,48253L,48254L,
96773 48255L,48256L,48257L,48258L,48259L,48260L,48261L,48262L,48263L,48264L,
96774 48265L,48266L,48267L,48268L,48269L,48270L,48271L,48272L,48273L,48274L,
96775 48275L,48276L,48277L,48278L,48279L,48280L,48281L,48282L,48283L,48284L,
96776 48285L,48286L,48287L,48288L,48289L,48290L,48291L,48292L,48293L,48294L,
96777 48295L,48296L,48297L,48298L,48299L,48300L,48301L,48302L,48303L,48304L,
96778 48305L,48306L,48307L,48308L,48309L,48310L,48311L,48312L,48313L,48314L,
96779 48315L,48316L,48317L,48318L,48319L,48320L,48321L,48322L,48323L,48324L,
96780 48325L,48326L,48327L,48328L,48329L,48330L,48331L,48332L,48333L,48334L,
96781 48335L,48336L,48337L,48338L,48339L,48340L,48341L,48342L,48343L,48344L,
96782 48345L,48346L,48347L,48348L,48349L,48350L,48351L,48352L,48353L,48354L,
96783 48355L,48356L,48357L,48358L,48359L,48360L,48361L,48362L,48363L,48364L,
96784 48365L,48366L,48367L,48368L,48369L,48370L,48371L,48372L,48373L,48374L,
96785 48375L,48376L,48377L,48378L,48379L,48380L,48381L,48382L,48383L,48384L,
96786 48385L,48386L,48387L,48388L,48389L,48390L,48391L,48392L,48393L,48394L,
96787 48395L,48396L,48397L,48398L,48399L,48400L,48401L,48402L,48403L,48404L,
96788 48405L,48406L,48407L,48408L,48409L,48410L,48411L,48412L,48413L,48414L,
96789 48415L,48416L,48417L,48418L,48419L,48420L,48421L,48422L,48423L,48424L,
96790 48425L,48426L,48427L,48428L,48429L,48430L,48431L,48432L,48433L,48434L,
96791 48435L,48436L,48437L,48438L,48439L,48440L,48441L,48442L,48443L,48444L,
96792 48445L,48446L,48447L,48448L,48449L,48450L,48451L,48452L,48453L,48454L,
96793 48455L,48456L,48457L,48458L,48459L,48460L,48461L,48462L,48463L,48464L,
96794 48465L,48466L,48467L,48468L,48469L,48470L,48471L,48472L,48473L,48474L,
96795 48475L,48476L,48477L,48478L,48479L,48480L,48481L,48482L,48483L,48484L,
96796 48485L,48486L,48487L,48488L,48489L,48490L,48491L,48492L,48493L,48494L,
96797 48495L,48496L,48497L,48498L,48499L,48500L,48501L,48502L,48503L,48504L,
96798 48505L,48506L,48507L,48508L,48509L,48510L,48511L,48512L,48513L,48514L,
96799 48515L,48516L,48517L,48518L,48519L,48520L,48521L,48522L,48523L,48524L,
96800 48525L,48526L,48527L,48528L,48529L,48530L,48531L,48532L,48533L,48534L,
96801 48535L,48536L,48537L,48538L,48539L,48540L,48541L,48542L,48543L,48544L,
96802 48545L,48546L,48547L,48548L,48549L,48550L,48551L,48552L,48553L,48554L,
96803 48555L,48556L,48557L,48558L,48559L,48560L,48561L,48562L,48563L,48564L,
96804 48565L,48566L,48567L,48568L,48569L,48570L,48571L,48572L,48573L,48574L,
96805 48575L,48576L,48577L,48578L,48579L,48580L,48581L,48582L,48583L,48584L,
96806 48585L,48586L,48587L,48588L,48589L,48590L,48591L,48592L,48593L,48594L,
96807 48595L,48596L,48597L,48598L,48599L,48600L,48601L,48602L,48603L,48604L,
96808 48605L,48606L,48607L,48608L,48609L,48610L,48611L,48612L,48613L,48614L,
96809 48615L,48616L,48617L,48618L,48619L,48620L,48621L,48622L,48623L,48624L,
96810 48625L,48626L,48627L,48628L,48629L,48630L,48631L,48632L,48633L,48634L,
96811 48635L,48636L,48637L,48638L,48639L,48640L,48641L,48642L,48643L,48644L,
96812 48645L,48646L,48647L,48648L,48649L,48650L,48651L,48652L,48653L,48654L,
96813 48655L,48656L,48657L,48658L,48659L,48660L,48661L,48662L,48663L,48664L,
96814 48665L,48666L,48667L,48668L,48669L,48670L,48671L,48672L,48673L,48674L,
96815 48675L,48676L,48677L,48678L,48679L,48680L,48681L,48682L,48683L,48684L,
96816 48685L,48686L,48687L,48688L,48689L,48690L,48691L,48692L,48693L,48694L,
96817 48695L,48696L,48697L,48698L,48699L,48700L,48701L,48702L,48703L,48704L,
96818 48705L,48706L,48707L,48708L,48709L,48710L,48711L,48712L,48713L,48714L,
96819 48715L,48716L,48717L,48718L,48719L,48720L,48721L,48722L,48723L,48724L,
96820 48725L,48726L,48727L,48728L,48729L,48730L,48731L,48732L,48733L,48734L,
96821 48735L,48736L,48737L,48738L,48739L,48740L,48741L,48742L,48743L,48744L,
96822 48745L,48746L,48747L,48748L,48749L,48750L,48751L,48752L,48753L,48754L,
96823 48755L,48756L,48757L,48758L,48759L,48760L,48761L,48762L,48763L,48764L,
96824 48765L,48766L,48767L,48768L,48769L,48770L,48771L,48772L,48773L,48774L,
96825 48775L,48776L,48777L,48778L,48779L,48780L,48781L,48782L,48783L,48784L,
96826 48785L,48786L,48787L,48788L,48789L,48790L,48791L,48792L,48793L,48794L,
96827 48795L,48796L,48797L,48798L,48799L,48800L,48801L,48802L,48803L,48804L,
96828 48805L,48806L,48807L,48808L,48809L,48810L,48811L,48812L,48813L,48814L,
96829 48815L,48816L,48817L,48818L,48819L,48820L,48821L,48822L,48823L,48824L,
96830 48825L,48826L,48827L,48828L,48829L,48830L,48831L,48832L,48833L,48834L,
96831 48835L,48836L,48837L,48838L,48839L,48840L,48841L,48842L,48843L,48844L,
96832 48845L,48846L,48847L,48848L,48849L,48850L,48851L,48852L,48853L,48854L,
96833 48855L,48856L,48857L,48858L,48859L,48860L,48861L,48862L,48863L,48864L,
96834 48865L,48866L,48867L,48868L,48869L,48870L,48871L,48872L,48873L,48874L,
96835 48875L,48876L,48877L,48878L,48879L,48880L,48881L,48882L,48883L,48884L,
96836 48885L,48886L,48887L,48888L,48889L,48890L,48891L,48892L,48893L,48894L,
96837 48895L,48896L,48897L,48898L,48899L,48900L,48901L,48902L,48903L,48904L,
96838 48905L,48906L,48907L,48908L,48909L,48910L,48911L,48912L,48913L,48914L,
96839 48915L,48916L,48917L,48918L,48919L,48920L,48921L,48922L,48923L,48924L,
96840 48925L,48926L,48927L,48928L,48929L,48930L,48931L,48932L,48933L,48934L,
96841 48935L,48936L,48937L,48938L,48939L,48940L,48941L,48942L,48943L,48944L,
96842 48945L,48946L,48947L,48948L,48949L,48950L,48951L,48952L,48953L,48954L,
96843 48955L,48956L,48957L,48958L,48959L,48960L,48961L,48962L,48963L,48964L,
96844 48965L,48966L,48967L,48968L,48969L,48970L,48971L,48972L,48973L,48974L,
96845 48975L,48976L,48977L,48978L,48979L,48980L,48981L,48982L,48983L,48984L,
96846 48985L,48986L,48987L,48988L,48989L,48990L,48991L,48992L,48993L,48994L,
96847 48995L,48996L,48997L,48998L,48999L,49000L,49001L,49002L,49003L,49004L,
96848 49005L,49006L,49007L,49008L,49009L,49010L,49011L,49012L,49013L,49014L,
96849 49015L,49016L,49017L,49018L,49019L,49020L,49021L,49022L,49023L,49024L,
96850 49025L,49026L,49027L,49028L,49029L,49030L,49031L,49032L,49033L,49034L,
96851 49035L,49036L,49037L,49038L,49039L,49040L,49041L,49042L,49043L,49044L,
96852 49045L,49046L,49047L,49048L,49049L,49050L,49051L,49052L,49053L,49054L,
96853 49055L,49056L,49057L,49058L,49059L,49060L,49061L,49062L,49063L,49064L,
96854 49065L,49066L,49067L,49068L,49069L,49070L,49071L,49072L,49073L,49074L,
96855 49075L,49076L,49077L,49078L,49079L,49080L,49081L,49082L,49083L,49084L,
96856 49085L,49086L,49087L,49088L,49089L,49090L,49091L,49092L,49093L,49094L,
96857 49095L,49096L,49097L,49098L,49099L,49100L,49101L,49102L,49103L,49104L,
96858 49105L,49106L,49107L,49108L,49109L,49110L,49111L,49112L,49113L,49114L,
96859 49115L,49116L,49117L,49118L,49119L,49120L,49121L,49122L,49123L,49124L,
96860 49125L,49126L,49127L,49128L,49129L,49130L,49131L,49132L,49133L,49134L,
96861 49135L,49136L,49137L,49138L,49139L,49140L,49141L,49142L,49143L,49144L,
96862 49145L,49146L,49147L,49148L,49149L,49150L,49151L,49152L,49153L,49154L,
96863 49155L,49156L,49157L,49158L,49159L,49160L,49161L,49162L,49163L,49164L,
96864 49165L,49166L,49167L,49168L,49169L,49170L,49171L,49172L,49173L,49174L,
96865 49175L,49176L,49177L,49178L,49179L,49180L,49181L,49182L,49183L,49184L,
96866 49185L,49186L,49187L,49188L,49189L,49190L,49191L,49192L,49193L,49194L,
96867 49195L,49196L,49197L,49198L,49199L,49200L,49201L,49202L,49203L,49204L,
96868 49205L,49206L,49207L,49208L,49209L,49210L,49211L,49212L,49213L,49214L,
96869 49215L,49216L,49217L,49218L,49219L,49220L,49221L,49222L,49223L,49224L,
96870 49225L,49226L,49227L,49228L,49229L,49230L,49231L,49232L,49233L,49234L,
96871 49235L,49236L,49237L,49238L,49239L,49240L,49241L,49242L,49243L,49244L,
96872 49245L,49246L,49247L,49248L,49249L,49250L,49251L,49252L,49253L,49254L,
96873 49255L,49256L,49257L,49258L,49259L,49260L,49261L,49262L,49263L,49264L,
96874 49265L,49266L,49267L,49268L,49269L,49270L,49271L,49272L,49273L,49274L,
96875 49275L,49276L,49277L,49278L,49279L,49280L,49281L,49282L,49283L,49284L,
96876 49285L,49286L,49287L,49288L,49289L,49290L,49291L,49292L,49293L,49294L,
96877 49295L,49296L,49297L,49298L,49299L,49300L,49301L,49302L,49303L,49304L,
96878 49305L,49306L,49307L,49308L,49309L,49310L,49311L,49312L,49313L,49314L,
96879 49315L,49316L,49317L,49318L,49319L,49320L,49321L,49322L,49323L,49324L,
96880 49325L,49326L,49327L,49328L,49329L,49330L,49331L,49332L,49333L,49334L,
96881 49335L,49336L,49337L,49338L,49339L,49340L,49341L,49342L,49343L,49344L,
96882 49345L,49346L,49347L,49348L,49349L,49350L,49351L,49352L,49353L,49354L,
96883 49355L,49356L,49357L,49358L,49359L,49360L,49361L,49362L,49363L,49364L,
96884 49365L,49366L,49367L,49368L,49369L,49370L,49371L,49372L,49373L,49374L,
96885 49375L,49376L,49377L,49378L,49379L,49380L,49381L,49382L,49383L,49384L,
96886 49385L,49386L,49387L,49388L,49389L,49390L,49391L,49392L,49393L,49394L,
96887 49395L,49396L,49397L,49398L,49399L,49400L,49401L,49402L,49403L,49404L,
96888 49405L,49406L,49407L,49408L,49409L,49410L,49411L,49412L,49413L,49414L,
96889 49415L,49416L,49417L,49418L,49419L,49420L,49421L,49422L,49423L,49424L,
96890 49425L,49426L,49427L,49428L,49429L,49430L,49431L,49432L,49433L,49434L,
96891 49435L,49436L,49437L,49438L,49439L,49440L,49441L,49442L,49443L,49444L,
96892 49445L,49446L,49447L,49448L,49449L,49450L,49451L,49452L,49453L,49454L,
96893 49455L,49456L,49457L,49458L,49459L,49460L,49461L,49462L,49463L,49464L,
96894 49465L,49466L,49467L,49468L,49469L,49470L,49471L,49472L,49473L,49474L,
96895 49475L,49476L,49477L,49478L,49479L,49480L,49481L,49482L,49483L,49484L,
96896 49485L,49486L,49487L,49488L,49489L,49490L,49491L,49492L,49493L,49494L,
96897 49495L,49496L,49497L,49498L,49499L,49500L,49501L,49502L,49503L,49504L,
96898 49505L,49506L,49507L,49508L,49509L,49510L,49511L,49512L,49513L,49514L,
96899 49515L,49516L,49517L,49518L,49519L,49520L,49521L,49522L,49523L,49524L,
96900 49525L,49526L,49527L,49528L,49529L,49530L,49531L,49532L,49533L,49534L,
96901 49535L,49536L,49537L,49538L,49539L,49540L,49541L,49542L,49543L,49544L,
96902 49545L,49546L,49547L,49548L,49549L,49550L,49551L,49552L,49553L,49554L,
96903 49555L,49556L,49557L,49558L,49559L,49560L,49561L,49562L,49563L,49564L,
96904 49565L,49566L,49567L,49568L,49569L,49570L,49571L,49572L,49573L,49574L,
96905 49575L,49576L,49577L,49578L,49579L,49580L,49581L,49582L,49583L,49584L,
96906 49585L,49586L,49587L,49588L,49589L,49590L,49591L,49592L,49593L,49594L,
96907 49595L,49596L,49597L,49598L,49599L,49600L,49601L,49602L,49603L,49604L,
96908 49605L,49606L,49607L,49608L,49609L,49610L,49611L,49612L,49613L,49614L,
96909 49615L,49616L,49617L,49618L,49619L,49620L,49621L,49622L,49623L,49624L,
96910 49625L,49626L,49627L,49628L,49629L,49630L,49631L,49632L,49633L,49634L,
96911 49635L,49636L,49637L,49638L,49639L,49640L,49641L,49642L,49643L,49644L,
96912 49645L,49646L,49647L,49648L,49649L,49650L,49651L,49652L,49653L,49654L,
96913 49655L,49656L,49657L,49658L,49659L,49660L,49661L,49662L,49663L,49664L,
96914 49665L,49666L,49667L,49668L,49669L,49670L,49671L,49672L,49673L,49674L,
96915 49675L,49676L,49677L,49678L,49679L,49680L,49681L,49682L,49683L,49684L,
96916 49685L,49686L,49687L,49688L,49689L,49690L,49691L,49692L,49693L,49694L,
96917 49695L,49696L,49697L,49698L,49699L,49700L,49701L,49702L,49703L,49704L,
96918 49705L,49706L,49707L,49708L,49709L,49710L,49711L,49712L,49713L,49714L,
96919 49715L,49716L,49717L,49718L,49719L,49720L,49721L,49722L,49723L,49724L,
96920 49725L,49726L,49727L,49728L,49729L,49730L,49731L,49732L,49733L,49734L,
96921 49735L,49736L,49737L,49738L,49739L,49740L,49741L,49742L,49743L,49744L,
96922 49745L,49746L,49747L,49748L,49749L,49750L,49751L,49752L,49753L,49754L,
96923 49755L,49756L,49757L,49758L,49759L,49760L,49761L,49762L,49763L,49764L,
96924 49765L,49766L,49767L,49768L,49769L,49770L,49771L,49772L,49773L,49774L,
96925 49775L,49776L,49777L,49778L,49779L,49780L,49781L,49782L,49783L,49784L,
96926 49785L,49786L,49787L,49788L,49789L,49790L,49791L,49792L,49793L,49794L,
96927 49795L,49796L,49797L,49798L,49799L,49800L,49801L,49802L,49803L,49804L,
96928 49805L,49806L,49807L,49808L,49809L,49810L,49811L,49812L,49813L,49814L,
96929 49815L,49816L,49817L,49818L,49819L,49820L,49821L,49822L,49823L,49824L,
96930 49825L,49826L,49827L,49828L,49829L,49830L,49831L,49832L,49833L,49834L,
96931 49835L,49836L,49837L,49838L,49839L,49840L,49841L,49842L,49843L,49844L,
96932 49845L,49846L,49847L,49848L,49849L,49850L,49851L,49852L,49853L,49854L,
96933 49855L,49856L,49857L,49858L,49859L,49860L,49861L,49862L,49863L,49864L,
96934 49865L,49866L,49867L,49868L,49869L,49870L,49871L,49872L,49873L,49874L,
96935 49875L,49876L,49877L,49878L,49879L,49880L,49881L,49882L,49883L,49884L,
96936 49885L,49886L,49887L,49888L,49889L,49890L,49891L,49892L,49893L,49894L,
96937 49895L,49896L,49897L,49898L,49899L,49900L,49901L,49902L,49903L,49904L,
96938 49905L,49906L,49907L,49908L,49909L,49910L,49911L,49912L,49913L,49914L,
96939 49915L,49916L,49917L,49918L,49919L,49920L,49921L,49922L,49923L,49924L,
96940 49925L,49926L,49927L,49928L,49929L,49930L,49931L,49932L,49933L,49934L,
96941 49935L,49936L,49937L,49938L,49939L,49940L,49941L,49942L,49943L,49944L,
96942 49945L,49946L,49947L,49948L,49949L,49950L,49951L,49952L,49953L,49954L,
96943 49955L,49956L,49957L,49958L,49959L,49960L,49961L,49962L,49963L,49964L,
96944 49965L,49966L,49967L,49968L,49969L,49970L,49971L,49972L,49973L,49974L,
96945 49975L,49976L,49977L,49978L,49979L,49980L,49981L,49982L,49983L,49984L,
96946 49985L,49986L,49987L,49988L,49989L,49990L,49991L,49992L,49993L,49994L,
96947 49995L,49996L,49997L,49998L,49999L,50000L,50001L,50002L,50003L,50004L,
96948 50005L,50006L,50007L,50008L,50009L,50010L,50011L,50012L,50013L,50014L,
96949 50015L,50016L,50017L,50018L,50019L,50020L,50021L,50022L,50023L,50024L,
96950 50025L,50026L,50027L,50028L,50029L,50030L,50031L,50032L,50033L,50034L,
96951 50035L,50036L,50037L,50038L,50039L,50040L,50041L,50042L,50043L,50044L,
96952 50045L,50046L,50047L,50048L,50049L,50050L,50051L,50052L,50053L,50054L,
96953 50055L,50056L,50057L,50058L,50059L,50060L,50061L,50062L,50063L,50064L,
96954 50065L,50066L,50067L,50068L,50069L,50070L,50071L,50072L,50073L,50074L,
96955 50075L,50076L,50077L,50078L,50079L,50080L,50081L,50082L,50083L,50084L,
96956 50085L,50086L,50087L,50088L,50089L,50090L,50091L,50092L,50093L,50094L,
96957 50095L,50096L,50097L,50098L,50099L,50100L,50101L,50102L,50103L,50104L,
96958 50105L,50106L,50107L,50108L,50109L,50110L,50111L,50112L,50113L,50114L,
96959 50115L,50116L,50117L,50118L,50119L,50120L,50121L,50122L,50123L,50124L,
96960 50125L,50126L,50127L,50128L,50129L,50130L,50131L,50132L,50133L,50134L,
96961 50135L,50136L,50137L,50138L,50139L,50140L,50141L,50142L,50143L,50144L,
96962 50145L,50146L,50147L,50148L,50149L,50150L,50151L,50152L,50153L,50154L,
96963 50155L,50156L,50157L,50158L,50159L,50160L,50161L,50162L,50163L,50164L,
96964 50165L,50166L,50167L,50168L,50169L,50170L,50171L,50172L,50173L,50174L,
96965 50175L,50176L,50177L,50178L,50179L,50180L,50181L,50182L,50183L,50184L,
96966 50185L,50186L,50187L,50188L,50189L,50190L,50191L,50192L,50193L,50194L,
96967 50195L,50196L,50197L,50198L,50199L,50200L,50201L,50202L,50203L,50204L,
96968 50205L,50206L,50207L,50208L,50209L,50210L,50211L,50212L,50213L,50214L,
96969 50215L,50216L,50217L,50218L,50219L,50220L,50221L,50222L,50223L,50224L,
96970 50225L,50226L,50227L,50228L,50229L,50230L,50231L,50232L,50233L,50234L,
96971 50235L,50236L,50237L,50238L,50239L,50240L,50241L,50242L,50243L,50244L,
96972 50245L,50246L,50247L,50248L,50249L,50250L,50251L,50252L,50253L,50254L,
96973 50255L,50256L,50257L,50258L,50259L,50260L,50261L,50262L,50263L,50264L,
96974 50265L,50266L,50267L,50268L,50269L,50270L,50271L,50272L,50273L,50274L,
96975 50275L,50276L,50277L,50278L,50279L,50280L,50281L,50282L,50283L,50284L,
96976 50285L,50286L,50287L,50288L,50289L,50290L,50291L,50292L,50293L,50294L,
96977 50295L,50296L,50297L,50298L,50299L,50300L,50301L,50302L,50303L,50304L,
96978 50305L,50306L,50307L,50308L,50309L,50310L,50311L,50312L,50313L,50314L,
96979 50315L,50316L,50317L,50318L,50319L,50320L,50321L,50322L,50323L,50324L,
96980 50325L,50326L,50327L,50328L,50329L,50330L,50331L,50332L,50333L,50334L,
96981 50335L,50336L,50337L,50338L,50339L,50340L,50341L,50342L,50343L,50344L,
96982 50345L,50346L,50347L,50348L,50349L,50350L,50351L,50352L,50353L,50354L,
96983 50355L,50356L,50357L,50358L,50359L,50360L,50361L,50362L,50363L,50364L,
96984 50365L,50366L,50367L,50368L,50369L,50370L,50371L,50372L,50373L,50374L,
96985 50375L,50376L,50377L,50378L,50379L,50380L,50381L,50382L,50383L,50384L,
96986 50385L,50386L,50387L,50388L,50389L,50390L,50391L,50392L,50393L,50394L,
96987 50395L,50396L,50397L,50398L,50399L,50400L,50401L,50402L,50403L,50404L,
96988 50405L,50406L,50407L,50408L,50409L,50410L,50411L,50412L,50413L,50414L,
96989 50415L,50416L,50417L,50418L,50419L,50420L,50421L,50422L,50423L,50424L,
96990 50425L,50426L,50427L,50428L,50429L,50430L,50431L,50432L,50433L,50434L,
96991 50435L,50436L,50437L,50438L,50439L,50440L,50441L,50442L,50443L,50444L,
96992 50445L,50446L,50447L,50448L,50449L,50450L,50451L,50452L,50453L,50454L,
96993 50455L,50456L,50457L,50458L,50459L,50460L,50461L,50462L,50463L,50464L,
96994 50465L,50466L,50467L,50468L,50469L,50470L,50471L,50472L,50473L,50474L,
96995 50475L,50476L,50477L,50478L,50479L,50480L,50481L,50482L,50483L,50484L,
96996 50485L,50486L,50487L,50488L,50489L,50490L,50491L,50492L,50493L,50494L,
96997 50495L,50496L,50497L,50498L,50499L,50500L,50501L,50502L,50503L,50504L,
96998 50505L,50506L,50507L,50508L,50509L,50510L,50511L,50512L,50513L,50514L,
96999 50515L,50516L,50517L,50518L,50519L,50520L,50521L,50522L,50523L,50524L,
97000 50525L,50526L,50527L,50528L,50529L,50530L,50531L,50532L,50533L,50534L,
97001 50535L,50536L,50537L,50538L,50539L,50540L,50541L,50542L,50543L,50544L,
97002 50545L,50546L,50547L,50548L,50549L,50550L,50551L,50552L,50553L,50554L,
97003 50555L,50556L,50557L,50558L,50559L,50560L,50561L,50562L,50563L,50564L,
97004 50565L,50566L,50567L,50568L,50569L,50570L,50571L,50572L,50573L,50574L,
97005 50575L,50576L,50577L,50578L,50579L,50580L,50581L,50582L,50583L,50584L,
97006 50585L,50586L,50587L,50588L,50589L,50590L,50591L,50592L,50593L,50594L,
97007 50595L,50596L,50597L,50598L,50599L,50600L,50601L,50602L,50603L,50604L,
97008 50605L,50606L,50607L,50608L,50609L,50610L,50611L,50612L,50613L,50614L,
97009 50615L,50616L,50617L,50618L,50619L,50620L,50621L,50622L,50623L,50624L,
97010 50625L,50626L,50627L,50628L,50629L,50630L,50631L,50632L,50633L,50634L,
97011 50635L,50636L,50637L,50638L,50639L,50640L,50641L,50642L,50643L,50644L,
97012 50645L,50646L,50647L,50648L,50649L,50650L,50651L,50652L,50653L,50654L,
97013 50655L,50656L,50657L,50658L,50659L,50660L,50661L,50662L,50663L,50664L,
97014 50665L,50666L,50667L,50668L,50669L,50670L,50671L,50672L,50673L,50674L,
97015 50675L,50676L,50677L,50678L,50679L,50680L,50681L,50682L,50683L,50684L,
97016 50685L,50686L,50687L,50688L,50689L,50690L,50691L,50692L,50693L,50694L,
97017 50695L,50696L,50697L,50698L,50699L,50700L,50701L,50702L,50703L,50704L,
97018 50705L,50706L,50707L,50708L,50709L,50710L,50711L,50712L,50713L,50714L,
97019 50715L,50716L,50717L,50718L,50719L,50720L,50721L,50722L,50723L,50724L,
97020 50725L,50726L,50727L,50728L,50729L,50730L,50731L,50732L,50733L,50734L,
97021 50735L,50736L,50737L,50738L,50739L,50740L,50741L,50742L,50743L,50744L,
97022 50745L,50746L,50747L,50748L,50749L,50750L,50751L,50752L,50753L,50754L,
97023 50755L,50756L,50757L,50758L,50759L,50760L,50761L,50762L,50763L,50764L,
97024 50765L,50766L,50767L,50768L,50769L,50770L,50771L,50772L,50773L,50774L,
97025 50775L,50776L,50777L,50778L,50779L,50780L,50781L,50782L,50783L,50784L,
97026 50785L,50786L,50787L,50788L,50789L,50790L,50791L,50792L,50793L,50794L,
97027 50795L,50796L,50797L,50798L,50799L,50800L,50801L,50802L,50803L,50804L,
97028 50805L,50806L,50807L,50808L,50809L,50810L,50811L,50812L,50813L,50814L,
97029 50815L,50816L,50817L,50818L,50819L,50820L,50821L,50822L,50823L,50824L,
97030 50825L,50826L,50827L,50828L,50829L,50830L,50831L,50832L,50833L,50834L,
97031 50835L,50836L,50837L,50838L,50839L,50840L,50841L,50842L,50843L,50844L,
97032 50845L,50846L,50847L,50848L,50849L,50850L,50851L,50852L,50853L,50854L,
97033 50855L,50856L,50857L,50858L,50859L,50860L,50861L,50862L,50863L,50864L,
97034 50865L,50866L,50867L,50868L,50869L,50870L,50871L,50872L,50873L,50874L,
97035 50875L,50876L,50877L,50878L,50879L,50880L,50881L,50882L,50883L,50884L,
97036 50885L,50886L,50887L,50888L,50889L,50890L,50891L,50892L,50893L,50894L,
97037 50895L,50896L,50897L,50898L,50899L,50900L,50901L,50902L,50903L,50904L,
97038 50905L,50906L,50907L,50908L,50909L,50910L,50911L,50912L,50913L,50914L,
97039 50915L,50916L,50917L,50918L,50919L,50920L,50921L,50922L,50923L,50924L,
97040 50925L,50926L,50927L,50928L,50929L,50930L,50931L,50932L,50933L,50934L,
97041 50935L,50936L,50937L,50938L,50939L,50940L,50941L,50942L,50943L,50944L,
97042 50945L,50946L,50947L,50948L,50949L,50950L,50951L,50952L,50953L,50954L,
97043 50955L,50956L,50957L,50958L,50959L,50960L,50961L,50962L,50963L,50964L,
97044 50965L,50966L,50967L,50968L,50969L,50970L,50971L,50972L,50973L,50974L,
97045 50975L,50976L,50977L,50978L,50979L,50980L,50981L,50982L,50983L,50984L,
97046 50985L,50986L,50987L,50988L,50989L,50990L,50991L,50992L,50993L,50994L,
97047 50995L,50996L,50997L,50998L,50999L,51000L,51001L,51002L,51003L,51004L,
97048 51005L,51006L,51007L,51008L,51009L,51010L,51011L,51012L,51013L,51014L,
97049 51015L,51016L,51017L,51018L,51019L,51020L,51021L,51022L,51023L,51024L,
97050 51025L,51026L,51027L,51028L,51029L,51030L,51031L,51032L,51033L,51034L,
97051 51035L,51036L,51037L,51038L,51039L,51040L,51041L,51042L,51043L,51044L,
97052 51045L,51046L,51047L,51048L,51049L,51050L,51051L,51052L,51053L,51054L,
97053 51055L,51056L,51057L,51058L,51059L,51060L,51061L,51062L,51063L,51064L,
97054 51065L,51066L,51067L,51068L,51069L,51070L,51071L,51072L,51073L,51074L,
97055 51075L,51076L,51077L,51078L,51079L,51080L,51081L,51082L,51083L,51084L,
97056 51085L,51086L,51087L,51088L,51089L,51090L,51091L,51092L,51093L,51094L,
97057 51095L,51096L,51097L,51098L,51099L,51100L,51101L,51102L,51103L,51104L,
97058 51105L,51106L,51107L,51108L,51109L,51110L,51111L,51112L,51113L,51114L,
97059 51115L,51116L,51117L,51118L,51119L,51120L,51121L,51122L,51123L,51124L,
97060 51125L,51126L,51127L,51128L,51129L,51130L,51131L,51132L,51133L,51134L,
97061 51135L,51136L,51137L,51138L,51139L,51140L,51141L,51142L,51143L,51144L,
97062 51145L,51146L,51147L,51148L,51149L,51150L,51151L,51152L,51153L,51154L,
97063 51155L,51156L,51157L,51158L,51159L,51160L,51161L,51162L,51163L,51164L,
97064 51165L,51166L,51167L,51168L,51169L,51170L,51171L,51172L,51173L,51174L,
97065 51175L,51176L,51177L,51178L,51179L,51180L,51181L,51182L,51183L,51184L,
97066 51185L,51186L,51187L,51188L,51189L,51190L,51191L,51192L,51193L,51194L,
97067 51195L,51196L,51197L,51198L,51199L,51200L,51201L,51202L,51203L,51204L,
97068 51205L,51206L,51207L,51208L,51209L,51210L,51211L,51212L,51213L,51214L,
97069 51215L,51216L,51217L,51218L,51219L,51220L,51221L,51222L,51223L,51224L,
97070 51225L,51226L,51227L,51228L,51229L,51230L,51231L,51232L,51233L,51234L,
97071 51235L,51236L,51237L,51238L,51239L,51240L,51241L,51242L,51243L,51244L,
97072 51245L,51246L,51247L,51248L,51249L,51250L,51251L,51252L,51253L,51254L,
97073 51255L,51256L,51257L,51258L,51259L,51260L,51261L,51262L,51263L,51264L,
97074 51265L,51266L,51267L,51268L,51269L,51270L,51271L,51272L,51273L,51274L,
97075 51275L,51276L,51277L,51278L,51279L,51280L,51281L,51282L,51283L,51284L,
97076 51285L,51286L,51287L,51288L,51289L,51290L,51291L,51292L,51293L,51294L,
97077 51295L,51296L,51297L,51298L,51299L,51300L,51301L,51302L,51303L,51304L,
97078 51305L,51306L,51307L,51308L,51309L,51310L,51311L,51312L,51313L,51314L,
97079 51315L,51316L,51317L,51318L,51319L,51320L,51321L,51322L,51323L,51324L,
97080 51325L,51326L,51327L,51328L,51329L,51330L,51331L,51332L,51333L,51334L,
97081 51335L,51336L,51337L,51338L,51339L,51340L,51341L,51342L,51343L,51344L,
97082 51345L,51346L,51347L,51348L,51349L,51350L,51351L,51352L,51353L,51354L,
97083 51355L,51356L,51357L,51358L,51359L,51360L,51361L,51362L,51363L,51364L,
97084 51365L,51366L,51367L,51368L,51369L,51370L,51371L,51372L,51373L,51374L,
97085 51375L,51376L,51377L,51378L,51379L,51380L,51381L,51382L,51383L,51384L,
97086 51385L,51386L,51387L,51388L,51389L,51390L,51391L,51392L,51393L,51394L,
97087 51395L,51396L,51397L,51398L,51399L,51400L,51401L,51402L,51403L,51404L,
97088 51405L,51406L,51407L,51408L,51409L,51410L,51411L,51412L,51413L,51414L,
97089 51415L,51416L,51417L,51418L,51419L,51420L,51421L,51422L,51423L,51424L,
97090 51425L,51426L,51427L,51428L,51429L,51430L,51431L,51432L,51433L,51434L,
97091 51435L,51436L,51437L,51438L,51439L,51440L,51441L,51442L,51443L,51444L,
97092 51445L,51446L,51447L,51448L,51449L,51450L,51451L,51452L,51453L,51454L,
97093 51455L,51456L,51457L,51458L,51459L,51460L,51461L,51462L,51463L,51464L,
97094 51465L,51466L,51467L,51468L,51469L,51470L,51471L,51472L,51473L,51474L,
97095 51475L,51476L,51477L,51478L,51479L,51480L,51481L,51482L,51483L,51484L,
97096 51485L,51486L,51487L,51488L,51489L,51490L,51491L,51492L,51493L,51494L,
97097 51495L,51496L,51497L,51498L,51499L,51500L,51501L,51502L,51503L,51504L,
97098 51505L,51506L,51507L,51508L,51509L,51510L,51511L,51512L,51513L,51514L,
97099 51515L,51516L,51517L,51518L,51519L,51520L,51521L,51522L,51523L,51524L,
97100 51525L,51526L,51527L,51528L,51529L,51530L,51531L,51532L,51533L,51534L,
97101 51535L,51536L,51537L,51538L,51539L,51540L,51541L,51542L,51543L,51544L,
97102 51545L,51546L,51547L,51548L,51549L,51550L,51551L,51552L,51553L,51554L,
97103 51555L,51556L,51557L,51558L,51559L,51560L,51561L,51562L,51563L,51564L,
97104 51565L,51566L,51567L,51568L,51569L,51570L,51571L,51572L,51573L,51574L,
97105 51575L,51576L,51577L,51578L,51579L,51580L,51581L,51582L,51583L,51584L,
97106 51585L,51586L,51587L,51588L,51589L,51590L,51591L,51592L,51593L,51594L,
97107 51595L,51596L,51597L,51598L,51599L,51600L,51601L,51602L,51603L,51604L,
97108 51605L,51606L,51607L,51608L,51609L,51610L,51611L,51612L,51613L,51614L,
97109 51615L,51616L,51617L,51618L,51619L,51620L,51621L,51622L,51623L,51624L,
97110 51625L,51626L,51627L,51628L,51629L,51630L,51631L,51632L,51633L,51634L,
97111 51635L,51636L,51637L,51638L,51639L,51640L,51641L,51642L,51643L,51644L,
97112 51645L,51646L,51647L,51648L,51649L,51650L,51651L,51652L,51653L,51654L,
97113 51655L,51656L,51657L,51658L,51659L,51660L,51661L,51662L,51663L,51664L,
97114 51665L,51666L,51667L,51668L,51669L,51670L,51671L,51672L,51673L,51674L,
97115 51675L,51676L,51677L,51678L,51679L,51680L,51681L,51682L,51683L,51684L,
97116 51685L,51686L,51687L,51688L,51689L,51690L,51691L,51692L,51693L,51694L,
97117 51695L,51696L,51697L,51698L,51699L,51700L,51701L,51702L,51703L,51704L,
97118 51705L,51706L,51707L,51708L,51709L,51710L,51711L,51712L,51713L,51714L,
97119 51715L,51716L,51717L,51718L,51719L,51720L,51721L,51722L,51723L,51724L,
97120 51725L,51726L,51727L,51728L,51729L,51730L,51731L,51732L,51733L,51734L,
97121 51735L,51736L,51737L,51738L,51739L,51740L,51741L,51742L,51743L,51744L,
97122 51745L,51746L,51747L,51748L,51749L,51750L,51751L,51752L,51753L,51754L,
97123 51755L,51756L,51757L,51758L,51759L,51760L,51761L,51762L,51763L,51764L,
97124 51765L,51766L,51767L,51768L,51769L,51770L,51771L,51772L,51773L,51774L,
97125 51775L,51776L,51777L,51778L,51779L,51780L,51781L,51782L,51783L,51784L,
97126 51785L,51786L,51787L,51788L,51789L,51790L,51791L,51792L,51793L,51794L,
97127 51795L,51796L,51797L,51798L,51799L,51800L,51801L,51802L,51803L,51804L,
97128 51805L,51806L,51807L,51808L,51809L,51810L,51811L,51812L,51813L,51814L,
97129 51815L,51816L,51817L,51818L,51819L,51820L,51821L,51822L,51823L,51824L,
97130 51825L,51826L,51827L,51828L,51829L,51830L,51831L,51832L,51833L,51834L,
97131 51835L,51836L,51837L,51838L,51839L,51840L,51841L,51842L,51843L,51844L,
97132 51845L,51846L,51847L,51848L,51849L,51850L,51851L,51852L,51853L,51854L,
97133 51855L,51856L,51857L,51858L,51859L,51860L,51861L,51862L,51863L,51864L,
97134 51865L,51866L,51867L,51868L,51869L,51870L,51871L,51872L,51873L,51874L,
97135 51875L,51876L,51877L,51878L,51879L,51880L,51881L,51882L,51883L,51884L,
97136 51885L,51886L,51887L,51888L,51889L,51890L,51891L,51892L,51893L,51894L,
97137 51895L,51896L,51897L,51898L,51899L,51900L,51901L,51902L,51903L,51904L,
97138 51905L,51906L,51907L,51908L,51909L,51910L,51911L,51912L,51913L,51914L,
97139 51915L,51916L,51917L,51918L,51919L,51920L,51921L,51922L,51923L,51924L,
97140 51925L,51926L,51927L,51928L,51929L,51930L,51931L,51932L,51933L,51934L,
97141 51935L,51936L,51937L,51938L,51939L,51940L,51941L,51942L,51943L,51944L,
97142 51945L,51946L,51947L,51948L,51949L,51950L,51951L,51952L,51953L,51954L,
97143 51955L,51956L,51957L,51958L,51959L,51960L,51961L,51962L,51963L,51964L,
97144 51965L,51966L,51967L,51968L,51969L,51970L,51971L,51972L,51973L,51974L,
97145 51975L,51976L,51977L,51978L,51979L,51980L,51981L,51982L,51983L,51984L,
97146 51985L,51986L,51987L,51988L,51989L,51990L,51991L,51992L,51993L,51994L,
97147 51995L,51996L,51997L,51998L,51999L,52000L,52001L,52002L,52003L,52004L,
97148 52005L,52006L,52007L,52008L,52009L,52010L,52011L,52012L,52013L,52014L,
97149 52015L,52016L,52017L,52018L,52019L,52020L,52021L,52022L,52023L,52024L,
97150 52025L,52026L,52027L,52028L,52029L,52030L,52031L,52032L,52033L,52034L,
97151 52035L,52036L,52037L,52038L,52039L,52040L,52041L,52042L,52043L,52044L,
97152 52045L,52046L,52047L,52048L,52049L,52050L,52051L,52052L,52053L,52054L,
97153 52055L,52056L,52057L,52058L,52059L,52060L,52061L,52062L,52063L,52064L,
97154 52065L,52066L,52067L,52068L,52069L,52070L,52071L,52072L,52073L,52074L,
97155 52075L,52076L,52077L,52078L,52079L,52080L,52081L,52082L,52083L,52084L,
97156 52085L,52086L,52087L,52088L,52089L,52090L,52091L,52092L,52093L,52094L,
97157 52095L,52096L,52097L,52098L,52099L,52100L,52101L,52102L,52103L,52104L,
97158 52105L,52106L,52107L,52108L,52109L,52110L,52111L,52112L,52113L,52114L,
97159 52115L,52116L,52117L,52118L,52119L,52120L,52121L,52122L,52123L,52124L,
97160 52125L,52126L,52127L,52128L,52129L,52130L,52131L,52132L,52133L,52134L,
97161 52135L,52136L,52137L,52138L,52139L,52140L,52141L,52142L,52143L,52144L,
97162 52145L,52146L,52147L,52148L,52149L,52150L,52151L,52152L,52153L,52154L,
97163 52155L,52156L,52157L,52158L,52159L,52160L,52161L,52162L,52163L,52164L,
97164 52165L,52166L,52167L,52168L,52169L,52170L,52171L,52172L,52173L,52174L,
97165 52175L,52176L,52177L,52178L,52179L,52180L,52181L,52182L,52183L,52184L,
97166 52185L,52186L,52187L,52188L,52189L,52190L,52191L,52192L,52193L,52194L,
97167 52195L,52196L,52197L,52198L,52199L,52200L,52201L,52202L,52203L,52204L,
97168 52205L,52206L,52207L,52208L,52209L,52210L,52211L,52212L,52213L,52214L,
97169 52215L,52216L,52217L,52218L,52219L,52220L,52221L,52222L,52223L,52224L,
97170 52225L,52226L,52227L,52228L,52229L,52230L,52231L,52232L,52233L,52234L,
97171 52235L,52236L,52237L,52238L,52239L,52240L,52241L,52242L,52243L,52244L,
97172 52245L,52246L,52247L,52248L,52249L,52250L,52251L,52252L,52253L,52254L,
97173 52255L,52256L,52257L,52258L,52259L,52260L,52261L,52262L,52263L,52264L,
97174 52265L,52266L,52267L,52268L,52269L,52270L,52271L,52272L,52273L,52274L,
97175 52275L,52276L,52277L,52278L,52279L,52280L,52281L,52282L,52283L,52284L,
97176 52285L,52286L,52287L,52288L,52289L,52290L,52291L,52292L,52293L,52294L,
97177 52295L,52296L,52297L,52298L,52299L,52300L,52301L,52302L,52303L,52304L,
97178 52305L,52306L,52307L,52308L,52309L,52310L,52311L,52312L,52313L,52314L,
97179 52315L,52316L,52317L,52318L,52319L,52320L,52321L,52322L,52323L,52324L,
97180 52325L,52326L,52327L,52328L,52329L,52330L,52331L,52332L,52333L,52334L,
97181 52335L,52336L,52337L,52338L,52339L,52340L,52341L,52342L,52343L,52344L,
97182 52345L,52346L,52347L,52348L,52349L,52350L,52351L,52352L,52353L,52354L,
97183 52355L,52356L,52357L,52358L,52359L,52360L,52361L,52362L,52363L,52364L,
97184 52365L,52366L,52367L,52368L,52369L,52370L,52371L,52372L,52373L,52374L,
97185 52375L,52376L,52377L,52378L,52379L,52380L,52381L,52382L,52383L,52384L,
97186 52385L,52386L,52387L,52388L,52389L,52390L,52391L,52392L,52393L,52394L,
97187 52395L,52396L,52397L,52398L,52399L,52400L,52401L,52402L,52403L,52404L,
97188 52405L,52406L,52407L,52408L,52409L,52410L,52411L,52412L,52413L,52414L,
97189 52415L,52416L,52417L,52418L,52419L,52420L,52421L,52422L,52423L,52424L,
97190 52425L,52426L,52427L,52428L,52429L,52430L,52431L,52432L,52433L,52434L,
97191 52435L,52436L,52437L,52438L,52439L,52440L,52441L,52442L,52443L,52444L,
97192 52445L,52446L,52447L,52448L,52449L,52450L,52451L,52452L,52453L,52454L,
97193 52455L,52456L,52457L,52458L,52459L,52460L,52461L,52462L,52463L,52464L,
97194 52465L,52466L,52467L,52468L,52469L,52470L,52471L,52472L,52473L,52474L,
97195 52475L,52476L,52477L,52478L,52479L,52480L,52481L,52482L,52483L,52484L,
97196 52485L,52486L,52487L,52488L,52489L,52490L,52491L,52492L,52493L,52494L,
97197 52495L,52496L,52497L,52498L,52499L,52500L,52501L,52502L,52503L,52504L,
97198 52505L,52506L,52507L,52508L,52509L,52510L,52511L,52512L,52513L,52514L,
97199 52515L,52516L,52517L,52518L,52519L,52520L,52521L,52522L,52523L,52524L,
97200 52525L,52526L,52527L,52528L,52529L,52530L,52531L,52532L,52533L,52534L,
97201 52535L,52536L,52537L,52538L,52539L,52540L,52541L,52542L,52543L,52544L,
97202 52545L,52546L,52547L,52548L,52549L,52550L,52551L,52552L,52553L,52554L,
97203 52555L,52556L,52557L,52558L,52559L,52560L,52561L,52562L,52563L,52564L,
97204 52565L,52566L,52567L,52568L,52569L,52570L,52571L,52572L,52573L,52574L,
97205 52575L,52576L,52577L,52578L,52579L,52580L,52581L,52582L,52583L,52584L,
97206 52585L,52586L,52587L,52588L,52589L,52590L,52591L,52592L,52593L,52594L,
97207 52595L,52596L,52597L,52598L,52599L,52600L,52601L,52602L,52603L,52604L,
97208 52605L,52606L,52607L,52608L,52609L,52610L,52611L,52612L,52613L,52614L,
97209 52615L,52616L,52617L,52618L,52619L,52620L,52621L,52622L,52623L,52624L,
97210 52625L,52626L,52627L,52628L,52629L,52630L,52631L,52632L,52633L,52634L,
97211 52635L,52636L,52637L,52638L,52639L,52640L,52641L,52642L,52643L,52644L,
97212 52645L,52646L,52647L,52648L,52649L,52650L,52651L,52652L,52653L,52654L,
97213 52655L,52656L,52657L,52658L,52659L,52660L,52661L,52662L,52663L,52664L,
97214 52665L,52666L,52667L,52668L,52669L,52670L,52671L,52672L,52673L,52674L,
97215 52675L,52676L,52677L,52678L,52679L,52680L,52681L,52682L,52683L,52684L,
97216 52685L,52686L,52687L,52688L,52689L,52690L,52691L,52692L,52693L,52694L,
97217 52695L,52696L,52697L,52698L,52699L,52700L,52701L,52702L,52703L,52704L,
97218 52705L,52706L,52707L,52708L,52709L,52710L,52711L,52712L,52713L,52714L,
97219 52715L,52716L,52717L,52718L,52719L,52720L,52721L,52722L,52723L,52724L,
97220 52725L,52726L,52727L,52728L,52729L,52730L,52731L,52732L,52733L,52734L,
97221 52735L,52736L,52737L,52738L,52739L,52740L,52741L,52742L,52743L,52744L,
97222 52745L,52746L,52747L,52748L,52749L,52750L,52751L,52752L,52753L,52754L,
97223 52755L,52756L,52757L,52758L,52759L,52760L,52761L,52762L,52763L,52764L,
97224 52765L,52766L,52767L,52768L,52769L,52770L,52771L,52772L,52773L,52774L,
97225 52775L,52776L,52777L,52778L,52779L,52780L,52781L,52782L,52783L,52784L,
97226 52785L,52786L,52787L,52788L,52789L,52790L,52791L,52792L,52793L,52794L,
97227 52795L,52796L,52797L,52798L,52799L,52800L,52801L,52802L,52803L,52804L,
97228 52805L,52806L,52807L,52808L,52809L,52810L,52811L,52812L,52813L,52814L,
97229 52815L,52816L,52817L,52818L,52819L,52820L,52821L,52822L,52823L,52824L,
97230 52825L,52826L,52827L,52828L,52829L,52830L,52831L,52832L,52833L,52834L,
97231 52835L,52836L,52837L,52838L,52839L,52840L,52841L,52842L,52843L,52844L,
97232 52845L,52846L,52847L,52848L,52849L,52850L,52851L,52852L,52853L,52854L,
97233 52855L,52856L,52857L,52858L,52859L,52860L,52861L,52862L,52863L,52864L,
97234 52865L,52866L,52867L,52868L,52869L,52870L,52871L,52872L,52873L,52874L,
97235 52875L,52876L,52877L,52878L,52879L,52880L,52881L,52882L,52883L,52884L,
97236 52885L,52886L,52887L,52888L,52889L,52890L,52891L,52892L,52893L,52894L,
97237 52895L,52896L,52897L,52898L,52899L,52900L,52901L,52902L,52903L,52904L,
97238 52905L,52906L,52907L,52908L,52909L,52910L,52911L,52912L,52913L,52914L,
97239 52915L,52916L,52917L,52918L,52919L,52920L,52921L,52922L,52923L,52924L,
97240 52925L,52926L,52927L,52928L,52929L,52930L,52931L,52932L,52933L,52934L,
97241 52935L,52936L,52937L,52938L,52939L,52940L,52941L,52942L,52943L,52944L,
97242 52945L,52946L,52947L,52948L,52949L,52950L,52951L,52952L,52953L,52954L,
97243 52955L,52956L,52957L,52958L,52959L,52960L,52961L,52962L,52963L,52964L,
97244 52965L,52966L,52967L,52968L,52969L,52970L,52971L,52972L,52973L,52974L,
97245 52975L,52976L,52977L,52978L,52979L,52980L,52981L,52982L,52983L,52984L,
97246 52985L,52986L,52987L,52988L,52989L,52990L,52991L,52992L,52993L,52994L,
97247 52995L,52996L,52997L,52998L,52999L,53000L,53001L,53002L,53003L,53004L,
97248 53005L,53006L,53007L,53008L,53009L,53010L,53011L,53012L,53013L,53014L,
97249 53015L,53016L,53017L,53018L,53019L,53020L,53021L,53022L,53023L,53024L,
97250 53025L,53026L,53027L,53028L,53029L,53030L,53031L,53032L,53033L,53034L,
97251 53035L,53036L,53037L,53038L,53039L,53040L,53041L,53042L,53043L,53044L,
97252 53045L,53046L,53047L,53048L,53049L,53050L,53051L,53052L,53053L,53054L,
97253 53055L,53056L,53057L,53058L,53059L,53060L,53061L,53062L,53063L,53064L,
97254 53065L,53066L,53067L,53068L,53069L,53070L,53071L,53072L,53073L,53074L,
97255 53075L,53076L,53077L,53078L,53079L,53080L,53081L,53082L,53083L,53084L,
97256 53085L,53086L,53087L,53088L,53089L,53090L,53091L,53092L,53093L,53094L,
97257 53095L,53096L,53097L,53098L,53099L,53100L,53101L,53102L,53103L,53104L,
97258 53105L,53106L,53107L,53108L,53109L,53110L,53111L,53112L,53113L,53114L,
97259 53115L,53116L,53117L,53118L,53119L,53120L,53121L,53122L,53123L,53124L,
97260 53125L,53126L,53127L,53128L,53129L,53130L,53131L,53132L,53133L,53134L,
97261 53135L,53136L,53137L,53138L,53139L,53140L,53141L,53142L,53143L,53144L,
97262 53145L,53146L,53147L,53148L,53149L,53150L,53151L,53152L,53153L,53154L,
97263 53155L,53156L,53157L,53158L,53159L,53160L,53161L,53162L,53163L,53164L,
97264 53165L,53166L,53167L,53168L,53169L,53170L,53171L,53172L,53173L,53174L,
97265 53175L,53176L,53177L,53178L,53179L,53180L,53181L,53182L,53183L,53184L,
97266 53185L,53186L,53187L,53188L,53189L,53190L,53191L,53192L,53193L,53194L,
97267 53195L,53196L,53197L,53198L,53199L,53200L,53201L,53202L,53203L,53204L,
97268 53205L,53206L,53207L,53208L,53209L,53210L,53211L,53212L,53213L,53214L,
97269 53215L,53216L,53217L,53218L,53219L,53220L,53221L,53222L,53223L,53224L,
97270 53225L,53226L,53227L,53228L,53229L,53230L,53231L,53232L,53233L,53234L,
97271 53235L,53236L,53237L,53238L,53239L,53240L,53241L,53242L,53243L,53244L,
97272 53245L,53246L,53247L,53248L,53249L,53250L,53251L,53252L,53253L,53254L,
97273 53255L,53256L,53257L,53258L,53259L,53260L,53261L,53262L,53263L,53264L,
97274 53265L,53266L,53267L,53268L,53269L,53270L,53271L,53272L,53273L,53274L,
97275 53275L,53276L,53277L,53278L,53279L,53280L,53281L,53282L,53283L,53284L,
97276 53285L,53286L,53287L,53288L,53289L,53290L,53291L,53292L,53293L,53294L,
97277 53295L,53296L,53297L,53298L,53299L,53300L,53301L,53302L,53303L,53304L,
97278 53305L,53306L,53307L,53308L,53309L,53310L,53311L,53312L,53313L,53314L,
97279 53315L,53316L,53317L,53318L,53319L,53320L,53321L,53322L,53323L,53324L,
97280 53325L,53326L,53327L,53328L,53329L,53330L,53331L,53332L,53333L,53334L,
97281 53335L,53336L,53337L,53338L,53339L,53340L,53341L,53342L,53343L,53344L,
97282 53345L,53346L,53347L,53348L,53349L,53350L,53351L,53352L,53353L,53354L,
97283 53355L,53356L,53357L,53358L,53359L,53360L,53361L,53362L,53363L,53364L,
97284 53365L,53366L,53367L,53368L,53369L,53370L,53371L,53372L,53373L,53374L,
97285 53375L,53376L,53377L,53378L,53379L,53380L,53381L,53382L,53383L,53384L,
97286 53385L,53386L,53387L,53388L,53389L,53390L,53391L,53392L,53393L,53394L,
97287 53395L,53396L,53397L,53398L,53399L,53400L,53401L,53402L,53403L,53404L,
97288 53405L,53406L,53407L,53408L,53409L,53410L,53411L,53412L,53413L,53414L,
97289 53415L,53416L,53417L,53418L,53419L,53420L,53421L,53422L,53423L,53424L,
97290 53425L,53426L,53427L,53428L,53429L,53430L,53431L,53432L,53433L,53434L,
97291 53435L,53436L,53437L,53438L,53439L,53440L,53441L,53442L,53443L,53444L,
97292 53445L,53446L,53447L,53448L,53449L,53450L,53451L,53452L,53453L,53454L,
97293 53455L,53456L,53457L,53458L,53459L,53460L,53461L,53462L,53463L,53464L,
97294 53465L,53466L,53467L,53468L,53469L,53470L,53471L,53472L,53473L,53474L,
97295 53475L,53476L,53477L,53478L,53479L,53480L,53481L,53482L,53483L,53484L,
97296 53485L,53486L,53487L,53488L,53489L,53490L,53491L,53492L,53493L,53494L,
97297 53495L,53496L,53497L,53498L,53499L,53500L,53501L,53502L,53503L,53504L,
97298 53505L,53506L,53507L,53508L,53509L,53510L,53511L,53512L,53513L,53514L,
97299 53515L,53516L,53517L,53518L,53519L,53520L,53521L,53522L,53523L,53524L,
97300 53525L,53526L,53527L,53528L,53529L,53530L,53531L,53532L,53533L,53534L,
97301 53535L,53536L,53537L,53538L,53539L,53540L,53541L,53542L,53543L,53544L,
97302 53545L,53546L,53547L,53548L,53549L,53550L,53551L,53552L,53553L,53554L,
97303 53555L,53556L,53557L,53558L,53559L,53560L,53561L,53562L,53563L,53564L,
97304 53565L,53566L,53567L,53568L,53569L,53570L,53571L,53572L,53573L,53574L,
97305 53575L,53576L,53577L,53578L,53579L,53580L,53581L,53582L,53583L,53584L,
97306 53585L,53586L,53587L,53588L,53589L,53590L,53591L,53592L,53593L,53594L,
97307 53595L,53596L,53597L,53598L,53599L,53600L,53601L,53602L,53603L,53604L,
97308 53605L,53606L,53607L,53608L,53609L,53610L,53611L,53612L,53613L,53614L,
97309 53615L,53616L,53617L,53618L,53619L,53620L,53621L,53622L,53623L,53624L,
97310 53625L,53626L,53627L,53628L,53629L,53630L,53631L,53632L,53633L,53634L,
97311 53635L,53636L,53637L,53638L,53639L,53640L,53641L,53642L,53643L,53644L,
97312 53645L,53646L,53647L,53648L,53649L,53650L,53651L,53652L,53653L,53654L,
97313 53655L,53656L,53657L,53658L,53659L,53660L,53661L,53662L,53663L,53664L,
97314 53665L,53666L,53667L,53668L,53669L,53670L,53671L,53672L,53673L,53674L,
97315 53675L,53676L,53677L,53678L,53679L,53680L,53681L,53682L,53683L,53684L,
97316 53685L,53686L,53687L,53688L,53689L,53690L,53691L,53692L,53693L,53694L,
97317 53695L,53696L,53697L,53698L,53699L,53700L,53701L,53702L,53703L,53704L,
97318 53705L,53706L,53707L,53708L,53709L,53710L,53711L,53712L,53713L,53714L,
97319 53715L,53716L,53717L,53718L,53719L,53720L,53721L,53722L,53723L,53724L,
97320 53725L,53726L,53727L,53728L,53729L,53730L,53731L,53732L,53733L,53734L,
97321 53735L,53736L,53737L,53738L,53739L,53740L,53741L,53742L,53743L,53744L,
97322 53745L,53746L,53747L,53748L,53749L,53750L,53751L,53752L,53753L,53754L,
97323 53755L,53756L,53757L,53758L,53759L,53760L,53761L,53762L,53763L,53764L,
97324 53765L,53766L,53767L,53768L,53769L,53770L,53771L,53772L,53773L,53774L,
97325 53775L,53776L,53777L,53778L,53779L,53780L,53781L,53782L,53783L,53784L,
97326 53785L,53786L,53787L,53788L,53789L,53790L,53791L,53792L,53793L,53794L,
97327 53795L,53796L,53797L,53798L,53799L,53800L,53801L,53802L,53803L,53804L,
97328 53805L,53806L,53807L,53808L,53809L,53810L,53811L,53812L,53813L,53814L,
97329 53815L,53816L,53817L,53818L,53819L,53820L,53821L,53822L,53823L,53824L,
97330 53825L,53826L,53827L,53828L,53829L,53830L,53831L,53832L,53833L,53834L,
97331 53835L,53836L,53837L,53838L,53839L,53840L,53841L,53842L,53843L,53844L,
97332 53845L,53846L,53847L,53848L,53849L,53850L,53851L,53852L,53853L,53854L,
97333 53855L,53856L,53857L,53858L,53859L,53860L,53861L,53862L,53863L,53864L,
97334 53865L,53866L,53867L,53868L,53869L,53870L,53871L,53872L,53873L,53874L,
97335 53875L,53876L,53877L,53878L,53879L,53880L,53881L,53882L,53883L,53884L,
97336 53885L,53886L,53887L,53888L,53889L,53890L,53891L,53892L,53893L,53894L,
97337 53895L,53896L,53897L,53898L,53899L,53900L,53901L,53902L,53903L,53904L,
97338 53905L,53906L,53907L,53908L,53909L,53910L,53911L,53912L,53913L,53914L,
97339 53915L,53916L,53917L,53918L,53919L,53920L,53921L,53922L,53923L,53924L,
97340 53925L,53926L,53927L,53928L,53929L,53930L,53931L,53932L,53933L,53934L,
97341 53935L,53936L,53937L,53938L,53939L,53940L,53941L,53942L,53943L,53944L,
97342 53945L,53946L,53947L,53948L,53949L,53950L,53951L,53952L,53953L,53954L,
97343 53955L,53956L,53957L,53958L,53959L,53960L,53961L,53962L,53963L,53964L,
97344 53965L,53966L,53967L,53968L,53969L,53970L,53971L,53972L,53973L,53974L,
97345 53975L,53976L,53977L,53978L,53979L,53980L,53981L,53982L,53983L,53984L,
97346 53985L,53986L,53987L,53988L,53989L,53990L,53991L,53992L,53993L,53994L,
97347 53995L,53996L,53997L,53998L,53999L,54000L,54001L,54002L,54003L,54004L,
97348 54005L,54006L,54007L,54008L,54009L,54010L,54011L,54012L,54013L,54014L,
97349 54015L,54016L,54017L,54018L,54019L,54020L,54021L,54022L,54023L,54024L,
97350 54025L,54026L,54027L,54028L,54029L,54030L,54031L,54032L,54033L,54034L,
97351 54035L,54036L,54037L,54038L,54039L,54040L,54041L,54042L,54043L,54044L,
97352 54045L,54046L,54047L,54048L,54049L,54050L,54051L,54052L,54053L,54054L,
97353 54055L,54056L,54057L,54058L,54059L,54060L,54061L,54062L,54063L,54064L,
97354 54065L,54066L,54067L,54068L,54069L,54070L,54071L,54072L,54073L,54074L,
97355 54075L,54076L,54077L,54078L,54079L,54080L,54081L,54082L,54083L,54084L,
97356 54085L,54086L,54087L,54088L,54089L,54090L,54091L,54092L,54093L,54094L,
97357 54095L,54096L,54097L,54098L,54099L,54100L,54101L,54102L,54103L,54104L,
97358 54105L,54106L,54107L,54108L,54109L,54110L,54111L,54112L,54113L,54114L,
97359 54115L,54116L,54117L,54118L,54119L,54120L,54121L,54122L,54123L,54124L,
97360 54125L,54126L,54127L,54128L,54129L,54130L,54131L,54132L,54133L,54134L,
97361 54135L,54136L,54137L,54138L,54139L,54140L,54141L,54142L,54143L,54144L,
97362 54145L,54146L,54147L,54148L,54149L,54150L,54151L,54152L,54153L,54154L,
97363 54155L,54156L,54157L,54158L,54159L,54160L,54161L,54162L,54163L,54164L,
97364 54165L,54166L,54167L,54168L,54169L,54170L,54171L,54172L,54173L,54174L,
97365 54175L,54176L,54177L,54178L,54179L,54180L,54181L,54182L,54183L,54184L,
97366 54185L,54186L,54187L,54188L,54189L,54190L,54191L,54192L,54193L,54194L,
97367 54195L,54196L,54197L,54198L,54199L,54200L,54201L,54202L,54203L,54204L,
97368 54205L,54206L,54207L,54208L,54209L,54210L,54211L,54212L,54213L,54214L,
97369 54215L,54216L,54217L,54218L,54219L,54220L,54221L,54222L,54223L,54224L,
97370 54225L,54226L,54227L,54228L,54229L,54230L,54231L,54232L,54233L,54234L,
97371 54235L,54236L,54237L,54238L,54239L,54240L,54241L,54242L,54243L,54244L,
97372 54245L,54246L,54247L,54248L,54249L,54250L,54251L,54252L,54253L,54254L,
97373 54255L,54256L,54257L,54258L,54259L,54260L,54261L,54262L,54263L,54264L,
97374 54265L,54266L,54267L,54268L,54269L,54270L,54271L,54272L,54273L,54274L,
97375 54275L,54276L,54277L,54278L,54279L,54280L,54281L,54282L,54283L,54284L,
97376 54285L,54286L,54287L,54288L,54289L,54290L,54291L,54292L,54293L,54294L,
97377 54295L,54296L,54297L,54298L,54299L,54300L,54301L,54302L,54303L,54304L,
97378 54305L,54306L,54307L,54308L,54309L,54310L,54311L,54312L,54313L,54314L,
97379 54315L,54316L,54317L,54318L,54319L,54320L,54321L,54322L,54323L,54324L,
97380 54325L,54326L,54327L,54328L,54329L,54330L,54331L,54332L,54333L,54334L,
97381 54335L,54336L,54337L,54338L,54339L,54340L,54341L,54342L,54343L,54344L,
97382 54345L,54346L,54347L,54348L,54349L,54350L,54351L,54352L,54353L,54354L,
97383 54355L,54356L,54357L,54358L,54359L,54360L,54361L,54362L,54363L,54364L,
97384 54365L,54366L,54367L,54368L,54369L,54370L,54371L,54372L,54373L,54374L,
97385 54375L,54376L,54377L,54378L,54379L,54380L,54381L,54382L,54383L,54384L,
97386 54385L,54386L,54387L,54388L,54389L,54390L,54391L,54392L,54393L,54394L,
97387 54395L,54396L,54397L,54398L,54399L,54400L,54401L,54402L,54403L,54404L,
97388 54405L,54406L,54407L,54408L,54409L,54410L,54411L,54412L,54413L,54414L,
97389 54415L,54416L,54417L,54418L,54419L,54420L,54421L,54422L,54423L,54424L,
97390 54425L,54426L,54427L,54428L,54429L,54430L,54431L,54432L,54433L,54434L,
97391 54435L,54436L,54437L,54438L,54439L,54440L,54441L,54442L,54443L,54444L,
97392 54445L,54446L,54447L,54448L,54449L,54450L,54451L,54452L,54453L,54454L,
97393 54455L,54456L,54457L,54458L,54459L,54460L,54461L,54462L,54463L,54464L,
97394 54465L,54466L,54467L,54468L,54469L,54470L,54471L,54472L,54473L,54474L,
97395 54475L,54476L,54477L,54478L,54479L,54480L,54481L,54482L,54483L,54484L,
97396 54485L,54486L,54487L,54488L,54489L,54490L,54491L,54492L,54493L,54494L,
97397 54495L,54496L,54497L,54498L,54499L,54500L,54501L,54502L,54503L,54504L,
97398 54505L,54506L,54507L,54508L,54509L,54510L,54511L,54512L,54513L,54514L,
97399 54515L,54516L,54517L,54518L,54519L,54520L,54521L,54522L,54523L,54524L,
97400 54525L,54526L,54527L,54528L,54529L,54530L,54531L,54532L,54533L,54534L,
97401 54535L,54536L,54537L,54538L,54539L,54540L,54541L,54542L,54543L,54544L,
97402 54545L,54546L,54547L,54548L,54549L,54550L,54551L,54552L,54553L,54554L,
97403 54555L,54556L,54557L,54558L,54559L,54560L,54561L,54562L,54563L,54564L,
97404 54565L,54566L,54567L,54568L,54569L,54570L,54571L,54572L,54573L,54574L,
97405 54575L,54576L,54577L,54578L,54579L,54580L,54581L,54582L,54583L,54584L,
97406 54585L,54586L,54587L,54588L,54589L,54590L,54591L,54592L,54593L,54594L,
97407 54595L,54596L,54597L,54598L,54599L,54600L,54601L,54602L,54603L,54604L,
97408 54605L,54606L,54607L,54608L,54609L,54610L,54611L,54612L,54613L,54614L,
97409 54615L,54616L,54617L,54618L,54619L,54620L,54621L,54622L,54623L,54624L,
97410 54625L,54626L,54627L,54628L,54629L,54630L,54631L,54632L,54633L,54634L,
97411 54635L,54636L,54637L,54638L,54639L,54640L,54641L,54642L,54643L,54644L,
97412 54645L,54646L,54647L,54648L,54649L,54650L,54651L,54652L,54653L,54654L,
97413 54655L,54656L,54657L,54658L,54659L,54660L,54661L,54662L,54663L,54664L,
97414 54665L,54666L,54667L,54668L,54669L,54670L,54671L,54672L,54673L,54674L,
97415 54675L,54676L,54677L,54678L,54679L,54680L,54681L,54682L,54683L,54684L,
97416 54685L,54686L,54687L,54688L,54689L,54690L,54691L,54692L,54693L,54694L,
97417 54695L,54696L,54697L,54698L,54699L,54700L,54701L,54702L,54703L,54704L,
97418 54705L,54706L,54707L,54708L,54709L,54710L,54711L,54712L,54713L,54714L,
97419 54715L,54716L,54717L,54718L,54719L,54720L,54721L,54722L,54723L,54724L,
97420 54725L,54726L,54727L,54728L,54729L,54730L,54731L,54732L,54733L,54734L,
97421 54735L,54736L,54737L,54738L,54739L,54740L,54741L,54742L,54743L,54744L,
97422 54745L,54746L,54747L,54748L,54749L,54750L,54751L,54752L,54753L,54754L,
97423 54755L,54756L,54757L,54758L,54759L,54760L,54761L,54762L,54763L,54764L,
97424 54765L,54766L,54767L,54768L,54769L,54770L,54771L,54772L,54773L,54774L,
97425 54775L,54776L,54777L,54778L,54779L,54780L,54781L,54782L,54783L,54784L,
97426 54785L,54786L,54787L,54788L,54789L,54790L,54791L,54792L,54793L,54794L,
97427 54795L,54796L,54797L,54798L,54799L,54800L,54801L,54802L,54803L,54804L,
97428 54805L,54806L,54807L,54808L,54809L,54810L,54811L,54812L,54813L,54814L,
97429 54815L,54816L,54817L,54818L,54819L,54820L,54821L,54822L,54823L,54824L,
97430 54825L,54826L,54827L,54828L,54829L,54830L,54831L,54832L,54833L,54834L,
97431 54835L,54836L,54837L,54838L,54839L,54840L,54841L,54842L,54843L,54844L,
97432 54845L,54846L,54847L,54848L,54849L,54850L,54851L,54852L,54853L,54854L,
97433 54855L,54856L,54857L,54858L,54859L,54860L,54861L,54862L,54863L,54864L,
97434 54865L,54866L,54867L,54868L,54869L,54870L,54871L,54872L,54873L,54874L,
97435 54875L,54876L,54877L,54878L,54879L,54880L,54881L,54882L,54883L,54884L,
97436 54885L,54886L,54887L,54888L,54889L,54890L,54891L,54892L,54893L,54894L,
97437 54895L,54896L,54897L,54898L,54899L,54900L,54901L,54902L,54903L,54904L,
97438 54905L,54906L,54907L,54908L,54909L,54910L,54911L,54912L,54913L,54914L,
97439 54915L,54916L,54917L,54918L,54919L,54920L,54921L,54922L,54923L,54924L,
97440 54925L,54926L,54927L,54928L,54929L,54930L,54931L,54932L,54933L,54934L,
97441 54935L,54936L,54937L,54938L,54939L,54940L,54941L,54942L,54943L,54944L,
97442 54945L,54946L,54947L,54948L,54949L,54950L,54951L,54952L,54953L,54954L,
97443 54955L,54956L,54957L,54958L,54959L,54960L,54961L,54962L,54963L,54964L,
97444 54965L,54966L,54967L,54968L,54969L,54970L,54971L,54972L,54973L,54974L,
97445 54975L,54976L,54977L,54978L,54979L,54980L,54981L,54982L,54983L,54984L,
97446 54985L,54986L,54987L,54988L,54989L,54990L,54991L,54992L,54993L,54994L,
97447 54995L,54996L,54997L,54998L,54999L,55000L,55001L,55002L,55003L,55004L,
97448 55005L,55006L,55007L,55008L,55009L,55010L,55011L,55012L,55013L,55014L,
97449 55015L,55016L,55017L,55018L,55019L,55020L,55021L,55022L,55023L,55024L,
97450 55025L,55026L,55027L,55028L,55029L,55030L,55031L,55032L,55033L,55034L,
97451 55035L,55036L,55037L,55038L,55039L,55040L,55041L,55042L,55043L,55044L,
97452 55045L,55046L,55047L,55048L,55049L,55050L,55051L,55052L,55053L,55054L,
97453 55055L,55056L,55057L,55058L,55059L,55060L,55061L,55062L,55063L,55064L,
97454 55065L,55066L,55067L,55068L,55069L,55070L,55071L,55072L,55073L,55074L,
97455 55075L,55076L,55077L,55078L,55079L,55080L,55081L,55082L,55083L,55084L,
97456 55085L,55086L,55087L,55088L,55089L,55090L,55091L,55092L,55093L,55094L,
97457 55095L,55096L,55097L,55098L,55099L,55100L,55101L,55102L,55103L,55104L,
97458 55105L,55106L,55107L,55108L,55109L,55110L,55111L,55112L,55113L,55114L,
97459 55115L,55116L,55117L,55118L,55119L,55120L,55121L,55122L,55123L,55124L,
97460 55125L,55126L,55127L,55128L,55129L,55130L,55131L,55132L,55133L,55134L,
97461 55135L,55136L,55137L,55138L,55139L,55140L,55141L,55142L,55143L,55144L,
97462 55145L,55146L,55147L,55148L,55149L,55150L,55151L,55152L,55153L,55154L,
97463 55155L,55156L,55157L,55158L,55159L,55160L,55161L,55162L,55163L,55164L,
97464 55165L,55166L,55167L,55168L,55169L,55170L,55171L,55172L,55173L,55174L,
97465 55175L,55176L,55177L,55178L,55179L,55180L,55181L,55182L,55183L,55184L,
97466 55185L,55186L,55187L,55188L,55189L,55190L,55191L,55192L,55193L,55194L,
97467 55195L,55196L,55197L,55198L,55199L,55200L,55201L,55202L,55203L,55204L,
97468 55205L,55206L,55207L,55208L,55209L,55210L,55211L,55212L,55213L,55214L,
97469 55215L,55216L,55217L,55218L,55219L,55220L,55221L,55222L,55223L,55224L,
97470 55225L,55226L,55227L,55228L,55229L,55230L,55231L,55232L,55233L,55234L,
97471 55235L,55236L,55237L,55238L,55239L,55240L,55241L,55242L,55243L,55244L,
97472 55245L,55246L,55247L,55248L,55249L,55250L,55251L,55252L,55253L,55254L,
97473 55255L,55256L,55257L,55258L,55259L,55260L,55261L,55262L,55263L,55264L,
97474 55265L,55266L,55267L,55268L,55269L,55270L,55271L,55272L,55273L,55274L,
97475 55275L,55276L,55277L,55278L,55279L,55280L,55281L,55282L,55283L,55284L,
97476 55285L,55286L,55287L,55288L,55289L,55290L,55291L,55292L,55293L,55294L,
97477 55295L,55296L,55297L,55298L,55299L,55300L,55301L,55302L,55303L,55304L,
97478 55305L,55306L,55307L,55308L,55309L,55310L,55311L,55312L,55313L,55314L,
97479 55315L,55316L,55317L,55318L,55319L,55320L,55321L,55322L,55323L,55324L,
97480 55325L,55326L,55327L,55328L,55329L,55330L,55331L,55332L,55333L,55334L,
97481 55335L,55336L,55337L,55338L,55339L,55340L,55341L,55342L,55343L,55344L,
97482 55345L,55346L,55347L,55348L,55349L,55350L,55351L,55352L,55353L,55354L,
97483 55355L,55356L,55357L,55358L,55359L,55360L,55361L,55362L,55363L,55364L,
97484 55365L,55366L,55367L,55368L,55369L,55370L,55371L,55372L,55373L,55374L,
97485 55375L,55376L,55377L,55378L,55379L,55380L,55381L,55382L,55383L,55384L,
97486 55385L,55386L,55387L,55388L,55389L,55390L,55391L,55392L,55393L,55394L,
97487 55395L,55396L,55397L,55398L,55399L,55400L,55401L,55402L,55403L,55404L,
97488 55405L,55406L,55407L,55408L,55409L,55410L,55411L,55412L,55413L,55414L,
97489 55415L,55416L,55417L,55418L,55419L,55420L,55421L,55422L,55423L,55424L,
97490 55425L,55426L,55427L,55428L,55429L,55430L,55431L,55432L,55433L,55434L,
97491 55435L,55436L,55437L,55438L,55439L,55440L,55441L,55442L,55443L,55444L,
97492 55445L,55446L,55447L,55448L,55449L,55450L,55451L,55452L,55453L,55454L,
97493 55455L,55456L,55457L,55458L,55459L,55460L,55461L,55462L,55463L,55464L,
97494 55465L,55466L,55467L,55468L,55469L,55470L,55471L,55472L,55473L,55474L,
97495 55475L,55476L,55477L,55478L,55479L,55480L,55481L,55482L,55483L,55484L,
97496 55485L,55486L,55487L,55488L,55489L,55490L,55491L,55492L,55493L,55494L,
97497 55495L,55496L,55497L,55498L,55499L,55500L,55501L,55502L,55503L,55504L,
97498 55505L,55506L,55507L,55508L,55509L,55510L,55511L,55512L,55513L,55514L,
97499 55515L,55516L,55517L,55518L,55519L,55520L,55521L,55522L,55523L,55524L,
97500 55525L,55526L,55527L,55528L,55529L,55530L,55531L,55532L,55533L,55534L,
97501 55535L,55536L,55537L,55538L,55539L,55540L,55541L,55542L,55543L,55544L,
97502 55545L,55546L,55547L,55548L,55549L,55550L,55551L,55552L,55553L,55554L,
97503 55555L,55556L,55557L,55558L,55559L,55560L,55561L,55562L,55563L,55564L,
97504 55565L,55566L,55567L,55568L,55569L,55570L,55571L,55572L,55573L,55574L,
97505 55575L,55576L,55577L,55578L,55579L,55580L,55581L,55582L,55583L,55584L,
97506 55585L,55586L,55587L,55588L,55589L,55590L,55591L,55592L,55593L,55594L,
97507 55595L,55596L,55597L,55598L,55599L,55600L,55601L,55602L,55603L,55604L,
97508 55605L,55606L,55607L,55608L,55609L,55610L,55611L,55612L,55613L,55614L,
97509 55615L,55616L,55617L,55618L,55619L,55620L,55621L,55622L,55623L,55624L,
97510 55625L,55626L,55627L,55628L,55629L,55630L,55631L,55632L,55633L,55634L,
97511 55635L,55636L,55637L,55638L,55639L,55640L,55641L,55642L,55643L,55644L,
97512 55645L,55646L,55647L,55648L,55649L,55650L,55651L,55652L,55653L,55654L,
97513 55655L,55656L,55657L,55658L,55659L,55660L,55661L,55662L,55663L,55664L,
97514 55665L,55666L,55667L,55668L,55669L,55670L,55671L,55672L,55673L,55674L,
97515 55675L,55676L,55677L,55678L,55679L,55680L,55681L,55682L,55683L,55684L,
97516 55685L,55686L,55687L,55688L,55689L,55690L,55691L,55692L,55693L,55694L,
97517 55695L,55696L,55697L,55698L,55699L,55700L,55701L,55702L,55703L,55704L,
97518 55705L,55706L,55707L,55708L,55709L,55710L,55711L,55712L,55713L,55714L,
97519 55715L,55716L,55717L,55718L,55719L,55720L,55721L,55722L,55723L,55724L,
97520 55725L,55726L,55727L,55728L,55729L,55730L,55731L,55732L,55733L,55734L,
97521 55735L,55736L,55737L,55738L,55739L,55740L,55741L,55742L,55743L,55744L,
97522 55745L,55746L,55747L,55748L,55749L,55750L,55751L,55752L,55753L,55754L,
97523 55755L,55756L,55757L,55758L,55759L,55760L,55761L,55762L,55763L,55764L,
97524 55765L,55766L,55767L,55768L,55769L,55770L,55771L,55772L,55773L,55774L,
97525 55775L,55776L,55777L,55778L,55779L,55780L,55781L,55782L,55783L,55784L,
97526 55785L,55786L,55787L,55788L,55789L,55790L,55791L,55792L,55793L,55794L,
97527 55795L,55796L,55797L,55798L,55799L,55800L,55801L,55802L,55803L,55804L,
97528 55805L,55806L,55807L,55808L,55809L,55810L,55811L,55812L,55813L,55814L,
97529 55815L,55816L,55817L,55818L,55819L,55820L,55821L,55822L,55823L,55824L,
97530 55825L,55826L,55827L,55828L,55829L,55830L,55831L,55832L,55833L,55834L,
97531 55835L,55836L,55837L,55838L,55839L,55840L,55841L,55842L,55843L,55844L,
97532 55845L,55846L,55847L,55848L,55849L,55850L,55851L,55852L,55853L,55854L,
97533 55855L,55856L,55857L,55858L,55859L,55860L,55861L,55862L,55863L,55864L,
97534 55865L,55866L,55867L,55868L,55869L,55870L,55871L,55872L,55873L,55874L,
97535 55875L,55876L,55877L,55878L,55879L,55880L,55881L,55882L,55883L,55884L,
97536 55885L,55886L,55887L,55888L,55889L,55890L,55891L,55892L,55893L,55894L,
97537 55895L,55896L,55897L,55898L,55899L,55900L,55901L,55902L,55903L,55904L,
97538 55905L,55906L,55907L,55908L,55909L,55910L,55911L,55912L,55913L,55914L,
97539 55915L,55916L,55917L,55918L,55919L,55920L,55921L,55922L,55923L,55924L,
97540 55925L,55926L,55927L,55928L,55929L,55930L,55931L,55932L,55933L,55934L,
97541 55935L,55936L,55937L,55938L,55939L,55940L,55941L,55942L,55943L,55944L,
97542 55945L,55946L,55947L,55948L,55949L,55950L,55951L,55952L,55953L,55954L,
97543 55955L,55956L,55957L,55958L,55959L,55960L,55961L,55962L,55963L,55964L,
97544 55965L,55966L,55967L,55968L,55969L,55970L,55971L,55972L,55973L,55974L,
97545 55975L,55976L,55977L,55978L,55979L,55980L,55981L,55982L,55983L,55984L,
97546 55985L,55986L,55987L,55988L,55989L,55990L,55991L,55992L,55993L,55994L,
97547 55995L,55996L,55997L,55998L,55999L,56000L,56001L,56002L,56003L,56004L,
97548 56005L,56006L,56007L,56008L,56009L,56010L,56011L,56012L,56013L,56014L,
97549 56015L,56016L,56017L,56018L,56019L,56020L,56021L,56022L,56023L,56024L,
97550 56025L,56026L,56027L,56028L,56029L,56030L,56031L,56032L,56033L,56034L,
97551 56035L,56036L,56037L,56038L,56039L,56040L,56041L,56042L,56043L,56044L,
97552 56045L,56046L,56047L,56048L,56049L,56050L,56051L,56052L,56053L,56054L,
97553 56055L,56056L,56057L,56058L,56059L,56060L,56061L,56062L,56063L,56064L,
97554 56065L,56066L,56067L,56068L,56069L,56070L,56071L,56072L,56073L,56074L,
97555 56075L,56076L,56077L,56078L,56079L,56080L,56081L,56082L,56083L,56084L,
97556 56085L,56086L,56087L,56088L,56089L,56090L,56091L,56092L,56093L,56094L,
97557 56095L,56096L,56097L,56098L,56099L,56100L,56101L,56102L,56103L,56104L,
97558 56105L,56106L,56107L,56108L,56109L,56110L,56111L,56112L,56113L,56114L,
97559 56115L,56116L,56117L,56118L,56119L,56120L,56121L,56122L,56123L,56124L,
97560 56125L,56126L,56127L,56128L,56129L,56130L,56131L,56132L,56133L,56134L,
97561 56135L,56136L,56137L,56138L,56139L,56140L,56141L,56142L,56143L,56144L,
97562 56145L,56146L,56147L,56148L,56149L,56150L,56151L,56152L,56153L,56154L,
97563 56155L,56156L,56157L,56158L,56159L,56160L,56161L,56162L,56163L,56164L,
97564 56165L,56166L,56167L,56168L,56169L,56170L,56171L,56172L,56173L,56174L,
97565 56175L,56176L,56177L,56178L,56179L,56180L,56181L,56182L,56183L,56184L,
97566 56185L,56186L,56187L,56188L,56189L,56190L,56191L,56192L,56193L,56194L,
97567 56195L,56196L,56197L,56198L,56199L,56200L,56201L,56202L,56203L,56204L,
97568 56205L,56206L,56207L,56208L,56209L,56210L,56211L,56212L,56213L,56214L,
97569 56215L,56216L,56217L,56218L,56219L,56220L,56221L,56222L,56223L,56224L,
97570 56225L,56226L,56227L,56228L,56229L,56230L,56231L,56232L,56233L,56234L,
97571 56235L,56236L,56237L,56238L,56239L,56240L,56241L,56242L,56243L,56244L,
97572 56245L,56246L,56247L,56248L,56249L,56250L,56251L,56252L,56253L,56254L,
97573 56255L,56256L,56257L,56258L,56259L,56260L,56261L,56262L,56263L,56264L,
97574 56265L,56266L,56267L,56268L,56269L,56270L,56271L,56272L,56273L,56274L,
97575 56275L,56276L,56277L,56278L,56279L,56280L,56281L,56282L,56283L,56284L,
97576 56285L,56286L,56287L,56288L,56289L,56290L,56291L,56292L,56293L,56294L,
97577 56295L,56296L,56297L,56298L,56299L,56300L,56301L,56302L,56303L,56304L,
97578 56305L,56306L,56307L,56308L,56309L,56310L,56311L,56312L,56313L,56314L,
97579 56315L,56316L,56317L,56318L,56319L,56320L,56321L,56322L,56323L,56324L,
97580 56325L,56326L,56327L,56328L,56329L,56330L,56331L,56332L,56333L,56334L,
97581 56335L,56336L,56337L,56338L,56339L,56340L,56341L,56342L,56343L,56344L,
97582 56345L,56346L,56347L,56348L,56349L,56350L,56351L,56352L,56353L,56354L,
97583 56355L,56356L,56357L,56358L,56359L,56360L,56361L,56362L,56363L,56364L,
97584 56365L,56366L,56367L,56368L,56369L,56370L,56371L,56372L,56373L,56374L,
97585 56375L,56376L,56377L,56378L,56379L,56380L,56381L,56382L,56383L,56384L,
97586 56385L,56386L,56387L,56388L,56389L,56390L,56391L,56392L,56393L,56394L,
97587 56395L,56396L,56397L,56398L,56399L,56400L,56401L,56402L,56403L,56404L,
97588 56405L,56406L,56407L,56408L,56409L,56410L,56411L,56412L,56413L,56414L,
97589 56415L,56416L,56417L,56418L,56419L,56420L,56421L,56422L,56423L,56424L,
97590 56425L,56426L,56427L,56428L,56429L,56430L,56431L,56432L,56433L,56434L,
97591 56435L,56436L,56437L,56438L,56439L,56440L,56441L,56442L,56443L,56444L,
97592 56445L,56446L,56447L,56448L,56449L,56450L,56451L,56452L,56453L,56454L,
97593 56455L,56456L,56457L,56458L,56459L,56460L,56461L,56462L,56463L,56464L,
97594 56465L,56466L,56467L,56468L,56469L,56470L,56471L,56472L,56473L,56474L,
97595 56475L,56476L,56477L,56478L,56479L,56480L,56481L,56482L,56483L,56484L,
97596 56485L,56486L,56487L,56488L,56489L,56490L,56491L,56492L,56493L,56494L,
97597 56495L,56496L,56497L,56498L,56499L,56500L,56501L,56502L,56503L,56504L,
97598 56505L,56506L,56507L,56508L,56509L,56510L,56511L,56512L,56513L,56514L,
97599 56515L,56516L,56517L,56518L,56519L,56520L,56521L,56522L,56523L,56524L,
97600 56525L,56526L,56527L,56528L,56529L,56530L,56531L,56532L,56533L,56534L,
97601 56535L,56536L,56537L,56538L,56539L,56540L,56541L,56542L,56543L,56544L,
97602 56545L,56546L,56547L,56548L,56549L,56550L,56551L,56552L,56553L,56554L,
97603 56555L,56556L,56557L,56558L,56559L,56560L,56561L,56562L,56563L,56564L,
97604 56565L,56566L,56567L,56568L,56569L,56570L,56571L,56572L,56573L,56574L,
97605 56575L,56576L,56577L,56578L,56579L,56580L,56581L,56582L,56583L,56584L,
97606 56585L,56586L,56587L,56588L,56589L,56590L,56591L,56592L,56593L,56594L,
97607 56595L,56596L,56597L,56598L,56599L,56600L,56601L,56602L,56603L,56604L,
97608 56605L,56606L,56607L,56608L,56609L,56610L,56611L,56612L,56613L,56614L,
97609 56615L,56616L,56617L,56618L,56619L,56620L,56621L,56622L,56623L,56624L,
97610 56625L,56626L,56627L,56628L,56629L,56630L,56631L,56632L,56633L,56634L,
97611 56635L,56636L,56637L,56638L,56639L,56640L,56641L,56642L,56643L,56644L,
97612 56645L,56646L,56647L,56648L,56649L,56650L,56651L,56652L,56653L,56654L,
97613 56655L,56656L,56657L,56658L,56659L,56660L,56661L,56662L,56663L,56664L,
97614 56665L,56666L,56667L,56668L,56669L,56670L,56671L,56672L,56673L,56674L,
97615 56675L,56676L,56677L,56678L,56679L,56680L,56681L,56682L,56683L,56684L,
97616 56685L,56686L,56687L,56688L,56689L,56690L,56691L,56692L,56693L,56694L,
97617 56695L,56696L,56697L,56698L,56699L,56700L,56701L,56702L,56703L,56704L,
97618 56705L,56706L,56707L,56708L,56709L,56710L,56711L,56712L,56713L,56714L,
97619 56715L,56716L,56717L,56718L,56719L,56720L,56721L,56722L,56723L,56724L,
97620 56725L,56726L,56727L,56728L,56729L,56730L,56731L,56732L,56733L,56734L,
97621 56735L,56736L,56737L,56738L,56739L,56740L,56741L,56742L,56743L,56744L,
97622 56745L,56746L,56747L,56748L,56749L,56750L,56751L,56752L,56753L,56754L,
97623 56755L,56756L,56757L,56758L,56759L,56760L,56761L,56762L,56763L,56764L,
97624 56765L,56766L,56767L,56768L,56769L,56770L,56771L,56772L,56773L,56774L,
97625 56775L,56776L,56777L,56778L,56779L,56780L,56781L,56782L,56783L,56784L,
97626 56785L,56786L,56787L,56788L,56789L,56790L,56791L,56792L,56793L,56794L,
97627 56795L,56796L,56797L,56798L,56799L,56800L,56801L,56802L,56803L,56804L,
97628 56805L,56806L,56807L,56808L,56809L,56810L,56811L,56812L,56813L,56814L,
97629 56815L,56816L,56817L,56818L,56819L,56820L,56821L,56822L,56823L,56824L,
97630 56825L,56826L,56827L,56828L,56829L,56830L,56831L,56832L,56833L,56834L,
97631 56835L,56836L,56837L,56838L,56839L,56840L,56841L,56842L,56843L,56844L,
97632 56845L,56846L,56847L,56848L,56849L,56850L,56851L,56852L,56853L,56854L,
97633 56855L,56856L,56857L,56858L,56859L,56860L,56861L,56862L,56863L,56864L,
97634 56865L,56866L,56867L,56868L,56869L,56870L,56871L,56872L,56873L,56874L,
97635 56875L,56876L,56877L,56878L,56879L,56880L,56881L,56882L,56883L,56884L,
97636 56885L,56886L,56887L,56888L,56889L,56890L,56891L,56892L,56893L,56894L,
97637 56895L,56896L,56897L,56898L,56899L,56900L,56901L,56902L,56903L,56904L,
97638 56905L,56906L,56907L,56908L,56909L,56910L,56911L,56912L,56913L,56914L,
97639 56915L,56916L,56917L,56918L,56919L,56920L,56921L,56922L,56923L,56924L,
97640 56925L,56926L,56927L,56928L,56929L,56930L,56931L,56932L,56933L,56934L,
97641 56935L,56936L,56937L,56938L,56939L,56940L,56941L,56942L,56943L,56944L,
97642 56945L,56946L,56947L,56948L,56949L,56950L,56951L,56952L,56953L,56954L,
97643 56955L,56956L,56957L,56958L,56959L,56960L,56961L,56962L,56963L,56964L,
97644 56965L,56966L,56967L,56968L,56969L,56970L,56971L,56972L,56973L,56974L,
97645 56975L,56976L,56977L,56978L,56979L,56980L,56981L,56982L,56983L,56984L,
97646 56985L,56986L,56987L,56988L,56989L,56990L,56991L,56992L,56993L,56994L,
97647 56995L,56996L,56997L,56998L,56999L,57000L,57001L,57002L,57003L,57004L,
97648 57005L,57006L,57007L,57008L,57009L,57010L,57011L,57012L,57013L,57014L,
97649 57015L,57016L,57017L,57018L,57019L,57020L,57021L,57022L,57023L,57024L,
97650 57025L,57026L,57027L,57028L,57029L,57030L,57031L,57032L,57033L,57034L,
97651 57035L,57036L,57037L,57038L,57039L,57040L,57041L,57042L,57043L,57044L,
97652 57045L,57046L,57047L,57048L,57049L,57050L,57051L,57052L,57053L,57054L,
97653 57055L,57056L,57057L,57058L,57059L,57060L,57061L,57062L,57063L,57064L,
97654 57065L,57066L,57067L,57068L,57069L,57070L,57071L,57072L,57073L,57074L,
97655 57075L,57076L,57077L,57078L,57079L,57080L,57081L,57082L,57083L,57084L,
97656 57085L,57086L,57087L,57088L,57089L,57090L,57091L,57092L,57093L,57094L,
97657 57095L,57096L,57097L,57098L,57099L,57100L,57101L,57102L,57103L,57104L,
97658 57105L,57106L,57107L,57108L,57109L,57110L,57111L,57112L,57113L,57114L,
97659 57115L,57116L,57117L,57118L,57119L,57120L,57121L,57122L,57123L,57124L,
97660 57125L,57126L,57127L,57128L,57129L,57130L,57131L,57132L,57133L,57134L,
97661 57135L,57136L,57137L,57138L,57139L,57140L,57141L,57142L,57143L,57144L,
97662 57145L,57146L,57147L,57148L,57149L,57150L,57151L,57152L,57153L,57154L,
97663 57155L,57156L,57157L,57158L,57159L,57160L,57161L,57162L,57163L,57164L,
97664 57165L,57166L,57167L,57168L,57169L,57170L,57171L,57172L,57173L,57174L,
97665 57175L,57176L,57177L,57178L,57179L,57180L,57181L,57182L,57183L,57184L,
97666 57185L,57186L,57187L,57188L,57189L,57190L,57191L,57192L,57193L,57194L,
97667 57195L,57196L,57197L,57198L,57199L,57200L,57201L,57202L,57203L,57204L,
97668 57205L,57206L,57207L,57208L,57209L,57210L,57211L,57212L,57213L,57214L,
97669 57215L,57216L,57217L,57218L,57219L,57220L,57221L,57222L,57223L,57224L,
97670 57225L,57226L,57227L,57228L,57229L,57230L,57231L,57232L,57233L,57234L,
97671 57235L,57236L,57237L,57238L,57239L,57240L,57241L,57242L,57243L,57244L,
97672 57245L,57246L,57247L,57248L,57249L,57250L,57251L,57252L,57253L,57254L,
97673 57255L,57256L,57257L,57258L,57259L,57260L,57261L,57262L,57263L,57264L,
97674 57265L,57266L,57267L,57268L,57269L,57270L,57271L,57272L,57273L,57274L,
97675 57275L,57276L,57277L,57278L,57279L,57280L,57281L,57282L,57283L,57284L,
97676 57285L,57286L,57287L,57288L,57289L,57290L,57291L,57292L,57293L,57294L,
97677 57295L,57296L,57297L,57298L,57299L,57300L,57301L,57302L,57303L,57304L,
97678 57305L,57306L,57307L,57308L,57309L,57310L,57311L,57312L,57313L,57314L,
97679 57315L,57316L,57317L,57318L,57319L,57320L,57321L,57322L,57323L,57324L,
97680 57325L,57326L,57327L,57328L,57329L,57330L,57331L,57332L,57333L,57334L,
97681 57335L,57336L,57337L,57338L,57339L,57340L,57341L,57342L,57343L,57344L,
97682 57345L,57346L,57347L,57348L,57349L,57350L,57351L,57352L,57353L,57354L,
97683 57355L,57356L,57357L,57358L,57359L,57360L,57361L,57362L,57363L,57364L,
97684 57365L,57366L,57367L,57368L,57369L,57370L,57371L,57372L,57373L,57374L,
97685 57375L,57376L,57377L,57378L,57379L,57380L,57381L,57382L,57383L,57384L,
97686 57385L,57386L,57387L,57388L,57389L,57390L,57391L,57392L,57393L,57394L,
97687 57395L,57396L,57397L,57398L,57399L,57400L,57401L,57402L,57403L,57404L,
97688 57405L,57406L,57407L,57408L,57409L,57410L,57411L,57412L,57413L,57414L,
97689 57415L,57416L,57417L,57418L,57419L,57420L,57421L,57422L,57423L,57424L,
97690 57425L,57426L,57427L,57428L,57429L,57430L,57431L,57432L,57433L,57434L,
97691 57435L,57436L,57437L,57438L,57439L,57440L,57441L,57442L,57443L,57444L,
97692 57445L,57446L,57447L,57448L,57449L,57450L,57451L,57452L,57453L,57454L,
97693 57455L,57456L,57457L,57458L,57459L,57460L,57461L,57462L,57463L,57464L,
97694 57465L,57466L,57467L,57468L,57469L,57470L,57471L,57472L,57473L,57474L,
97695 57475L,57476L,57477L,57478L,57479L,57480L,57481L,57482L,57483L,57484L,
97696 57485L,57486L,57487L,57488L,57489L,57490L,57491L,57492L,57493L,57494L,
97697 57495L,57496L,57497L,57498L,57499L,57500L,57501L,57502L,57503L,57504L,
97698 57505L,57506L,57507L,57508L,57509L,57510L,57511L,57512L,57513L,57514L,
97699 57515L,57516L,57517L,57518L,57519L,57520L,57521L,57522L,57523L,57524L,
97700 57525L,57526L,57527L,57528L,57529L,57530L,57531L,57532L,57533L,57534L,
97701 57535L,57536L,57537L,57538L,57539L,57540L,57541L,57542L,57543L,57544L,
97702 57545L,57546L,57547L,57548L,57549L,57550L,57551L,57552L,57553L,57554L,
97703 57555L,57556L,57557L,57558L,57559L,57560L,57561L,57562L,57563L,57564L,
97704 57565L,57566L,57567L,57568L,57569L,57570L,57571L,57572L,57573L,57574L,
97705 57575L,57576L,57577L,57578L,57579L,57580L,57581L,57582L,57583L,57584L,
97706 57585L,57586L,57587L,57588L,57589L,57590L,57591L,57592L,57593L,57594L,
97707 57595L,57596L,57597L,57598L,57599L,57600L,57601L,57602L,57603L,57604L,
97708 57605L,57606L,57607L,57608L,57609L,57610L,57611L,57612L,57613L,57614L,
97709 57615L,57616L,57617L,57618L,57619L,57620L,57621L,57622L,57623L,57624L,
97710 57625L,57626L,57627L,57628L,57629L,57630L,57631L,57632L,57633L,57634L,
97711 57635L,57636L,57637L,57638L,57639L,57640L,57641L,57642L,57643L,57644L,
97712 57645L,57646L,57647L,57648L,57649L,57650L,57651L,57652L,57653L,57654L,
97713 57655L,57656L,57657L,57658L,57659L,57660L,57661L,57662L,57663L,57664L,
97714 57665L,57666L,57667L,57668L,57669L,57670L,57671L,57672L,57673L,57674L,
97715 57675L,57676L,57677L,57678L,57679L,57680L,57681L,57682L,57683L,57684L,
97716 57685L,57686L,57687L,57688L,57689L,57690L,57691L,57692L,57693L,57694L,
97717 57695L,57696L,57697L,57698L,57699L,57700L,57701L,57702L,57703L,57704L,
97718 57705L,57706L,57707L,57708L,57709L,57710L,57711L,57712L,57713L,57714L,
97719 57715L,57716L,57717L,57718L,57719L,57720L,57721L,57722L,57723L,57724L,
97720 57725L,57726L,57727L,57728L,57729L,57730L,57731L,57732L,57733L,57734L,
97721 57735L,57736L,57737L,57738L,57739L,57740L,57741L,57742L,57743L,57744L,
97722 57745L,57746L,57747L,57748L,57749L,57750L,57751L,57752L,57753L,57754L,
97723 57755L,57756L,57757L,57758L,57759L,57760L,57761L,57762L,57763L,57764L,
97724 57765L,57766L,57767L,57768L,57769L,57770L,57771L,57772L,57773L,57774L,
97725 57775L,57776L,57777L,57778L,57779L,57780L,57781L,57782L,57783L,57784L,
97726 57785L,57786L,57787L,57788L,57789L,57790L,57791L,57792L,57793L,57794L,
97727 57795L,57796L,57797L,57798L,57799L,57800L,57801L,57802L,57803L,57804L,
97728 57805L,57806L,57807L,57808L,57809L,57810L,57811L,57812L,57813L,57814L,
97729 57815L,57816L,57817L,57818L,57819L,57820L,57821L,57822L,57823L,57824L,
97730 57825L,57826L,57827L,57828L,57829L,57830L,57831L,57832L,57833L,57834L,
97731 57835L,57836L,57837L,57838L,57839L,57840L,57841L,57842L,57843L,57844L,
97732 57845L,57846L,57847L,57848L,57849L,57850L,57851L,57852L,57853L,57854L,
97733 57855L,57856L,57857L,57858L,57859L,57860L,57861L,57862L,57863L,57864L,
97734 57865L,57866L,57867L,57868L,57869L,57870L,57871L,57872L,57873L,57874L,
97735 57875L,57876L,57877L,57878L,57879L,57880L,57881L,57882L,57883L,57884L,
97736 57885L,57886L,57887L,57888L,57889L,57890L,57891L,57892L,57893L,57894L,
97737 57895L,57896L,57897L,57898L,57899L,57900L,57901L,57902L,57903L,57904L,
97738 57905L,57906L,57907L,57908L,57909L,57910L,57911L,57912L,57913L,57914L,
97739 57915L,57916L,57917L,57918L,57919L,57920L,57921L,57922L,57923L,57924L,
97740 57925L,57926L,57927L,57928L,57929L,57930L,57931L,57932L,57933L,57934L,
97741 57935L,57936L,57937L,57938L,57939L,57940L,57941L,57942L,57943L,57944L,
97742 57945L,57946L,57947L,57948L,57949L,57950L,57951L,57952L,57953L,57954L,
97743 57955L,57956L,57957L,57958L,57959L,57960L,57961L,57962L,57963L,57964L,
97744 57965L,57966L,57967L,57968L,57969L,57970L,57971L,57972L,57973L,57974L,
97745 57975L,57976L,57977L,57978L,57979L,57980L,57981L,57982L,57983L,57984L,
97746 57985L,57986L,57987L,57988L,57989L,57990L,57991L,57992L,57993L,57994L,
97747 57995L,57996L,57997L,57998L,57999L,58000L,58001L,58002L,58003L,58004L,
97748 58005L,58006L,58007L,58008L,58009L,58010L,58011L,58012L,58013L,58014L,
97749 58015L,58016L,58017L,58018L,58019L,58020L,58021L,58022L,58023L,58024L,
97750 58025L,58026L,58027L,58028L,58029L,58030L,58031L,58032L,58033L,58034L,
97751 58035L,58036L,58037L,58038L,58039L,58040L,58041L,58042L,58043L,58044L,
97752 58045L,58046L,58047L,58048L,58049L,58050L,58051L,58052L,58053L,58054L,
97753 58055L,58056L,58057L,58058L,58059L,58060L,58061L,58062L,58063L,58064L,
97754 58065L,58066L,58067L,58068L,58069L,58070L,58071L,58072L,58073L,58074L,
97755 58075L,58076L,58077L,58078L,58079L,58080L,58081L,58082L,58083L,58084L,
97756 58085L,58086L,58087L,58088L,58089L,58090L,58091L,58092L,58093L,58094L,
97757 58095L,58096L,58097L,58098L,58099L,58100L,58101L,58102L,58103L,58104L,
97758 58105L,58106L,58107L,58108L,58109L,58110L,58111L,58112L,58113L,58114L,
97759 58115L,58116L,58117L,58118L,58119L,58120L,58121L,58122L,58123L,58124L,
97760 58125L,58126L,58127L,58128L,58129L,58130L,58131L,58132L,58133L,58134L,
97761 58135L,58136L,58137L,58138L,58139L,58140L,58141L,58142L,58143L,58144L,
97762 58145L,58146L,58147L,58148L,58149L,58150L,58151L,58152L,58153L,58154L,
97763 58155L,58156L,58157L,58158L,58159L,58160L,58161L,58162L,58163L,58164L,
97764 58165L,58166L,58167L,58168L,58169L,58170L,58171L,58172L,58173L,58174L,
97765 58175L,58176L,58177L,58178L,58179L,58180L,58181L,58182L,58183L,58184L,
97766 58185L,58186L,58187L,58188L,58189L,58190L,58191L,58192L,58193L,58194L,
97767 58195L,58196L,58197L,58198L,58199L,58200L,58201L,58202L,58203L,58204L,
97768 58205L,58206L,58207L,58208L,58209L,58210L,58211L,58212L,58213L,58214L,
97769 58215L,58216L,58217L,58218L,58219L,58220L,58221L,58222L,58223L,58224L,
97770 58225L,58226L,58227L,58228L,58229L,58230L,58231L,58232L,58233L,58234L,
97771 58235L,58236L,58237L,58238L,58239L,58240L,58241L,58242L,58243L,58244L,
97772 58245L,58246L,58247L,58248L,58249L,58250L,58251L,58252L,58253L,58254L,
97773 58255L,58256L,58257L,58258L,58259L,58260L,58261L,58262L,58263L,58264L,
97774 58265L,58266L,58267L,58268L,58269L,58270L,58271L,58272L,58273L,58274L,
97775 58275L,58276L,58277L,58278L,58279L,58280L,58281L,58282L,58283L,58284L,
97776 58285L,58286L,58287L,58288L,58289L,58290L,58291L,58292L,58293L,58294L,
97777 58295L,58296L,58297L,58298L,58299L,58300L,58301L,58302L,58303L,58304L,
97778 58305L,58306L,58307L,58308L,58309L,58310L,58311L,58312L,58313L,58314L,
97779 58315L,58316L,58317L,58318L,58319L,58320L,58321L,58322L,58323L,58324L,
97780 58325L,58326L,58327L,58328L,58329L,58330L,58331L,58332L,58333L,58334L,
97781 58335L,58336L,58337L,58338L,58339L,58340L,58341L,58342L,58343L,58344L,
97782 58345L,58346L,58347L,58348L,58349L,58350L,58351L,58352L,58353L,58354L,
97783 58355L,58356L,58357L,58358L,58359L,58360L,58361L,58362L,58363L,58364L,
97784 58365L,58366L,58367L,58368L,58369L,58370L,58371L,58372L,58373L,58374L,
97785 58375L,58376L,58377L,58378L,58379L,58380L,58381L,58382L,58383L,58384L,
97786 58385L,58386L,58387L,58388L,58389L,58390L,58391L,58392L,58393L,58394L,
97787 58395L,58396L,58397L,58398L,58399L,58400L,58401L,58402L,58403L,58404L,
97788 58405L,58406L,58407L,58408L,58409L,58410L,58411L,58412L,58413L,58414L,
97789 58415L,58416L,58417L,58418L,58419L,58420L,58421L,58422L,58423L,58424L,
97790 58425L,58426L,58427L,58428L,58429L,58430L,58431L,58432L,58433L,58434L,
97791 58435L,58436L,58437L,58438L,58439L,58440L,58441L,58442L,58443L,58444L,
97792 58445L,58446L,58447L,58448L,58449L,58450L,58451L,58452L,58453L,58454L,
97793 58455L,58456L,58457L,58458L,58459L,58460L,58461L,58462L,58463L,58464L,
97794 58465L,58466L,58467L,58468L,58469L,58470L,58471L,58472L,58473L,58474L,
97795 58475L,58476L,58477L,58478L,58479L,58480L,58481L,58482L,58483L,58484L,
97796 58485L,58486L,58487L,58488L,58489L,58490L,58491L,58492L,58493L,58494L,
97797 58495L,58496L,58497L,58498L,58499L,58500L,58501L,58502L,58503L,58504L,
97798 58505L,58506L,58507L,58508L,58509L,58510L,58511L,58512L,58513L,58514L,
97799 58515L,58516L,58517L,58518L,58519L,58520L,58521L,58522L,58523L,58524L,
97800 58525L,58526L,58527L,58528L,58529L,58530L,58531L,58532L,58533L,58534L,
97801 58535L,58536L,58537L,58538L,58539L,58540L,58541L,58542L,58543L,58544L,
97802 58545L,58546L,58547L,58548L,58549L,58550L,58551L,58552L,58553L,58554L,
97803 58555L,58556L,58557L,58558L,58559L,58560L,58561L,58562L,58563L,58564L,
97804 58565L,58566L,58567L,58568L,58569L,58570L,58571L,58572L,58573L,58574L,
97805 58575L,58576L,58577L,58578L,58579L,58580L,58581L,58582L,58583L,58584L,
97806 58585L,58586L,58587L,58588L,58589L,58590L,58591L,58592L,58593L,58594L,
97807 58595L,58596L,58597L,58598L,58599L,58600L,58601L,58602L,58603L,58604L,
97808 58605L,58606L,58607L,58608L,58609L,58610L,58611L,58612L,58613L,58614L,
97809 58615L,58616L,58617L,58618L,58619L,58620L,58621L,58622L,58623L,58624L,
97810 58625L,58626L,58627L,58628L,58629L,58630L,58631L,58632L,58633L,58634L,
97811 58635L,58636L,58637L,58638L,58639L,58640L,58641L,58642L,58643L,58644L,
97812 58645L,58646L,58647L,58648L,58649L,58650L,58651L,58652L,58653L,58654L,
97813 58655L,58656L,58657L,58658L,58659L,58660L,58661L,58662L,58663L,58664L,
97814 58665L,58666L,58667L,58668L,58669L,58670L,58671L,58672L,58673L,58674L,
97815 58675L,58676L,58677L,58678L,58679L,58680L,58681L,58682L,58683L,58684L,
97816 58685L,58686L,58687L,58688L,58689L,58690L,58691L,58692L,58693L,58694L,
97817 58695L,58696L,58697L,58698L,58699L,58700L,58701L,58702L,58703L,58704L,
97818 58705L,58706L,58707L,58708L,58709L,58710L,58711L,58712L,58713L,58714L,
97819 58715L,58716L,58717L,58718L,58719L,58720L,58721L,58722L,58723L,58724L,
97820 58725L,58726L,58727L,58728L,58729L,58730L,58731L,58732L,58733L,58734L,
97821 58735L,58736L,58737L,58738L,58739L,58740L,58741L,58742L,58743L,58744L,
97822 58745L,58746L,58747L,58748L,58749L,58750L,58751L,58752L,58753L,58754L,
97823 58755L,58756L,58757L,58758L,58759L,58760L,58761L,58762L,58763L,58764L,
97824 58765L,58766L,58767L,58768L,58769L,58770L,58771L,58772L,58773L,58774L,
97825 58775L,58776L,58777L,58778L,58779L,58780L,58781L,58782L,58783L,58784L,
97826 58785L,58786L,58787L,58788L,58789L,58790L,58791L,58792L,58793L,58794L,
97827 58795L,58796L,58797L,58798L,58799L,58800L,58801L,58802L,58803L,58804L,
97828 58805L,58806L,58807L,58808L,58809L,58810L,58811L,58812L,58813L,58814L,
97829 58815L,58816L,58817L,58818L,58819L,58820L,58821L,58822L,58823L,58824L,
97830 58825L,58826L,58827L,58828L,58829L,58830L,58831L,58832L,58833L,58834L,
97831 58835L,58836L,58837L,58838L,58839L,58840L,58841L,58842L,58843L,58844L,
97832 58845L,58846L,58847L,58848L,58849L,58850L,58851L,58852L,58853L,58854L,
97833 58855L,58856L,58857L,58858L,58859L,58860L,58861L,58862L,58863L,58864L,
97834 58865L,58866L,58867L,58868L,58869L,58870L,58871L,58872L,58873L,58874L,
97835 58875L,58876L,58877L,58878L,58879L,58880L,58881L,58882L,58883L,58884L,
97836 58885L,58886L,58887L,58888L,58889L,58890L,58891L,58892L,58893L,58894L,
97837 58895L,58896L,58897L,58898L,58899L,58900L,58901L,58902L,58903L,58904L,
97838 58905L,58906L,58907L,58908L,58909L,58910L,58911L,58912L,58913L,58914L,
97839 58915L,58916L,58917L,58918L,58919L,58920L,58921L,58922L,58923L,58924L,
97840 58925L,58926L,58927L,58928L,58929L,58930L,58931L,58932L,58933L,58934L,
97841 58935L,58936L,58937L,58938L,58939L,58940L,58941L,58942L,58943L,58944L,
97842 58945L,58946L,58947L,58948L,58949L,58950L,58951L,58952L,58953L,58954L,
97843 58955L,58956L,58957L,58958L,58959L,58960L,58961L,58962L,58963L,58964L,
97844 58965L,58966L,58967L,58968L,58969L,58970L,58971L,58972L,58973L,58974L,
97845 58975L,58976L,58977L,58978L,58979L,58980L,58981L,58982L,58983L,58984L,
97846 58985L,58986L,58987L,58988L,58989L,58990L,58991L,58992L,58993L,58994L,
97847 58995L,58996L,58997L,58998L,58999L,59000L,59001L,59002L,59003L,59004L,
97848 59005L,59006L,59007L,59008L,59009L,59010L,59011L,59012L,59013L,59014L,
97849 59015L,59016L,59017L,59018L,59019L,59020L,59021L,59022L,59023L,59024L,
97850 59025L,59026L,59027L,59028L,59029L,59030L,59031L,59032L,59033L,59034L,
97851 59035L,59036L,59037L,59038L,59039L,59040L,59041L,59042L,59043L,59044L,
97852 59045L,59046L,59047L,59048L,59049L,59050L,59051L,59052L,59053L,59054L,
97853 59055L,59056L,59057L,59058L,59059L,59060L,59061L,59062L,59063L,59064L,
97854 59065L,59066L,59067L,59068L,59069L,59070L,59071L,59072L,59073L,59074L,
97855 59075L,59076L,59077L,59078L,59079L,59080L,59081L,59082L,59083L,59084L,
97856 59085L,59086L,59087L,59088L,59089L,59090L,59091L,59092L,59093L,59094L,
97857 59095L,59096L,59097L,59098L,59099L,59100L,59101L,59102L,59103L,59104L,
97858 59105L,59106L,59107L,59108L,59109L,59110L,59111L,59112L,59113L,59114L,
97859 59115L,59116L,59117L,59118L,59119L,59120L,59121L,59122L,59123L,59124L,
97860 59125L,59126L,59127L,59128L,59129L,59130L,59131L,59132L,59133L,59134L,
97861 59135L,59136L,59137L,59138L,59139L,59140L,59141L,59142L,59143L,59144L,
97862 59145L,59146L,59147L,59148L,59149L,59150L,59151L,59152L,59153L,59154L,
97863 59155L,59156L,59157L,59158L,59159L,59160L,59161L,59162L,59163L,59164L,
97864 59165L,59166L,59167L,59168L,59169L,59170L,59171L,59172L,59173L,59174L,
97865 59175L,59176L,59177L,59178L,59179L,59180L,59181L,59182L,59183L,59184L,
97866 59185L,59186L,59187L,59188L,59189L,59190L,59191L,59192L,59193L,59194L,
97867 59195L,59196L,59197L,59198L,59199L,59200L,59201L,59202L,59203L,59204L,
97868 59205L,59206L,59207L,59208L,59209L,59210L,59211L,59212L,59213L,59214L,
97869 59215L,59216L,59217L,59218L,59219L,59220L,59221L,59222L,59223L,59224L,
97870 59225L,59226L,59227L,59228L,59229L,59230L,59231L,59232L,59233L,59234L,
97871 59235L,59236L,59237L,59238L,59239L,59240L,59241L,59242L,59243L,59244L,
97872 59245L,59246L,59247L,59248L,59249L,59250L,59251L,59252L,59253L,59254L,
97873 59255L,59256L,59257L,59258L,59259L,59260L,59261L,59262L,59263L,59264L,
97874 59265L,59266L,59267L,59268L,59269L,59270L,59271L,59272L,59273L,59274L,
97875 59275L,59276L,59277L,59278L,59279L,59280L,59281L,59282L,59283L,59284L,
97876 59285L,59286L,59287L,59288L,59289L,59290L,59291L,59292L,59293L,59294L,
97877 59295L,59296L,59297L,59298L,59299L,59300L,59301L,59302L,59303L,59304L,
97878 59305L,59306L,59307L,59308L,59309L,59310L,59311L,59312L,59313L,59314L,
97879 59315L,59316L,59317L,59318L,59319L,59320L,59321L,59322L,59323L,59324L,
97880 59325L,59326L,59327L,59328L,59329L,59330L,59331L,59332L,59333L,59334L,
97881 59335L,59336L,59337L,59338L,59339L,59340L,59341L,59342L,59343L,59344L,
97882 59345L,59346L,59347L,59348L,59349L,59350L,59351L,59352L,59353L,59354L,
97883 59355L,59356L,59357L,59358L,59359L,59360L,59361L,59362L,59363L,59364L,
97884 59365L,59366L,59367L,59368L,59369L,59370L,59371L,59372L,59373L,59374L,
97885 59375L,59376L,59377L,59378L,59379L,59380L,59381L,59382L,59383L,59384L,
97886 59385L,59386L,59387L,59388L,59389L,59390L,59391L,59392L,59393L,59394L,
97887 59395L,59396L,59397L,59398L,59399L,59400L,59401L,59402L,59403L,59404L,
97888 59405L,59406L,59407L,59408L,59409L,59410L,59411L,59412L,59413L,59414L,
97889 59415L,59416L,59417L,59418L,59419L,59420L,59421L,59422L,59423L,59424L,
97890 59425L,59426L,59427L,59428L,59429L,59430L,59431L,59432L,59433L,59434L,
97891 59435L,59436L,59437L,59438L,59439L,59440L,59441L,59442L,59443L,59444L,
97892 59445L,59446L,59447L,59448L,59449L,59450L,59451L,59452L,59453L,59454L,
97893 59455L,59456L,59457L,59458L,59459L,59460L,59461L,59462L,59463L,59464L,
97894 59465L,59466L,59467L,59468L,59469L,59470L,59471L,59472L,59473L,59474L,
97895 59475L,59476L,59477L,59478L,59479L,59480L,59481L,59482L,59483L,59484L,
97896 59485L,59486L,59487L,59488L,59489L,59490L,59491L,59492L,59493L,59494L,
97897 59495L,59496L,59497L,59498L,59499L,59500L,59501L,59502L,59503L,59504L,
97898 59505L,59506L,59507L,59508L,59509L,59510L,59511L,59512L,59513L,59514L,
97899 59515L,59516L,59517L,59518L,59519L,59520L,59521L,59522L,59523L,59524L,
97900 59525L,59526L,59527L,59528L,59529L,59530L,59531L,59532L,59533L,59534L,
97901 59535L,59536L,59537L,59538L,59539L,59540L,59541L,59542L,59543L,59544L,
97902 59545L,59546L,59547L,59548L,59549L,59550L,59551L,59552L,59553L,59554L,
97903 59555L,59556L,59557L,59558L,59559L,59560L,59561L,59562L,59563L,59564L,
97904 59565L,59566L,59567L,59568L,59569L,59570L,59571L,59572L,59573L,59574L,
97905 59575L,59576L,59577L,59578L,59579L,59580L,59581L,59582L,59583L,59584L,
97906 59585L,59586L,59587L,59588L,59589L,59590L,59591L,59592L,59593L,59594L,
97907 59595L,59596L,59597L,59598L,59599L,59600L,59601L,59602L,59603L,59604L,
97908 59605L,59606L,59607L,59608L,59609L,59610L,59611L,59612L,59613L,59614L,
97909 59615L,59616L,59617L,59618L,59619L,59620L,59621L,59622L,59623L,59624L,
97910 59625L,59626L,59627L,59628L,59629L,59630L,59631L,59632L,59633L,59634L,
97911 59635L,59636L,59637L,59638L,59639L,59640L,59641L,59642L,59643L,59644L,
97912 59645L,59646L,59647L,59648L,59649L,59650L,59651L,59652L,59653L,59654L,
97913 59655L,59656L,59657L,59658L,59659L,59660L,59661L,59662L,59663L,59664L,
97914 59665L,59666L,59667L,59668L,59669L,59670L,59671L,59672L,59673L,59674L,
97915 59675L,59676L,59677L,59678L,59679L,59680L,59681L,59682L,59683L,59684L,
97916 59685L,59686L,59687L,59688L,59689L,59690L,59691L,59692L,59693L,59694L,
97917 59695L,59696L,59697L,59698L,59699L,59700L,59701L,59702L,59703L,59704L,
97918 59705L,59706L,59707L,59708L,59709L,59710L,59711L,59712L,59713L,59714L,
97919 59715L,59716L,59717L,59718L,59719L,59720L,59721L,59722L,59723L,59724L,
97920 59725L,59726L,59727L,59728L,59729L,59730L,59731L,59732L,59733L,59734L,
97921 59735L,59736L,59737L,59738L,59739L,59740L,59741L,59742L,59743L,59744L,
97922 59745L,59746L,59747L,59748L,59749L,59750L,59751L,59752L,59753L,59754L,
97923 59755L,59756L,59757L,59758L,59759L,59760L,59761L,59762L,59763L,59764L,
97924 59765L,59766L,59767L,59768L,59769L,59770L,59771L,59772L,59773L,59774L,
97925 59775L,59776L,59777L,59778L,59779L,59780L,59781L,59782L,59783L,59784L,
97926 59785L,59786L,59787L,59788L,59789L,59790L,59791L,59792L,59793L,59794L,
97927 59795L,59796L,59797L,59798L,59799L,59800L,59801L,59802L,59803L,59804L,
97928 59805L,59806L,59807L,59808L,59809L,59810L,59811L,59812L,59813L,59814L,
97929 59815L,59816L,59817L,59818L,59819L,59820L,59821L,59822L,59823L,59824L,
97930 59825L,59826L,59827L,59828L,59829L,59830L,59831L,59832L,59833L,59834L,
97931 59835L,59836L,59837L,59838L,59839L,59840L,59841L,59842L,59843L,59844L,
97932 59845L,59846L,59847L,59848L,59849L,59850L,59851L,59852L,59853L,59854L,
97933 59855L,59856L,59857L,59858L,59859L,59860L,59861L,59862L,59863L,59864L,
97934 59865L,59866L,59867L,59868L,59869L,59870L,59871L,59872L,59873L,59874L,
97935 59875L,59876L,59877L,59878L,59879L,59880L,59881L,59882L,59883L,59884L,
97936 59885L,59886L,59887L,59888L,59889L,59890L,59891L,59892L,59893L,59894L,
97937 59895L,59896L,59897L,59898L,59899L,59900L,59901L,59902L,59903L,59904L,
97938 59905L,59906L,59907L,59908L,59909L,59910L,59911L,59912L,59913L,59914L,
97939 59915L,59916L,59917L,59918L,59919L,59920L,59921L,59922L,59923L,59924L,
97940 59925L,59926L,59927L,59928L,59929L,59930L,59931L,59932L,59933L,59934L,
97941 59935L,59936L,59937L,59938L,59939L,59940L,59941L,59942L,59943L,59944L,
97942 59945L,59946L,59947L,59948L,59949L,59950L,59951L,59952L,59953L,59954L,
97943 59955L,59956L,59957L,59958L,59959L,59960L,59961L,59962L,59963L,59964L,
97944 59965L,59966L,59967L,59968L,59969L,59970L,59971L,59972L,59973L,59974L,
97945 59975L,59976L,59977L,59978L,59979L,59980L,59981L,59982L,59983L,59984L,
97946 59985L,59986L,59987L,59988L,59989L,59990L,59991L,59992L,59993L,59994L,
97947 59995L,59996L,59997L,59998L,59999L,60000L,60001L,60002L,60003L,60004L,
97948 60005L,60006L,60007L,60008L,60009L,60010L,60011L,60012L,60013L,60014L,
97949 60015L,60016L,60017L,60018L,60019L,60020L,60021L,60022L,60023L,60024L,
97950 60025L,60026L,60027L,60028L,60029L,60030L,60031L,60032L,60033L,60034L,
97951 60035L,60036L,60037L,60038L,60039L,60040L,60041L,60042L,60043L,60044L,
97952 60045L,60046L,60047L,60048L,60049L,60050L,60051L,60052L,60053L,60054L,
97953 60055L,60056L,60057L,60058L,60059L,60060L,60061L,60062L,60063L,60064L,
97954 60065L,60066L,60067L,60068L,60069L,60070L,60071L,60072L,60073L,60074L,
97955 60075L,60076L,60077L,60078L,60079L,60080L,60081L,60082L,60083L,60084L,
97956 60085L,60086L,60087L,60088L,60089L,60090L,60091L,60092L,60093L,60094L,
97957 60095L,60096L,60097L,60098L,60099L,60100L,60101L,60102L,60103L,60104L,
97958 60105L,60106L,60107L,60108L,60109L,60110L,60111L,60112L,60113L,60114L,
97959 60115L,60116L,60117L,60118L,60119L,60120L,60121L,60122L,60123L,60124L,
97960 60125L,60126L,60127L,60128L,60129L,60130L,60131L,60132L,60133L,60134L,
97961 60135L,60136L,60137L,60138L,60139L,60140L,60141L,60142L,60143L,60144L,
97962 60145L,60146L,60147L,60148L,60149L,60150L,60151L,60152L,60153L,60154L,
97963 60155L,60156L,60157L,60158L,60159L,60160L,60161L,60162L,60163L,60164L,
97964 60165L,60166L,60167L,60168L,60169L,60170L,60171L,60172L,60173L,60174L,
97965 60175L,60176L,60177L,60178L,60179L,60180L,60181L,60182L,60183L,60184L,
97966 60185L,60186L,60187L,60188L,60189L,60190L,60191L,60192L,60193L,60194L,
97967 60195L,60196L,60197L,60198L,60199L,60200L,60201L,60202L,60203L,60204L,
97968 60205L,60206L,60207L,60208L,60209L,60210L,60211L,60212L,60213L,60214L,
97969 60215L,60216L,60217L,60218L,60219L,60220L,60221L,60222L,60223L,60224L,
97970 60225L,60226L,60227L,60228L,60229L,60230L,60231L,60232L,60233L,60234L,
97971 60235L,60236L,60237L,60238L,60239L,60240L,60241L,60242L,60243L,60244L,
97972 60245L,60246L,60247L,60248L,60249L,60250L,60251L,60252L,60253L,60254L,
97973 60255L,60256L,60257L,60258L,60259L,60260L,60261L,60262L,60263L,60264L,
97974 60265L,60266L,60267L,60268L,60269L,60270L,60271L,60272L,60273L,60274L,
97975 60275L,60276L,60277L,60278L,60279L,60280L,60281L,60282L,60283L,60284L,
97976 60285L,60286L,60287L,60288L,60289L,60290L,60291L,60292L,60293L,60294L,
97977 60295L,60296L,60297L,60298L,60299L,60300L,60301L,60302L,60303L,60304L,
97978 60305L,60306L,60307L,60308L,60309L,60310L,60311L,60312L,60313L,60314L,
97979 60315L,60316L,60317L,60318L,60319L,60320L,60321L,60322L,60323L,60324L,
97980 60325L,60326L,60327L,60328L,60329L,60330L,60331L,60332L,60333L,60334L,
97981 60335L,60336L,60337L,60338L,60339L,60340L,60341L,60342L,60343L,60344L,
97982 60345L,60346L,60347L,60348L,60349L,60350L,60351L,60352L,60353L,60354L,
97983 60355L,60356L,60357L,60358L,60359L,60360L,60361L,60362L,60363L,60364L,
97984 60365L,60366L,60367L,60368L,60369L,60370L,60371L,60372L,60373L,60374L,
97985 60375L,60376L,60377L,60378L,60379L,60380L,60381L,60382L,60383L,60384L,
97986 60385L,60386L,60387L,60388L,60389L,60390L,60391L,60392L,60393L,60394L,
97987 60395L,60396L,60397L,60398L,60399L,60400L,60401L,60402L,60403L,60404L,
97988 60405L,60406L,60407L,60408L,60409L,60410L,60411L,60412L,60413L,60414L,
97989 60415L,60416L,60417L,60418L,60419L,60420L,60421L,60422L,60423L,60424L,
97990 60425L,60426L,60427L,60428L,60429L,60430L,60431L,60432L,60433L,60434L,
97991 60435L,60436L,60437L,60438L,60439L,60440L,60441L,60442L,60443L,60444L,
97992 60445L,60446L,60447L,60448L,60449L,60450L,60451L,60452L,60453L,60454L,
97993 60455L,60456L,60457L,60458L,60459L,60460L,60461L,60462L,60463L,60464L,
97994 60465L,60466L,60467L,60468L,60469L,60470L,60471L,60472L,60473L,60474L,
97995 60475L,60476L,60477L,60478L,60479L,60480L,60481L,60482L,60483L,60484L,
97996 60485L,60486L,60487L,60488L,60489L,60490L,60491L,60492L,60493L,60494L,
97997 60495L,60496L,60497L,60498L,60499L,60500L,60501L,60502L,60503L,60504L,
97998 60505L,60506L,60507L,60508L,60509L,60510L,60511L,60512L,60513L,60514L,
97999 60515L,60516L,60517L,60518L,60519L,60520L,60521L,60522L,60523L,60524L,
98000 60525L,60526L,60527L,60528L,60529L,60530L,60531L,60532L,60533L,60534L,
98001 60535L,60536L,60537L,60538L,60539L,60540L,60541L,60542L,60543L,60544L,
98002 60545L,60546L,60547L,60548L,60549L,60550L,60551L,60552L,60553L,60554L,
98003 60555L,60556L,60557L,60558L,60559L,60560L,60561L,60562L,60563L,60564L,
98004 60565L,60566L,60567L,60568L,60569L,60570L,60571L,60572L,60573L,60574L,
98005 60575L,60576L,60577L,60578L,60579L,60580L,60581L,60582L,60583L,60584L,
98006 60585L,60586L,60587L,60588L,60589L,60590L,60591L,60592L,60593L,60594L,
98007 60595L,60596L,60597L,60598L,60599L,60600L,60601L,60602L,60603L,60604L,
98008 60605L,60606L,60607L,60608L,60609L,60610L,60611L,60612L,60613L,60614L,
98009 60615L,60616L,60617L,60618L,60619L,60620L,60621L,60622L,60623L,60624L,
98010 60625L,60626L,60627L,60628L,60629L,60630L,60631L,60632L,60633L,60634L,
98011 60635L,60636L,60637L,60638L,60639L,60640L,60641L,60642L,60643L,60644L,
98012 60645L,60646L,60647L,60648L,60649L,60650L,60651L,60652L,60653L,60654L,
98013 60655L,60656L,60657L,60658L,60659L,60660L,60661L,60662L,60663L,60664L,
98014 60665L,60666L,60667L,60668L,60669L,60670L,60671L,60672L,60673L,60674L,
98015 60675L,60676L,60677L,60678L,60679L,60680L,60681L,60682L,60683L,60684L,
98016 60685L,60686L,60687L,60688L,60689L,60690L,60691L,60692L,60693L,60694L,
98017 60695L,60696L,60697L,60698L,60699L,60700L,60701L,60702L,60703L,60704L,
98018 60705L,60706L,60707L,60708L,60709L,60710L,60711L,60712L,60713L,60714L,
98019 60715L,60716L,60717L,60718L,60719L,60720L,60721L,60722L,60723L,60724L,
98020 60725L,60726L,60727L,60728L,60729L,60730L,60731L,60732L,60733L,60734L,
98021 60735L,60736L,60737L,60738L,60739L,60740L,60741L,60742L,60743L,60744L,
98022 60745L,60746L,60747L,60748L,60749L,60750L,60751L,60752L,60753L,60754L,
98023 60755L,60756L,60757L,60758L,60759L,60760L,60761L,60762L,60763L,60764L,
98024 60765L,60766L,60767L,60768L,60769L,60770L,60771L,60772L,60773L,60774L,
98025 60775L,60776L,60777L,60778L,60779L,60780L,60781L,60782L,60783L,60784L,
98026 60785L,60786L,60787L,60788L,60789L,60790L,60791L,60792L,60793L,60794L,
98027 60795L,60796L,60797L,60798L,60799L,60800L,60801L,60802L,60803L,60804L,
98028 60805L,60806L,60807L,60808L,60809L,60810L,60811L,60812L,60813L,60814L,
98029 60815L,60816L,60817L,60818L,60819L,60820L,60821L,60822L,60823L,60824L,
98030 60825L,60826L,60827L,60828L,60829L,60830L,60831L,60832L,60833L,60834L,
98031 60835L,60836L,60837L,60838L,60839L,60840L,60841L,60842L,60843L,60844L,
98032 60845L,60846L,60847L,60848L,60849L,60850L,60851L,60852L,60853L,60854L,
98033 60855L,60856L,60857L,60858L,60859L,60860L,60861L,60862L,60863L,60864L,
98034 60865L,60866L,60867L,60868L,60869L,60870L,60871L,60872L,60873L,60874L,
98035 60875L,60876L,60877L,60878L,60879L,60880L,60881L,60882L,60883L,60884L,
98036 60885L,60886L,60887L,60888L,60889L,60890L,60891L,60892L,60893L,60894L,
98037 60895L,60896L,60897L,60898L,60899L,60900L,60901L,60902L,60903L,60904L,
98038 60905L,60906L,60907L,60908L,60909L,60910L,60911L,60912L,60913L,60914L,
98039 60915L,60916L,60917L,60918L,60919L,60920L,60921L,60922L,60923L,60924L,
98040 60925L,60926L,60927L,60928L,60929L,60930L,60931L,60932L,60933L,60934L,
98041 60935L,60936L,60937L,60938L,60939L,60940L,60941L,60942L,60943L,60944L,
98042 60945L,60946L,60947L,60948L,60949L,60950L,60951L,60952L,60953L,60954L,
98043 60955L,60956L,60957L,60958L,60959L,60960L,60961L,60962L,60963L,60964L,
98044 60965L,60966L,60967L,60968L,60969L,60970L,60971L,60972L,60973L,60974L,
98045 60975L,60976L,60977L,60978L,60979L,60980L,60981L,60982L,60983L,60984L,
98046 60985L,60986L,60987L,60988L,60989L,60990L,60991L,60992L,60993L,60994L,
98047 60995L,60996L,60997L,60998L,60999L,61000L,61001L,61002L,61003L,61004L,
98048 61005L,61006L,61007L,61008L,61009L,61010L,61011L,61012L,61013L,61014L,
98049 61015L,61016L,61017L,61018L,61019L,61020L,61021L,61022L,61023L,61024L,
98050 61025L,61026L,61027L,61028L,61029L,61030L,61031L,61032L,61033L,61034L,
98051 61035L,61036L,61037L,61038L,61039L,61040L,61041L,61042L,61043L,61044L,
98052 61045L,61046L,61047L,61048L,61049L,61050L,61051L,61052L,61053L,61054L,
98053 61055L,61056L,61057L,61058L,61059L,61060L,61061L,61062L,61063L,61064L,
98054 61065L,61066L,61067L,61068L,61069L,61070L,61071L,61072L,61073L,61074L,
98055 61075L,61076L,61077L,61078L,61079L,61080L,61081L,61082L,61083L,61084L,
98056 61085L,61086L,61087L,61088L,61089L,61090L,61091L,61092L,61093L,61094L,
98057 61095L,61096L,61097L,61098L,61099L,61100L,61101L,61102L,61103L,61104L,
98058 61105L,61106L,61107L,61108L,61109L,61110L,61111L,61112L,61113L,61114L,
98059 61115L,61116L,61117L,61118L,61119L,61120L,61121L,61122L,61123L,61124L,
98060 61125L,61126L,61127L,61128L,61129L,61130L,61131L,61132L,61133L,61134L,
98061 61135L,61136L,61137L,61138L,61139L,61140L,61141L,61142L,61143L,61144L,
98062 61145L,61146L,61147L,61148L,61149L,61150L,61151L,61152L,61153L,61154L,
98063 61155L,61156L,61157L,61158L,61159L,61160L,61161L,61162L,61163L,61164L,
98064 61165L,61166L,61167L,61168L,61169L,61170L,61171L,61172L,61173L,61174L,
98065 61175L,61176L,61177L,61178L,61179L,61180L,61181L,61182L,61183L,61184L,
98066 61185L,61186L,61187L,61188L,61189L,61190L,61191L,61192L,61193L,61194L,
98067 61195L,61196L,61197L,61198L,61199L,61200L,61201L,61202L,61203L,61204L,
98068 61205L,61206L,61207L,61208L,61209L,61210L,61211L,61212L,61213L,61214L,
98069 61215L,61216L,61217L,61218L,61219L,61220L,61221L,61222L,61223L,61224L,
98070 61225L,61226L,61227L,61228L,61229L,61230L,61231L,61232L,61233L,61234L,
98071 61235L,61236L,61237L,61238L,61239L,61240L,61241L,61242L,61243L,61244L,
98072 61245L,61246L,61247L,61248L,61249L,61250L,61251L,61252L,61253L,61254L,
98073 61255L,61256L,61257L,61258L,61259L,61260L,61261L,61262L,61263L,61264L,
98074 61265L,61266L,61267L,61268L,61269L,61270L,61271L,61272L,61273L,61274L,
98075 61275L,61276L,61277L,61278L,61279L,61280L,61281L,61282L,61283L,61284L,
98076 61285L,61286L,61287L,61288L,61289L,61290L,61291L,61292L,61293L,61294L,
98077 61295L,61296L,61297L,61298L,61299L,61300L,61301L,61302L,61303L,61304L,
98078 61305L,61306L,61307L,61308L,61309L,61310L,61311L,61312L,61313L,61314L,
98079 61315L,61316L,61317L,61318L,61319L,61320L,61321L,61322L,61323L,61324L,
98080 61325L,61326L,61327L,61328L,61329L,61330L,61331L,61332L,61333L,61334L,
98081 61335L,61336L,61337L,61338L,61339L,61340L,61341L,61342L,61343L,61344L,
98082 61345L,61346L,61347L,61348L,61349L,61350L,61351L,61352L,61353L,61354L,
98083 61355L,61356L,61357L,61358L,61359L,61360L,61361L,61362L,61363L,61364L,
98084 61365L,61366L,61367L,61368L,61369L,61370L,61371L,61372L,61373L,61374L,
98085 61375L,61376L,61377L,61378L,61379L,61380L,61381L,61382L,61383L,61384L,
98086 61385L,61386L,61387L,61388L,61389L,61390L,61391L,61392L,61393L,61394L,
98087 61395L,61396L,61397L,61398L,61399L,61400L,61401L,61402L,61403L,61404L,
98088 61405L,61406L,61407L,61408L,61409L,61410L,61411L,61412L,61413L,61414L,
98089 61415L,61416L,61417L,61418L,61419L,61420L,61421L,61422L,61423L,61424L,
98090 61425L,61426L,61427L,61428L,61429L,61430L,61431L,61432L,61433L,61434L,
98091 61435L,61436L,61437L,61438L,61439L,61440L,61441L,61442L,61443L,61444L,
98092 61445L,61446L,61447L,61448L,61449L,61450L,61451L,61452L,61453L,61454L,
98093 61455L,61456L,61457L,61458L,61459L,61460L,61461L,61462L,61463L,61464L,
98094 61465L,61466L,61467L,61468L,61469L,61470L,61471L,61472L,61473L,61474L,
98095 61475L,61476L,61477L,61478L,61479L,61480L,61481L,61482L,61483L,61484L,
98096 61485L,61486L,61487L,61488L,61489L,61490L,61491L,61492L,61493L,61494L,
98097 61495L,61496L,61497L,61498L,61499L,61500L,61501L,61502L,61503L,61504L,
98098 61505L,61506L,61507L,61508L,61509L,61510L,61511L,61512L,61513L,61514L,
98099 61515L,61516L,61517L,61518L,61519L,61520L,61521L,61522L,61523L,61524L,
98100 61525L,61526L,61527L,61528L,61529L,61530L,61531L,61532L,61533L,61534L,
98101 61535L,61536L,61537L,61538L,61539L,61540L,61541L,61542L,61543L,61544L,
98102 61545L,61546L,61547L,61548L,61549L,61550L,61551L,61552L,61553L,61554L,
98103 61555L,61556L,61557L,61558L,61559L,61560L,61561L,61562L,61563L,61564L,
98104 61565L,61566L,61567L,61568L,61569L,61570L,61571L,61572L,61573L,61574L,
98105 61575L,61576L,61577L,61578L,61579L,61580L,61581L,61582L,61583L,61584L,
98106 61585L,61586L,61587L,61588L,61589L,61590L,61591L,61592L,61593L,61594L,
98107 61595L,61596L,61597L,61598L,61599L,61600L,61601L,61602L,61603L,61604L,
98108 61605L,61606L,61607L,61608L,61609L,61610L,61611L,61612L,61613L,61614L,
98109 61615L,61616L,61617L,61618L,61619L,61620L,61621L,61622L,61623L,61624L,
98110 61625L,61626L,61627L,61628L,61629L,61630L,61631L,61632L,61633L,61634L,
98111 61635L,61636L,61637L,61638L,61639L,61640L,61641L,61642L,61643L,61644L,
98112 61645L,61646L,61647L,61648L,61649L,61650L,61651L,61652L,61653L,61654L,
98113 61655L,61656L,61657L,61658L,61659L,61660L,61661L,61662L,61663L,61664L,
98114 61665L,61666L,61667L,61668L,61669L,61670L,61671L,61672L,61673L,61674L,
98115 61675L,61676L,61677L,61678L,61679L,61680L,61681L,61682L,61683L,61684L,
98116 61685L,61686L,61687L,61688L,61689L,61690L,61691L,61692L,61693L,61694L,
98117 61695L,61696L,61697L,61698L,61699L,61700L,61701L,61702L,61703L,61704L,
98118 61705L,61706L,61707L,61708L,61709L,61710L,61711L,61712L,61713L,61714L,
98119 61715L,61716L,61717L,61718L,61719L,61720L,61721L,61722L,61723L,61724L,
98120 61725L,61726L,61727L,61728L,61729L,61730L,61731L,61732L,61733L,61734L,
98121 61735L,61736L,61737L,61738L,61739L,61740L,61741L,61742L,61743L,61744L,
98122 61745L,61746L,61747L,61748L,61749L,61750L,61751L,61752L,61753L,61754L,
98123 61755L,61756L,61757L,61758L,61759L,61760L,61761L,61762L,61763L,61764L,
98124 61765L,61766L,61767L,61768L,61769L,61770L,61771L,61772L,61773L,61774L,
98125 61775L,61776L,61777L,61778L,61779L,61780L,61781L,61782L,61783L,61784L,
98126 61785L,61786L,61787L,61788L,61789L,61790L,61791L,61792L,61793L,61794L,
98127 61795L,61796L,61797L,61798L,61799L,61800L,61801L,61802L,61803L,61804L,
98128 61805L,61806L,61807L,61808L,61809L,61810L,61811L,61812L,61813L,61814L,
98129 61815L,61816L,61817L,61818L,61819L,61820L,61821L,61822L,61823L,61824L,
98130 61825L,61826L,61827L,61828L,61829L,61830L,61831L,61832L,61833L,61834L,
98131 61835L,61836L,61837L,61838L,61839L,61840L,61841L,61842L,61843L,61844L,
98132 61845L,61846L,61847L,61848L,61849L,61850L,61851L,61852L,61853L,61854L,
98133 61855L,61856L,61857L,61858L,61859L,61860L,61861L,61862L,61863L,61864L,
98134 61865L,61866L,61867L,61868L,61869L,61870L,61871L,61872L,61873L,61874L,
98135 61875L,61876L,61877L,61878L,61879L,61880L,61881L,61882L,61883L,61884L,
98136 61885L,61886L,61887L,61888L,61889L,61890L,61891L,61892L,61893L,61894L,
98137 61895L,61896L,61897L,61898L,61899L,61900L,61901L,61902L,61903L,61904L,
98138 61905L,61906L,61907L,61908L,61909L,61910L,61911L,61912L,61913L,61914L,
98139 61915L,61916L,61917L,61918L,61919L,61920L,61921L,61922L,61923L,61924L,
98140 61925L,61926L,61927L,61928L,61929L,61930L,61931L,61932L,61933L,61934L,
98141 61935L,61936L,61937L,61938L,61939L,61940L,61941L,61942L,61943L,61944L,
98142 61945L,61946L,61947L,61948L,61949L,61950L,61951L,61952L,61953L,61954L,
98143 61955L,61956L,61957L,61958L,61959L,61960L,61961L,61962L,61963L,61964L,
98144 61965L,61966L,61967L,61968L,61969L,61970L,61971L,61972L,61973L,61974L,
98145 61975L,61976L,61977L,61978L,61979L,61980L,61981L,61982L,61983L,61984L,
98146 61985L,61986L,61987L,61988L,61989L,61990L,61991L,61992L,61993L,61994L,
98147 61995L,61996L,61997L,61998L,61999L,62000L,62001L,62002L,62003L,62004L,
98148 62005L,62006L,62007L,62008L,62009L,62010L,62011L,62012L,62013L,62014L,
98149 62015L,62016L,62017L,62018L,62019L,62020L,62021L,62022L,62023L,62024L,
98150 62025L,62026L,62027L,62028L,62029L,62030L,62031L,62032L,62033L,62034L,
98151 62035L,62036L,62037L,62038L,62039L,62040L,62041L,62042L,62043L,62044L,
98152 62045L,62046L,62047L,62048L,62049L,62050L,62051L,62052L,62053L,62054L,
98153 62055L,62056L,62057L,62058L,62059L,62060L,62061L,62062L,62063L,62064L,
98154 62065L,62066L,62067L,62068L,62069L,62070L,62071L,62072L,62073L,62074L,
98155 62075L,62076L,62077L,62078L,62079L,62080L,62081L,62082L,62083L,62084L,
98156 62085L,62086L,62087L,62088L,62089L,62090L,62091L,62092L,62093L,62094L,
98157 62095L,62096L,62097L,62098L,62099L,62100L,62101L,62102L,62103L,62104L,
98158 62105L,62106L,62107L,62108L,62109L,62110L,62111L,62112L,62113L,62114L,
98159 62115L,62116L,62117L,62118L,62119L,62120L,62121L,62122L,62123L,62124L,
98160 62125L,62126L,62127L,62128L,62129L,62130L,62131L,62132L,62133L,62134L,
98161 62135L,62136L,62137L,62138L,62139L,62140L,62141L,62142L,62143L,62144L,
98162 62145L,62146L,62147L,62148L,62149L,62150L,62151L,62152L,62153L,62154L,
98163 62155L,62156L,62157L,62158L,62159L,62160L,62161L,62162L,62163L,62164L,
98164 62165L,62166L,62167L,62168L,62169L,62170L,62171L,62172L,62173L,62174L,
98165 62175L,62176L,62177L,62178L,62179L,62180L,62181L,62182L,62183L,62184L,
98166 62185L,62186L,62187L,62188L,62189L,62190L,62191L,62192L,62193L,62194L,
98167 62195L,62196L,62197L,62198L,62199L,62200L,62201L,62202L,62203L,62204L,
98168 62205L,62206L,62207L,62208L,62209L,62210L,62211L,62212L,62213L,62214L,
98169 62215L,62216L,62217L,62218L,62219L,62220L,62221L,62222L,62223L,62224L,
98170 62225L,62226L,62227L,62228L,62229L,62230L,62231L,62232L,62233L,62234L,
98171 62235L,62236L,62237L,62238L,62239L,62240L,62241L,62242L,62243L,62244L,
98172 62245L,62246L,62247L,62248L,62249L,62250L,62251L,62252L,62253L,62254L,
98173 62255L,62256L,62257L,62258L,62259L,62260L,62261L,62262L,62263L,62264L,
98174 62265L,62266L,62267L,62268L,62269L,62270L,62271L,62272L,62273L,62274L,
98175 62275L,62276L,62277L,62278L,62279L,62280L,62281L,62282L,62283L,62284L,
98176 62285L,62286L,62287L,62288L,62289L,62290L,62291L,62292L,62293L,62294L,
98177 62295L,62296L,62297L,62298L,62299L,62300L,62301L,62302L,62303L,62304L,
98178 62305L,62306L,62307L,62308L,62309L,62310L,62311L,62312L,62313L,62314L,
98179 62315L,62316L,62317L,62318L,62319L,62320L,62321L,62322L,62323L,62324L,
98180 62325L,62326L,62327L,62328L,62329L,62330L,62331L,62332L,62333L,62334L,
98181 62335L,62336L,62337L,62338L,62339L,62340L,62341L,62342L,62343L,62344L,
98182 62345L,62346L,62347L,62348L,62349L,62350L,62351L,62352L,62353L,62354L,
98183 62355L,62356L,62357L,62358L,62359L,62360L,62361L,62362L,62363L,62364L,
98184 62365L,62366L,62367L,62368L,62369L,62370L,62371L,62372L,62373L,62374L,
98185 62375L,62376L,62377L,62378L,62379L,62380L,62381L,62382L,62383L,62384L,
98186 62385L,62386L,62387L,62388L,62389L,62390L,62391L,62392L,62393L,62394L,
98187 62395L,62396L,62397L,62398L,62399L,62400L,62401L,62402L,62403L,62404L,
98188 62405L,62406L,62407L,62408L,62409L,62410L,62411L,62412L,62413L,62414L,
98189 62415L,62416L,62417L,62418L,62419L,62420L,62421L,62422L,62423L,62424L,
98190 62425L,62426L,62427L,62428L,62429L,62430L,62431L,62432L,62433L,62434L,
98191 62435L,62436L,62437L,62438L,62439L,62440L,62441L,62442L,62443L,62444L,
98192 62445L,62446L,62447L,62448L,62449L,62450L,62451L,62452L,62453L,62454L,
98193 62455L,62456L,62457L,62458L,62459L,62460L,62461L,62462L,62463L,62464L,
98194 62465L,62466L,62467L,62468L,62469L,62470L,62471L,62472L,62473L,62474L,
98195 62475L,62476L,62477L,62478L,62479L,62480L,62481L,62482L,62483L,62484L,
98196 62485L,62486L,62487L,62488L,62489L,62490L,62491L,62492L,62493L,62494L,
98197 62495L,62496L,62497L,62498L,62499L,62500L,62501L,62502L,62503L,62504L,
98198 62505L,62506L,62507L,62508L,62509L,62510L,62511L,62512L,62513L,62514L,
98199 62515L,62516L,62517L,62518L,62519L,62520L,62521L,62522L,62523L,62524L,
98200 62525L,62526L,62527L,62528L,62529L,62530L,62531L,62532L,62533L,62534L,
98201 62535L,62536L,62537L,62538L,62539L,62540L,62541L,62542L,62543L,62544L,
98202 62545L,62546L,62547L,62548L,62549L,62550L,62551L,62552L,62553L,62554L,
98203 62555L,62556L,62557L,62558L,62559L,62560L,62561L,62562L,62563L,62564L,
98204 62565L,62566L,62567L,62568L,62569L,62570L,62571L,62572L,62573L,62574L,
98205 62575L,62576L,62577L,62578L,62579L,62580L,62581L,62582L,62583L,62584L,
98206 62585L,62586L,62587L,62588L,62589L,62590L,62591L,62592L,62593L,62594L,
98207 62595L,62596L,62597L,62598L,62599L,62600L,62601L,62602L,62603L,62604L,
98208 62605L,62606L,62607L,62608L,62609L,62610L,62611L,62612L,62613L,62614L,
98209 62615L,62616L,62617L,62618L,62619L,62620L,62621L,62622L,62623L,62624L,
98210 62625L,62626L,62627L,62628L,62629L,62630L,62631L,62632L,62633L,62634L,
98211 62635L,62636L,62637L,62638L,62639L,62640L,62641L,62642L,62643L,62644L,
98212 62645L,62646L,62647L,62648L,62649L,62650L,62651L,62652L,62653L,62654L,
98213 62655L,62656L,62657L,62658L,62659L,62660L,62661L,62662L,62663L,62664L,
98214 62665L,62666L,62667L,62668L,62669L,62670L,62671L,62672L,62673L,62674L,
98215 62675L,62676L,62677L,62678L,62679L,62680L,62681L,62682L,62683L,62684L,
98216 62685L,62686L,62687L,62688L,62689L,62690L,62691L,62692L,62693L,62694L,
98217 62695L,62696L,62697L,62698L,62699L,62700L,62701L,62702L,62703L,62704L,
98218 62705L,62706L,62707L,62708L,62709L,62710L,62711L,62712L,62713L,62714L,
98219 62715L,62716L,62717L,62718L,62719L,62720L,62721L,62722L,62723L,62724L,
98220 62725L,62726L,62727L,62728L,62729L,62730L,62731L,62732L,62733L,62734L,
98221 62735L,62736L,62737L,62738L,62739L,62740L,62741L,62742L,62743L,62744L,
98222 62745L,62746L,62747L,62748L,62749L,62750L,62751L,62752L,62753L,62754L,
98223 62755L,62756L,62757L,62758L,62759L,62760L,62761L,62762L,62763L,62764L,
98224 62765L,62766L,62767L,62768L,62769L,62770L,62771L,62772L,62773L,62774L,
98225 62775L,62776L,62777L,62778L,62779L,62780L,62781L,62782L,62783L,62784L,
98226 62785L,62786L,62787L,62788L,62789L,62790L,62791L,62792L,62793L,62794L,
98227 62795L,62796L,62797L,62798L,62799L,62800L,62801L,62802L,62803L,62804L,
98228 62805L,62806L,62807L,62808L,62809L,62810L,62811L,62812L,62813L,62814L,
98229 62815L,62816L,62817L,62818L,62819L,62820L,62821L,62822L,62823L,62824L,
98230 62825L,62826L,62827L,62828L,62829L,62830L,62831L,62832L,62833L,62834L,
98231 62835L,62836L,62837L,62838L,62839L,62840L,62841L,62842L,62843L,62844L,
98232 62845L,62846L,62847L,62848L,62849L,62850L,62851L,62852L,62853L,62854L,
98233 62855L,62856L,62857L,62858L,62859L,62860L,62861L,62862L,62863L,62864L,
98234 62865L,62866L,62867L,62868L,62869L,62870L,62871L,62872L,62873L,62874L,
98235 62875L,62876L,62877L,62878L,62879L,62880L,62881L,62882L,62883L,62884L,
98236 62885L,62886L,62887L,62888L,62889L,62890L,62891L,62892L,62893L,62894L,
98237 62895L,62896L,62897L,62898L,62899L,62900L,62901L,62902L,62903L,62904L,
98238 62905L,62906L,62907L,62908L,62909L,62910L,62911L,62912L,62913L,62914L,
98239 62915L,62916L,62917L,62918L,62919L,62920L,62921L,62922L,62923L,62924L,
98240 62925L,62926L,62927L,62928L,62929L,62930L,62931L,62932L,62933L,62934L,
98241 62935L,62936L,62937L,62938L,62939L,62940L,62941L,62942L,62943L,62944L,
98242 62945L,62946L,62947L,62948L,62949L,62950L,62951L,62952L,62953L,62954L,
98243 62955L,62956L,62957L,62958L,62959L,62960L,62961L,62962L,62963L,62964L,
98244 62965L,62966L,62967L,62968L,62969L,62970L,62971L,62972L,62973L,62974L,
98245 62975L,62976L,62977L,62978L,62979L,62980L,62981L,62982L,62983L,62984L,
98246 62985L,62986L,62987L,62988L,62989L,62990L,62991L,62992L,62993L,62994L,
98247 62995L,62996L,62997L,62998L,62999L,63000L,63001L,63002L,63003L,63004L,
98248 63005L,63006L,63007L,63008L,63009L,63010L,63011L,63012L,63013L,63014L,
98249 63015L,63016L,63017L,63018L,63019L,63020L,63021L,63022L,63023L,63024L,
98250 63025L,63026L,63027L,63028L,63029L,63030L,63031L,63032L,63033L,63034L,
98251 63035L,63036L,63037L,63038L,63039L,63040L,63041L,63042L,63043L,63044L,
98252 63045L,63046L,63047L,63048L,63049L,63050L,63051L,63052L,63053L,63054L,
98253 63055L,63056L,63057L,63058L,63059L,63060L,63061L,63062L,63063L,63064L,
98254 63065L,63066L,63067L,63068L,63069L,63070L,63071L,63072L,63073L,63074L,
98255 63075L,63076L,63077L,63078L,63079L,63080L,63081L,63082L,63083L,63084L,
98256 63085L,63086L,63087L,63088L,63089L,63090L,63091L,63092L,63093L,63094L,
98257 63095L,63096L,63097L,63098L,63099L,63100L,63101L,63102L,63103L,63104L,
98258 63105L,63106L,63107L,63108L,63109L,63110L,63111L,63112L,63113L,63114L,
98259 63115L,63116L,63117L,63118L,63119L,63120L,63121L,63122L,63123L,63124L,
98260 63125L,63126L,63127L,63128L,63129L,63130L,63131L,63132L,63133L,63134L,
98261 63135L,63136L,63137L,63138L,63139L,63140L,63141L,63142L,63143L,63144L,
98262 63145L,63146L,63147L,63148L,63149L,63150L,63151L,63152L,63153L,63154L,
98263 63155L,63156L,63157L,63158L,63159L,63160L,63161L,63162L,63163L,63164L,
98264 63165L,63166L,63167L,63168L,63169L,63170L,63171L,63172L,63173L,63174L,
98265 63175L,63176L,63177L,63178L,63179L,63180L,63181L,63182L,63183L,63184L,
98266 63185L,63186L,63187L,63188L,63189L,63190L,63191L,63192L,63193L,63194L,
98267 63195L,63196L,63197L,63198L,63199L,63200L,63201L,63202L,63203L,63204L,
98268 63205L,63206L,63207L,63208L,63209L,63210L,63211L,63212L,63213L,63214L,
98269 63215L,63216L,63217L,63218L,63219L,63220L,63221L,63222L,63223L,63224L,
98270 63225L,63226L,63227L,63228L,63229L,63230L,63231L,63232L,63233L,63234L,
98271 63235L,63236L,63237L,63238L,63239L,63240L,63241L,63242L,63243L,63244L,
98272 63245L,63246L,63247L,63248L,63249L,63250L,63251L,63252L,63253L,63254L,
98273 63255L,63256L,63257L,63258L,63259L,63260L,63261L,63262L,63263L,63264L,
98274 63265L,63266L,63267L,63268L,63269L,63270L,63271L,63272L,63273L,63274L,
98275 63275L,63276L,63277L,63278L,63279L,63280L,63281L,63282L,63283L,63284L,
98276 63285L,63286L,63287L,63288L,63289L,63290L,63291L,63292L,63293L,63294L,
98277 63295L,63296L,63297L,63298L,63299L,63300L,63301L,63302L,63303L,63304L,
98278 63305L,63306L,63307L,63308L,63309L,63310L,63311L,63312L,63313L,63314L,
98279 63315L,63316L,63317L,63318L,63319L,63320L,63321L,63322L,63323L,63324L,
98280 63325L,63326L,63327L,63328L,63329L,63330L,63331L,63332L,63333L,63334L,
98281 63335L,63336L,63337L,63338L,63339L,63340L,63341L,63342L,63343L,63344L,
98282 63345L,63346L,63347L,63348L,63349L,63350L,63351L,63352L,63353L,63354L,
98283 63355L,63356L,63357L,63358L,63359L,63360L,63361L,63362L,63363L,63364L,
98284 63365L,63366L,63367L,63368L,63369L,63370L,63371L,63372L,63373L,63374L,
98285 63375L,63376L,63377L,63378L,63379L,63380L,63381L,63382L,63383L,63384L,
98286 63385L,63386L,63387L,63388L,63389L,63390L,63391L,63392L,63393L,63394L,
98287 63395L,63396L,63397L,63398L,63399L,63400L,63401L,63402L,63403L,63404L,
98288 63405L,63406L,63407L,63408L,63409L,63410L,63411L,63412L,63413L,63414L,
98289 63415L,63416L,63417L,63418L,63419L,63420L,63421L,63422L,63423L,63424L,
98290 63425L,63426L,63427L,63428L,63429L,63430L,63431L,63432L,63433L,63434L,
98291 63435L,63436L,63437L,63438L,63439L,63440L,63441L,63442L,63443L,63444L,
98292 63445L,63446L,63447L,63448L,63449L,63450L,63451L,63452L,63453L,63454L,
98293 63455L,63456L,63457L,63458L,63459L,63460L,63461L,63462L,63463L,63464L,
98294 63465L,63466L,63467L,63468L,63469L,63470L,63471L,63472L,63473L,63474L,
98295 63475L,63476L,63477L,63478L,63479L,63480L,63481L,63482L,63483L,63484L,
98296 63485L,63486L,63487L,63488L,63489L,63490L,63491L,63492L,63493L,63494L,
98297 63495L,63496L,63497L,63498L,63499L,63500L,63501L,63502L,63503L,63504L,
98298 63505L,63506L,63507L,63508L,63509L,63510L,63511L,63512L,63513L,63514L,
98299 63515L,63516L,63517L,63518L,63519L,63520L,63521L,63522L,63523L,63524L,
98300 63525L,63526L,63527L,63528L,63529L,63530L,63531L,63532L,63533L,63534L,
98301 63535L,63536L,63537L,63538L,63539L,63540L,63541L,63542L,63543L,63544L,
98302 63545L,63546L,63547L,63548L,63549L,63550L,63551L,63552L,63553L,63554L,
98303 63555L,63556L,63557L,63558L,63559L,63560L,63561L,63562L,63563L,63564L,
98304 63565L,63566L,63567L,63568L,63569L,63570L,63571L,63572L,63573L,63574L,
98305 63575L,63576L,63577L,63578L,63579L,63580L,63581L,63582L,63583L,63584L,
98306 63585L,63586L,63587L,63588L,63589L,63590L,63591L,63592L,63593L,63594L,
98307 63595L,63596L,63597L,63598L,63599L,63600L,63601L,63602L,63603L,63604L,
98308 63605L,63606L,63607L,63608L,63609L,63610L,63611L,63612L,63613L,63614L,
98309 63615L,63616L,63617L,63618L,63619L,63620L,63621L,63622L,63623L,63624L,
98310 63625L,63626L,63627L,63628L,63629L,63630L,63631L,63632L,63633L,63634L,
98311 63635L,63636L,63637L,63638L,63639L,63640L,63641L,63642L,63643L,63644L,
98312 63645L,63646L,63647L,63648L,63649L,63650L,63651L,63652L,63653L,63654L,
98313 63655L,63656L,63657L,63658L,63659L,63660L,63661L,63662L,63663L,63664L,
98314 63665L,63666L,63667L,63668L,63669L,63670L,63671L,63672L,63673L,63674L,
98315 63675L,63676L,63677L,63678L,63679L,63680L,63681L,63682L,63683L,63684L,
98316 63685L,63686L,63687L,63688L,63689L,63690L,63691L,63692L,63693L,63694L,
98317 63695L,63696L,63697L,63698L,63699L,63700L,63701L,63702L,63703L,63704L,
98318 63705L,63706L,63707L,63708L,63709L,63710L,63711L,63712L,63713L,63714L,
98319 63715L,63716L,63717L,63718L,63719L,63720L,63721L,63722L,63723L,63724L,
98320 63725L,63726L,63727L,63728L,63729L,63730L,63731L,63732L,63733L,63734L,
98321 63735L,63736L,63737L,63738L,63739L,63740L,63741L,63742L,63743L,63744L,
98322 63745L,63746L,63747L,63748L,63749L,63750L,63751L,63752L,63753L,63754L,
98323 63755L,63756L,63757L,63758L,63759L,63760L,63761L,63762L,63763L,63764L,
98324 63765L,63766L,63767L,63768L,63769L,63770L,63771L,63772L,63773L,63774L,
98325 63775L,63776L,63777L,63778L,63779L,63780L,63781L,63782L,63783L,63784L,
98326 63785L,63786L,63787L,63788L,63789L,63790L,63791L,63792L,63793L,63794L,
98327 63795L,63796L,63797L,63798L,63799L,63800L,63801L,63802L,63803L,63804L,
98328 63805L,63806L,63807L,63808L,63809L,63810L,63811L,63812L,63813L,63814L,
98329 63815L,63816L,63817L,63818L,63819L,63820L,63821L,63822L,63823L,63824L,
98330 63825L,63826L,63827L,63828L,63829L,63830L,63831L,63832L,63833L,63834L,
98331 63835L,63836L,63837L,63838L,63839L,63840L,63841L,63842L,63843L,63844L,
98332 63845L,63846L,63847L,63848L,63849L,63850L,63851L,63852L,63853L,63854L,
98333 63855L,63856L,63857L,63858L,63859L,63860L,63861L,63862L,63863L,63864L,
98334 63865L,63866L,63867L,63868L,63869L,63870L,63871L,63872L,63873L,63874L,
98335 63875L,63876L,63877L,63878L,63879L,63880L,63881L,63882L,63883L,63884L,
98336 63885L,63886L,63887L,63888L,63889L,63890L,63891L,63892L,63893L,63894L,
98337 63895L,63896L,63897L,63898L,63899L,63900L,63901L,63902L,63903L,63904L,
98338 63905L,63906L,63907L,63908L,63909L,63910L,63911L,63912L,63913L,63914L,
98339 63915L,63916L,63917L,63918L,63919L,63920L,63921L,63922L,63923L,63924L,
98340 63925L,63926L,63927L,63928L,63929L,63930L,63931L,63932L,63933L,63934L,
98341 63935L,63936L,63937L,63938L,63939L,63940L,63941L,63942L,63943L,63944L,
98342 63945L,63946L,63947L,63948L,63949L,63950L,63951L,63952L,63953L,63954L,
98343 63955L,63956L,63957L,63958L,63959L,63960L,63961L,63962L,63963L,63964L,
98344 63965L,63966L,63967L,63968L,63969L,63970L,63971L,63972L,63973L,63974L,
98345 63975L,63976L,63977L,63978L,63979L,63980L,63981L,63982L,63983L,63984L,
98346 63985L,63986L,63987L,63988L,63989L,63990L,63991L,63992L,63993L,63994L,
98347 63995L,63996L,63997L,63998L,63999L,64000L,64001L,64002L,64003L,64004L,
98348 64005L,64006L,64007L,64008L,64009L,64010L,64011L,64012L,64013L,64014L,
98349 64015L,64016L,64017L,64018L,64019L,64020L,64021L,64022L,64023L,64024L,
98350 64025L,64026L,64027L,64028L,64029L,64030L,64031L,64032L,64033L,64034L,
98351 64035L,64036L,64037L,64038L,64039L,64040L,64041L,64042L,64043L,64044L,
98352 64045L,64046L,64047L,64048L,64049L,64050L,64051L,64052L,64053L,64054L,
98353 64055L,64056L,64057L,64058L,64059L,64060L,64061L,64062L,64063L,64064L,
98354 64065L,64066L,64067L,64068L,64069L,64070L,64071L,64072L,64073L,64074L,
98355 64075L,64076L,64077L,64078L,64079L,64080L,64081L,64082L,64083L,64084L,
98356 64085L,64086L,64087L,64088L,64089L,64090L,64091L,64092L,64093L,64094L,
98357 64095L,64096L,64097L,64098L,64099L,64100L,64101L,64102L,64103L,64104L,
98358 64105L,64106L,64107L,64108L,64109L,64110L,64111L,64112L,64113L,64114L,
98359 64115L,64116L,64117L,64118L,64119L,64120L,64121L,64122L,64123L,64124L,
98360 64125L,64126L,64127L,64128L,64129L,64130L,64131L,64132L,64133L,64134L,
98361 64135L,64136L,64137L,64138L,64139L,64140L,64141L,64142L,64143L,64144L,
98362 64145L,64146L,64147L,64148L,64149L,64150L,64151L,64152L,64153L,64154L,
98363 64155L,64156L,64157L,64158L,64159L,64160L,64161L,64162L,64163L,64164L,
98364 64165L,64166L,64167L,64168L,64169L,64170L,64171L,64172L,64173L,64174L,
98365 64175L,64176L,64177L,64178L,64179L,64180L,64181L,64182L,64183L,64184L,
98366 64185L,64186L,64187L,64188L,64189L,64190L,64191L,64192L,64193L,64194L,
98367 64195L,64196L,64197L,64198L,64199L,64200L,64201L,64202L,64203L,64204L,
98368 64205L,64206L,64207L,64208L,64209L,64210L,64211L,64212L,64213L,64214L,
98369 64215L,64216L,64217L,64218L,64219L,64220L,64221L,64222L,64223L,64224L,
98370 64225L,64226L,64227L,64228L,64229L,64230L,64231L,64232L,64233L,64234L,
98371 64235L,64236L,64237L,64238L,64239L,64240L,64241L,64242L,64243L,64244L,
98372 64245L,64246L,64247L,64248L,64249L,64250L,64251L,64252L,64253L,64254L,
98373 64255L,64256L,64257L,64258L,64259L,64260L,64261L,64262L,64263L,64264L,
98374 64265L,64266L,64267L,64268L,64269L,64270L,64271L,64272L,64273L,64274L,
98375 64275L,64276L,64277L,64278L,64279L,64280L,64281L,64282L,64283L,64284L,
98376 64285L,64286L,64287L,64288L,64289L,64290L,64291L,64292L,64293L,64294L,
98377 64295L,64296L,64297L,64298L,64299L,64300L,64301L,64302L,64303L,64304L,
98378 64305L,64306L,64307L,64308L,64309L,64310L,64311L,64312L,64313L,64314L,
98379 64315L,64316L,64317L,64318L,64319L,64320L,64321L,64322L,64323L,64324L,
98380 64325L,64326L,64327L,64328L,64329L,64330L,64331L,64332L,64333L,64334L,
98381 64335L,64336L,64337L,64338L,64339L,64340L,64341L,64342L,64343L,64344L,
98382 64345L,64346L,64347L,64348L,64349L,64350L,64351L,64352L,64353L,64354L,
98383 64355L,64356L,64357L,64358L,64359L,64360L,64361L,64362L,64363L,64364L,
98384 64365L,64366L,64367L,64368L,64369L,64370L,64371L,64372L,64373L,64374L,
98385 64375L,64376L,64377L,64378L,64379L,64380L,64381L,64382L,64383L,64384L,
98386 64385L,64386L,64387L,64388L,64389L,64390L,64391L,64392L,64393L,64394L,
98387 64395L,64396L,64397L,64398L,64399L,64400L,64401L,64402L,64403L,64404L,
98388 64405L,64406L,64407L,64408L,64409L,64410L,64411L,64412L,64413L,64414L,
98389 64415L,64416L,64417L,64418L,64419L,64420L,64421L,64422L,64423L,64424L,
98390 64425L,64426L,64427L,64428L,64429L,64430L,64431L,64432L,64433L,64434L,
98391 64435L,64436L,64437L,64438L,64439L,64440L,64441L,64442L,64443L,64444L,
98392 64445L,64446L,64447L,64448L,64449L,64450L,64451L,64452L,64453L,64454L,
98393 64455L,64456L,64457L,64458L,64459L,64460L,64461L,64462L,64463L,64464L,
98394 64465L,64466L,64467L,64468L,64469L,64470L,64471L,64472L,64473L,64474L,
98395 64475L,64476L,64477L,64478L,64479L,64480L,64481L,64482L,64483L,64484L,
98396 64485L,64486L,64487L,64488L,64489L,64490L,64491L,64492L,64493L,64494L,
98397 64495L,64496L,64497L,64498L,64499L,64500L,64501L,64502L,64503L,64504L,
98398 64505L,64506L,64507L,64508L,64509L,64510L,64511L,64512L,64513L,64514L,
98399 64515L,64516L,64517L,64518L,64519L,64520L,64521L,64522L,64523L,64524L,
98400 64525L,64526L,64527L,64528L,64529L,64530L,64531L,64532L,64533L,64534L,
98401 64535L,64536L,64537L,64538L,64539L,64540L,64541L,64542L,64543L,64544L,
98402 64545L,64546L,64547L,64548L,64549L,64550L,64551L,64552L,64553L,64554L,
98403 64555L,64556L,64557L,64558L,64559L,64560L,64561L,64562L,64563L,64564L,
98404 64565L,64566L,64567L,64568L,64569L,64570L,64571L,64572L,64573L,64574L,
98405 64575L,64576L,64577L,64578L,64579L,64580L,64581L,64582L,64583L,64584L,
98406 64585L,64586L,64587L,64588L,64589L,64590L,64591L,64592L,64593L,64594L,
98407 64595L,64596L,64597L,64598L,64599L,64600L,64601L,64602L,64603L,64604L,
98408 64605L,64606L,64607L,64608L,64609L,64610L,64611L,64612L,64613L,64614L,
98409 64615L,64616L,64617L,64618L,64619L,64620L,64621L,64622L,64623L,64624L,
98410 64625L,64626L,64627L,64628L,64629L,64630L,64631L,64632L,64633L,64634L,
98411 64635L,64636L,64637L,64638L,64639L,64640L,64641L,64642L,64643L,64644L,
98412 64645L,64646L,64647L,64648L,64649L,64650L,64651L,64652L,64653L,64654L,
98413 64655L,64656L,64657L,64658L,64659L,64660L,64661L,64662L,64663L,64664L,
98414 64665L,64666L,64667L,64668L,64669L,64670L,64671L,64672L,64673L,64674L,
98415 64675L,64676L,64677L,64678L,64679L,64680L,64681L,64682L,64683L,64684L,
98416 64685L,64686L,64687L,64688L,64689L,64690L,64691L,64692L,64693L,64694L,
98417 64695L,64696L,64697L,64698L,64699L,64700L,64701L,64702L,64703L,64704L,
98418 64705L,64706L,64707L,64708L,64709L,64710L,64711L,64712L,64713L,64714L,
98419 64715L,64716L,64717L,64718L,64719L,64720L,64721L,64722L,64723L,64724L,
98420 64725L,64726L,64727L,64728L,64729L,64730L,64731L,64732L,64733L,64734L,
98421 64735L,64736L,64737L,64738L,64739L,64740L,64741L,64742L,64743L,64744L,
98422 64745L,64746L,64747L,64748L,64749L,64750L,64751L,64752L,64753L,64754L,
98423 64755L,64756L,64757L,64758L,64759L,64760L,64761L,64762L,64763L,64764L,
98424 64765L,64766L,64767L,64768L,64769L,64770L,64771L,64772L,64773L,64774L,
98425 64775L,64776L,64777L,64778L,64779L,64780L,64781L,64782L,64783L,64784L,
98426 64785L,64786L,64787L,64788L,64789L,64790L,64791L,64792L,64793L,64794L,
98427 64795L,64796L,64797L,64798L,64799L,64800L,64801L,64802L,64803L,64804L,
98428 64805L,64806L,64807L,64808L,64809L,64810L,64811L,64812L,64813L,64814L,
98429 64815L,64816L,64817L,64818L,64819L,64820L,64821L,64822L,64823L,64824L,
98430 64825L,64826L,64827L,64828L,64829L,64830L,64831L,64832L,64833L,64834L,
98431 64835L,64836L,64837L,64838L,64839L,64840L,64841L,64842L,64843L,64844L,
98432 64845L,64846L,64847L,64848L,64849L,64850L,64851L,64852L,64853L,64854L,
98433 64855L,64856L,64857L,64858L,64859L,64860L,64861L,64862L,64863L,64864L,
98434 64865L,64866L,64867L,64868L,64869L,64870L,64871L,64872L,64873L,64874L,
98435 64875L,64876L,64877L,64878L,64879L,64880L,64881L,64882L,64883L,64884L,
98436 64885L,64886L,64887L,64888L,64889L,64890L,64891L,64892L,64893L,64894L,
98437 64895L,64896L,64897L,64898L,64899L,64900L,64901L,64902L,64903L,64904L,
98438 64905L,64906L,64907L,64908L,64909L,64910L,64911L,64912L,64913L,64914L,
98439 64915L,64916L,64917L,64918L,64919L,64920L,64921L,64922L,64923L,64924L,
98440 64925L,64926L,64927L,64928L,64929L,64930L,64931L,64932L,64933L,64934L,
98441 64935L,64936L,64937L,64938L,64939L,64940L,64941L,64942L,64943L,64944L,
98442 64945L,64946L,64947L,64948L,64949L,64950L,64951L,64952L,64953L,64954L,
98443 64955L,64956L,64957L,64958L,64959L,64960L,64961L,64962L,64963L,64964L,
98444 64965L,64966L,64967L,64968L,64969L,64970L,64971L,64972L,64973L,64974L,
98445 64975L,64976L,64977L,64978L,64979L,64980L,64981L,64982L,64983L,64984L,
98446 64985L,64986L,64987L,64988L,64989L,64990L,64991L,64992L,64993L,64994L,
98447 64995L,64996L,64997L,64998L,64999L,65000L,65001L,65002L,65003L,65004L,
98448 65005L,65006L,65007L,65008L,65009L,65010L,65011L,65012L,65013L,65014L,
98449 65015L,65016L,65017L,65018L,65019L,65020L,65021L,65022L,65023L,65024L,
98450 65025L,65026L,65027L,65028L,65029L,65030L,65031L,65032L,65033L,65034L,
98451 65035L,65036L,65037L,65038L,65039L,65040L,65041L,65042L,65043L,65044L,
98452 65045L,65046L,65047L,65048L,65049L,65050L,65051L,65052L,65053L,65054L,
98453 65055L,65056L,65057L,65058L,65059L,65060L,65061L,65062L,65063L,65064L,
98454 65065L,65066L,65067L,65068L,65069L,65070L,65071L,65072L,65073L,65074L,
98455 65075L,65076L,65077L,65078L,65079L,65080L,65081L,65082L,65083L,65084L,
98456 65085L,65086L,65087L,65088L,65089L,65090L,65091L,65092L,65093L,65094L,
98457 65095L,65096L,65097L,65098L,65099L,65100L,65101L,65102L,65103L,65104L,
98458 65105L,65106L,65107L,65108L,65109L,65110L,65111L,65112L,65113L,65114L,
98459 65115L,65116L,65117L,65118L,65119L,65120L,65121L,65122L,65123L,65124L,
98460 65125L,65126L,65127L,65128L,65129L,65130L,65131L,65132L,65133L,65134L,
98461 65135L,65136L,65137L,65138L,65139L,65140L,65141L,65142L,65143L,65144L,
98462 65145L,65146L,65147L,65148L,65149L,65150L,65151L,65152L,65153L,65154L,
98463 65155L,65156L,65157L,65158L,65159L,65160L,65161L,65162L,65163L,65164L,
98464 65165L,65166L,65167L,65168L,65169L,65170L,65171L,65172L,65173L,65174L,
98465 65175L,65176L,65177L,65178L,65179L,65180L,65181L,65182L,65183L,65184L,
98466 65185L,65186L,65187L,65188L,65189L,65190L,65191L,65192L,65193L,65194L,
98467 65195L,65196L,65197L,65198L,65199L,65200L,65201L,65202L,65203L,65204L,
98468 65205L,65206L,65207L,65208L,65209L,65210L,65211L,65212L,65213L,65214L,
98469 65215L,65216L,65217L,65218L,65219L,65220L,65221L,65222L,65223L,65224L,
98470 65225L,65226L,65227L,65228L,65229L,65230L,65231L,65232L,65233L,65234L,
98471 65235L,65236L,65237L,65238L,65239L,65240L,65241L,65242L,65243L,65244L,
98472 65245L,65246L,65247L,65248L,65249L,65250L,65251L,65252L,65253L,65254L,
98473 65255L,65256L,65257L,65258L,65259L,65260L,65261L,65262L,65263L,65264L,
98474 65265L,65266L,65267L,65268L,65269L,65270L,65271L,65272L,65273L,65274L,
98475 65275L,65276L,65277L,65278L,65279L,65280L,65281L,65282L,65283L,65284L,
98476 65285L,65286L,65287L,65288L,65289L,65290L,65291L,65292L,65293L,65294L,
98477 65295L,65296L,65297L,65298L,65299L,65300L,65301L,65302L,65303L,65304L,
98478 65305L,65306L,65307L,65308L,65309L,65310L,65311L,65312L,65313L,65314L,
98479 65315L,65316L,65317L,65318L,65319L,65320L,65321L,65322L,65323L,65324L,
98480 65325L,65326L,65327L,65328L,65329L,65330L,65331L,65332L,65333L,65334L,
98481 65335L,65336L,65337L,65338L,65339L,65340L,65341L,65342L,65343L,65344L,
98482 65313L,65314L,65315L,65316L,65317L,65318L,65319L,65320L,65321L,65322L,
98483 65323L,65324L,65325L,65326L,65327L,65328L,65329L,65330L,65331L,65332L,
98484 65333L,65334L,65335L,65336L,65337L,65338L,65371L,65372L,65373L,65374L,
98485 65375L,65376L,65377L,65378L,65379L,65380L,65381L,65382L,65383L,65384L,
98486 65385L,65386L,65387L,65388L,65389L,65390L,65391L,65392L,65393L,65394L,
98487 65395L,65396L,65397L,65398L,65399L,65400L,65401L,65402L,65403L,65404L,
98488 65405L,65406L,65407L,65408L,65409L,65410L,65411L,65412L,65413L,65414L,
98489 65415L,65416L,65417L,65418L,65419L,65420L,65421L,65422L,65423L,65424L,
98490 65425L,65426L,65427L,65428L,65429L,65430L,65431L,65432L,65433L,65434L,
98491 65435L,65436L,65437L,65438L,65439L,65440L,65441L,65442L,65443L,65444L,
98492 65445L,65446L,65447L,65448L,65449L,65450L,65451L,65452L,65453L,65454L,
98493 65455L,65456L,65457L,65458L,65459L,65460L,65461L,65462L,65463L,65464L,
98494 65465L,65466L,65467L,65468L,65469L,65470L,65471L,65472L,65473L,65474L,
98495 65475L,65476L,65477L,65478L,65479L,65480L,65481L,65482L,65483L,65484L,
98496 65485L,65486L,65487L,65488L,65489L,65490L,65491L,65492L,65493L,65494L,
98497 65495L,65496L,65497L,65498L,65499L,65500L,65501L,65502L,65503L,65504L,
98498 65505L,65506L,65507L,65508L,65509L,65510L,65511L,65512L,65513L,65514L,
98499 65515L,65516L,65517L,65518L,65519L,65520L,65521L,65522L,65523L,65524L,
98500 65525L,65526L,65527L,65528L,65529L,65530L,65531L,65532L,65533L,65534L,
98501 65535L,
98502 };
98503 #endif
98504 
98505 #if defined(DUK_USE_REGEXP_CANON_BITMAP)
98506 /*
98507  *  Automatically generated by extract_caseconv.py, do not edit!
98508  */
98509 
98510 const duk_uint8_t duk_unicode_re_canon_bitmap[256] = {
98511 23,0,224,19,1,228,255,255,255,255,255,255,255,255,255,255,63,254,255,127,
98512 255,255,255,255,255,255,255,255,231,231,0,16,255,227,255,255,63,255,255,
98513 255,255,255,255,255,1,252,255,255,255,255,255,255,255,255,255,255,255,255,
98514 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
98515 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
98516 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
98517 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
98518 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
98519 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
98520 227,129,255,255,255,147,255,255,255,255,255,255,255,255,255,255,255,255,
98521 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
98522 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
98523 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
98524 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,251,
98525 };
98526 #endif
98527 /*
98528  *  Bitstream decoder.
98529  */
98530 
98531 /* #include duk_internal.h -> already included */
98532 
98533 /* Decode 'bits' bits from the input stream (bits must be 1...24).
98534  * When reading past bitstream end, zeroes are shifted in.  The result
98535  * is signed to match duk_bd_decode_flagged.
98536  */
98537 DUK_INTERNAL duk_uint32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits) {
98538 	duk_small_int_t shift;
98539 	duk_uint32_t mask;
98540 	duk_uint32_t tmp;
98541 
98542 	/* Note: cannot read more than 24 bits without possibly shifting top bits out.
98543 	 * Fixable, but adds complexity.
98544 	 */
98545 	DUK_ASSERT(bits >= 1 && bits <= 24);
98546 
98547 	while (ctx->currbits < bits) {
98548 #if 0
98549 		DUK_DDD(DUK_DDDPRINT("decode_bits: shift more data (bits=%ld, currbits=%ld)",
98550 		                     (long) bits, (long) ctx->currbits));
98551 #endif
98552 		ctx->currval <<= 8;
98553 		if (ctx->offset < ctx->length) {
98554 			/* If ctx->offset >= ctx->length, we "shift zeroes in"
98555 			 * instead of croaking.
98556 			 */
98557 			ctx->currval |= ctx->data[ctx->offset++];
98558 		}
98559 		ctx->currbits += 8;
98560 	}
98561 #if 0
98562 	DUK_DDD(DUK_DDDPRINT("decode_bits: bits=%ld, currbits=%ld, currval=0x%08lx",
98563 	                     (long) bits, (long) ctx->currbits, (unsigned long) ctx->currval));
98564 #endif
98565 
98566 	/* Extract 'top' bits of currval; note that the extracted bits do not need
98567 	 * to be cleared, we just ignore them on next round.
98568 	 */
98569 	shift = ctx->currbits - bits;
98570 	mask = (((duk_uint32_t) 1U) << bits) - 1U;
98571 	tmp = (ctx->currval >> shift) & mask;
98572 	ctx->currbits = shift;  /* remaining */
98573 
98574 #if 0
98575 	DUK_DDD(DUK_DDDPRINT("decode_bits: %ld bits -> 0x%08lx (%ld), currbits=%ld, currval=0x%08lx",
98576 	                     (long) bits, (unsigned long) tmp, (long) tmp, (long) ctx->currbits, (unsigned long) ctx->currval));
98577 #endif
98578 
98579 	return tmp;
98580 }
98581 
98582 DUK_INTERNAL duk_small_uint_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx) {
98583 	return (duk_small_uint_t) duk_bd_decode(ctx, 1);
98584 }
98585 
98586 /* Decode a one-bit flag, and if set, decode a value of 'bits', otherwise return
98587  * default value.
98588  */
98589 DUK_INTERNAL duk_uint32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_uint32_t def_value) {
98590 	if (duk_bd_decode_flag(ctx)) {
98591 		return duk_bd_decode(ctx, bits);
98592 	} else {
98593 		return def_value;
98594 	}
98595 }
98596 
98597 /* Signed variant, allows negative marker value. */
98598 DUK_INTERNAL duk_int32_t duk_bd_decode_flagged_signed(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value) {
98599 	return (duk_int32_t) duk_bd_decode_flagged(ctx, bits, (duk_uint32_t) def_value);
98600 }
98601 
98602 /* Shared varint encoding.  Match dukutil.py BitEncode.varuint(). */
98603 DUK_INTERNAL duk_uint32_t duk_bd_decode_varuint(duk_bitdecoder_ctx *ctx) {
98604 	duk_small_uint_t t;
98605 
98606 	/* The bit encoding choices here are based on manual testing against
98607 	 * the actual varuints generated by genbuiltins.py.
98608 	 */
98609 	switch (duk_bd_decode(ctx, 2)) {
98610 	case 0:
98611 		return 0;  /* [0,0] */
98612 	case 1:
98613 		return duk_bd_decode(ctx, 2) + 1;  /* [1,4] */
98614 	case 2:
98615 		return duk_bd_decode(ctx, 5) + 5;  /* [5,36] */
98616 	default:
98617 		t = duk_bd_decode(ctx, 7);
98618 		if (t == 0) {
98619 			return duk_bd_decode(ctx, 20);
98620 		}
98621 		return (t - 1) + 37;  /* [37,163] */
98622 	}
98623 }
98624 
98625 /* Decode a bit packed string from a custom format used by genbuiltins.py.
98626  * This function is here because it's used for both heap and thread inits.
98627  * Caller must supply the output buffer whose size is NOT checked!
98628  */
98629 
98630 #define DUK__BITPACK_LETTER_LIMIT  26
98631 #define DUK__BITPACK_LOOKUP1       26
98632 #define DUK__BITPACK_LOOKUP2       27
98633 #define DUK__BITPACK_SWITCH1       28
98634 #define DUK__BITPACK_SWITCH        29
98635 #define DUK__BITPACK_UNUSED1       30
98636 #define DUK__BITPACK_EIGHTBIT      31
98637 
98638 DUK_LOCAL const duk_uint8_t duk__bitpacked_lookup[16] = {
98639 	DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
98640 	DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
98641 	DUK_ASC_8, DUK_ASC_9, DUK_ASC_UNDERSCORE, DUK_ASC_SPACE,
98642 	0x82, 0x80, DUK_ASC_DOUBLEQUOTE, DUK_ASC_LCURLY
98643 };
98644 
98645 DUK_INTERNAL duk_small_uint_t duk_bd_decode_bitpacked_string(duk_bitdecoder_ctx *bd, duk_uint8_t *out) {
98646 	duk_small_uint_t len;
98647 	duk_small_uint_t mode;
98648 	duk_small_uint_t t;
98649 	duk_small_uint_t i;
98650 
98651 	len = duk_bd_decode(bd, 5);
98652 	if (len == 31) {
98653 		len = duk_bd_decode(bd, 8);  /* Support up to 256 bytes; rare. */
98654 	}
98655 
98656 	mode = 32;  /* 0 = uppercase, 32 = lowercase (= 'a' - 'A') */
98657 	for (i = 0; i < len; i++) {
98658 		t = duk_bd_decode(bd, 5);
98659 		if (t < DUK__BITPACK_LETTER_LIMIT) {
98660 			t = t + DUK_ASC_UC_A + mode;
98661 		} else if (t == DUK__BITPACK_LOOKUP1) {
98662 			t = duk__bitpacked_lookup[duk_bd_decode(bd, 3)];
98663 		} else if (t == DUK__BITPACK_LOOKUP2) {
98664 			t = duk__bitpacked_lookup[8 + duk_bd_decode(bd, 3)];
98665 		} else if (t == DUK__BITPACK_SWITCH1) {
98666 			t = duk_bd_decode(bd, 5);
98667 			DUK_ASSERT_DISABLE(t >= 0);  /* unsigned */
98668 			DUK_ASSERT(t <= 25);
98669 			t = t + DUK_ASC_UC_A + (mode ^ 32);
98670 		} else if (t == DUK__BITPACK_SWITCH) {
98671 			mode = mode ^ 32;
98672 			t = duk_bd_decode(bd, 5);
98673 			DUK_ASSERT_DISABLE(t >= 0);
98674 			DUK_ASSERT(t <= 25);
98675 			t = t + DUK_ASC_UC_A + mode;
98676 		} else if (t == DUK__BITPACK_EIGHTBIT) {
98677 			t = duk_bd_decode(bd, 8);
98678 		}
98679 		out[i] = (duk_uint8_t) t;
98680 	}
98681 
98682 	return len;
98683 }
98684 
98685 /* automatic undefs */
98686 #undef DUK__BITPACK_EIGHTBIT
98687 #undef DUK__BITPACK_LETTER_LIMIT
98688 #undef DUK__BITPACK_LOOKUP1
98689 #undef DUK__BITPACK_LOOKUP2
98690 #undef DUK__BITPACK_SWITCH
98691 #undef DUK__BITPACK_SWITCH1
98692 #undef DUK__BITPACK_UNUSED1
98693 /*
98694  *  Bitstream encoder.
98695  */
98696 
98697 /* #include duk_internal.h -> already included */
98698 
98699 DUK_INTERNAL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits) {
98700 	duk_uint8_t tmp;
98701 
98702 	DUK_ASSERT(ctx != NULL);
98703 	DUK_ASSERT(ctx->currbits < 8);
98704 
98705 	/* This limitation would be fixable but adds unnecessary complexity. */
98706 	DUK_ASSERT(bits >= 1 && bits <= 24);
98707 
98708 	ctx->currval = (ctx->currval << bits) | data;
98709 	ctx->currbits += bits;
98710 
98711 	while (ctx->currbits >= 8) {
98712 		if (ctx->offset < ctx->length) {
98713 			tmp = (duk_uint8_t) ((ctx->currval >> (ctx->currbits - 8)) & 0xff);
98714 			ctx->data[ctx->offset++] = tmp;
98715 		} else {
98716 			/* If buffer has been exhausted, truncate bitstream */
98717 			ctx->truncated = 1;
98718 		}
98719 
98720 		ctx->currbits -= 8;
98721 	}
98722 }
98723 
98724 DUK_INTERNAL void duk_be_finish(duk_bitencoder_ctx *ctx) {
98725 	duk_small_int_t npad;
98726 
98727 	DUK_ASSERT(ctx != NULL);
98728 	DUK_ASSERT(ctx->currbits < 8);
98729 
98730 	npad = (duk_small_int_t) (8 - ctx->currbits);
98731 	if (npad > 0) {
98732 		duk_be_encode(ctx, 0, npad);
98733 	}
98734 	DUK_ASSERT(ctx->currbits == 0);
98735 }
98736 /*
98737  *  Fast buffer writer with slack management.
98738  */
98739 
98740 /* #include duk_internal.h -> already included */
98741 
98742 /* XXX: Avoid duk_{memcmp,memmove}_unsafe() by imposing a minimum length of
98743  * >0 for the underlying dynamic buffer.
98744  */
98745 
98746 /*
98747  *  Macro support functions (use only macros in calling code)
98748  */
98749 
98750 DUK_LOCAL void duk__bw_update_ptrs(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t curr_offset, duk_size_t new_length) {
98751 	duk_uint8_t *p;
98752 
98753 	DUK_ASSERT(thr != NULL);
98754 	DUK_ASSERT(bw_ctx != NULL);
98755 	DUK_UNREF(thr);
98756 
98757 	/* 'p' might be NULL when the underlying buffer is zero size.  If so,
98758 	 * the resulting pointers are not used unsafely.
98759 	 */
98760 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, bw_ctx->buf);
98761 	DUK_ASSERT(p != NULL || (DUK_HBUFFER_DYNAMIC_GET_SIZE(bw_ctx->buf) == 0 && curr_offset == 0 && new_length == 0));
98762 	bw_ctx->p = p + curr_offset;
98763 	bw_ctx->p_base = p;
98764 	bw_ctx->p_limit = p + new_length;
98765 }
98766 
98767 DUK_INTERNAL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf) {
98768 	DUK_ASSERT(thr != NULL);
98769 	DUK_ASSERT(bw_ctx != NULL);
98770 	DUK_ASSERT(h_buf != NULL);
98771 
98772 	bw_ctx->buf = h_buf;
98773 	duk__bw_update_ptrs(thr, bw_ctx, 0, DUK_HBUFFER_DYNAMIC_GET_SIZE(h_buf));
98774 }
98775 
98776 DUK_INTERNAL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size) {
98777 	DUK_ASSERT(thr != NULL);
98778 	DUK_ASSERT(bw_ctx != NULL);
98779 
98780 	(void) duk_push_dynamic_buffer(thr, buf_size);
98781 	bw_ctx->buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, -1);
98782 	DUK_ASSERT(bw_ctx->buf != NULL);
98783 	duk__bw_update_ptrs(thr, bw_ctx, 0, buf_size);
98784 }
98785 
98786 /* Resize target buffer for requested size.  Called by the macro only when the
98787  * fast path test (= there is space) fails.
98788  */
98789 DUK_INTERNAL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz) {
98790 	duk_size_t curr_off;
98791 	duk_size_t add_sz;
98792 	duk_size_t new_sz;
98793 
98794 	DUK_ASSERT(thr != NULL);
98795 	DUK_ASSERT(bw_ctx != NULL);
98796 
98797 	/* We could do this operation without caller updating bw_ctx->ptr,
98798 	 * but by writing it back here we can share code better.
98799 	 */
98800 
98801 	curr_off = (duk_size_t) (bw_ctx->p - bw_ctx->p_base);
98802 	add_sz = (curr_off >> DUK_BW_SLACK_SHIFT) + DUK_BW_SLACK_ADD;
98803 	new_sz = curr_off + sz + add_sz;
98804 	if (DUK_UNLIKELY(new_sz < curr_off)) {
98805 		/* overflow */
98806 		DUK_ERROR_RANGE(thr, DUK_STR_BUFFER_TOO_LONG);
98807 		DUK_WO_NORETURN(return NULL;);
98808 	}
98809 #if 0  /* for manual torture testing: tight allocation, useful with valgrind */
98810 	new_sz = curr_off + sz;
98811 #endif
98812 
98813 	/* This is important to ensure dynamic buffer data pointer is not
98814 	 * NULL (which is possible if buffer size is zero), which in turn
98815 	 * causes portability issues with e.g. memmove() and memcpy().
98816 	 */
98817 	DUK_ASSERT(new_sz >= 1);
98818 
98819 	DUK_DD(DUK_DDPRINT("resize bufferwriter from %ld to %ld (add_sz=%ld)", (long) curr_off, (long) new_sz, (long) add_sz));
98820 
98821 	duk_hbuffer_resize(thr, bw_ctx->buf, new_sz);
98822 	duk__bw_update_ptrs(thr, bw_ctx, curr_off, new_sz);
98823 	return bw_ctx->p;
98824 }
98825 
98826 /* Make buffer compact, matching current written size. */
98827 DUK_INTERNAL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx) {
98828 	duk_size_t len;
98829 
98830 	DUK_ASSERT(thr != NULL);
98831 	DUK_ASSERT(bw_ctx != NULL);
98832 	DUK_UNREF(thr);
98833 
98834 	len = (duk_size_t) (bw_ctx->p - bw_ctx->p_base);
98835 	duk_hbuffer_resize(thr, bw_ctx->buf, len);
98836 	duk__bw_update_ptrs(thr, bw_ctx, len, len);
98837 }
98838 
98839 DUK_INTERNAL void duk_bw_write_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len) {
98840 	duk_uint8_t *p_base;
98841 
98842 	DUK_ASSERT(thr != NULL);
98843 	DUK_ASSERT(bw != NULL);
98844 	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
98845 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
98846 	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
98847 	DUK_UNREF(thr);
98848 
98849 	p_base = bw->p_base;
98850 	duk_memcpy_unsafe((void *) bw->p,
98851 	                  (const void *) (p_base + src_off),
98852 	                  (size_t) len);
98853 	bw->p += len;
98854 }
98855 
98856 DUK_INTERNAL void duk_bw_write_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len) {
98857 	DUK_ASSERT(thr != NULL);
98858 	DUK_ASSERT(bw != NULL);
98859 	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
98860 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
98861 	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
98862 
98863 	DUK_BW_ENSURE(thr, bw, len);
98864 	duk_bw_write_raw_slice(thr, bw, src_off, len);
98865 }
98866 
98867 DUK_INTERNAL void duk_bw_insert_raw_bytes(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, const duk_uint8_t *buf, duk_size_t len) {
98868 	duk_uint8_t *p_base;
98869 	duk_size_t buf_sz, move_sz;
98870 
98871 	DUK_ASSERT(thr != NULL);
98872 	DUK_ASSERT(bw != NULL);
98873 	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
98874 	DUK_ASSERT(buf != NULL);
98875 	DUK_UNREF(thr);
98876 
98877 	p_base = bw->p_base;
98878 	buf_sz = (duk_size_t) (bw->p - p_base);  /* constrained by maximum buffer size */
98879 	move_sz = buf_sz - dst_off;
98880 
98881 	DUK_ASSERT(p_base != NULL);  /* buffer size is >= 1 */
98882 	duk_memmove_unsafe((void *) (p_base + dst_off + len),
98883 	                   (const void *) (p_base + dst_off),
98884 	                   (size_t) move_sz);
98885 	duk_memcpy_unsafe((void *) (p_base + dst_off),
98886 	                  (const void *) buf,
98887 	                  (size_t) len);
98888 	bw->p += len;
98889 }
98890 
98891 DUK_INTERNAL void duk_bw_insert_ensure_bytes(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, const duk_uint8_t *buf, duk_size_t len) {
98892 	DUK_ASSERT(thr != NULL);
98893 	DUK_ASSERT(bw != NULL);
98894 	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
98895 	DUK_ASSERT(buf != NULL);
98896 
98897 	DUK_BW_ENSURE(thr, bw, len);
98898 	duk_bw_insert_raw_bytes(thr, bw, dst_off, buf, len);
98899 }
98900 
98901 DUK_INTERNAL void duk_bw_insert_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, duk_size_t src_off, duk_size_t len) {
98902 	duk_uint8_t *p_base;
98903 	duk_size_t buf_sz, move_sz;
98904 
98905 	DUK_ASSERT(thr != NULL);
98906 	DUK_ASSERT(bw != NULL);
98907 	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
98908 	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
98909 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
98910 	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
98911 	DUK_UNREF(thr);
98912 
98913 	p_base = bw->p_base;
98914 
98915 	/* Don't support "straddled" source now. */
98916 	DUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len);
98917 
98918 	if (dst_off <= src_off) {
98919 		/* Target is before source.  Source offset is expressed as
98920 		 * a "before change" offset.  Account for the memmove.
98921 		 */
98922 		src_off += len;
98923 	}
98924 
98925 	buf_sz = (duk_size_t) (bw->p - p_base);
98926 	move_sz = buf_sz - dst_off;
98927 
98928 	DUK_ASSERT(p_base != NULL);  /* buffer size is >= 1 */
98929 	duk_memmove_unsafe((void *) (p_base + dst_off + len),
98930 	                   (const void *) (p_base + dst_off),
98931 	                   (size_t) move_sz);
98932 	duk_memcpy_unsafe((void *) (p_base + dst_off),
98933 	                  (const void *) (p_base + src_off),
98934 	                  (size_t) len);
98935 	bw->p += len;
98936 }
98937 
98938 DUK_INTERNAL void duk_bw_insert_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, duk_size_t src_off, duk_size_t len) {
98939 	DUK_ASSERT(thr != NULL);
98940 	DUK_ASSERT(bw != NULL);
98941 	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
98942 	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
98943 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
98944 	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
98945 
98946 	/* Don't support "straddled" source now. */
98947 	DUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len);
98948 
98949 	DUK_BW_ENSURE(thr, bw, len);
98950 	duk_bw_insert_raw_slice(thr, bw, dst_off, src_off, len);
98951 }
98952 
98953 DUK_INTERNAL duk_uint8_t *duk_bw_insert_raw_area(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len) {
98954 	duk_uint8_t *p_base, *p_dst, *p_src;
98955 	duk_size_t buf_sz, move_sz;
98956 
98957 	DUK_ASSERT(thr != NULL);
98958 	DUK_ASSERT(bw != NULL);
98959 	DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
98960 	DUK_UNREF(thr);
98961 
98962 	p_base = bw->p_base;
98963 	buf_sz = (duk_size_t) (bw->p - p_base);
98964 	move_sz = buf_sz - off;
98965 	p_dst = p_base + off + len;
98966 	p_src = p_base + off;
98967 	duk_memmove_unsafe((void *) p_dst, (const void *) p_src, (size_t) move_sz);
98968 	return p_src;  /* point to start of 'reserved area' */
98969 }
98970 
98971 DUK_INTERNAL duk_uint8_t *duk_bw_insert_ensure_area(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len) {
98972 	DUK_ASSERT(thr != NULL);
98973 	DUK_ASSERT(bw != NULL);
98974 	DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
98975 
98976 	DUK_BW_ENSURE(thr, bw, len);
98977 	return duk_bw_insert_raw_area(thr, bw, off, len);
98978 }
98979 
98980 DUK_INTERNAL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len) {
98981 	duk_size_t move_sz;
98982 
98983 	duk_uint8_t *p_base;
98984 	duk_uint8_t *p_src;
98985 	duk_uint8_t *p_dst;
98986 
98987 	DUK_ASSERT(thr != NULL);
98988 	DUK_ASSERT(bw != NULL);
98989 	DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
98990 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
98991 	DUK_ASSERT(off + len <= DUK_BW_GET_SIZE(thr, bw));
98992 	DUK_UNREF(thr);
98993 
98994 	p_base = bw->p_base;
98995 	p_dst = p_base + off;
98996 	p_src = p_dst + len;
98997 	move_sz = (duk_size_t) (bw->p - p_src);
98998 	duk_memmove_unsafe((void *) p_dst,
98999 	                   (const void *) p_src,
99000 	                   (size_t) move_sz);
99001 	bw->p -= len;
99002 }
99003 
99004 /*
99005  *  Assertion helpers
99006  */
99007 
99008 #if defined(DUK_USE_ASSERTIONS)
99009 DUK_INTERNAL void duk_bw_assert_valid(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx) {
99010 	DUK_UNREF(thr);
99011 	DUK_ASSERT(bw_ctx != NULL);
99012 	DUK_ASSERT(bw_ctx->buf != NULL);
99013 	DUK_ASSERT((DUK_HBUFFER_DYNAMIC_GET_SIZE(bw_ctx->buf) == 0) ||
99014 	           (bw_ctx->p != NULL &&
99015 	            bw_ctx->p_base != NULL &&
99016 	            bw_ctx->p_limit != NULL &&
99017 	            bw_ctx->p_limit >= bw_ctx->p_base &&
99018 	            bw_ctx->p >= bw_ctx->p_base &&
99019 	            bw_ctx->p <= bw_ctx->p_limit));
99020 }
99021 #endif
99022 /*
99023  *  Cast helpers.
99024  *
99025  *  C99+ coercion is challenging portability-wise because out-of-range casts
99026  *  may invoke implementation defined or even undefined behavior.  See e.g.
99027  *  http://blog.frama-c.com/index.php?post/2013/10/09/Overflow-float-integer.
99028  *
99029  *  Provide explicit cast helpers which try to avoid implementation defined
99030  *  or undefined behavior.  These helpers can then be simplified in the vast
99031  *  majority of cases where the implementation defined or undefined behavior
99032  *  is not problematic.
99033  */
99034 
99035 /* #include duk_internal.h -> already included */
99036 
99037 /* Portable double-to-integer cast which avoids undefined behavior and avoids
99038  * relying on fmin(), fmax(), or other intrinsics.  Out-of-range results are
99039  * not assumed by caller, but here value is clamped, NaN converts to minval.
99040  */
99041 #define DUK__DOUBLE_INT_CAST1(tname,minval,maxval)  do { \
99042 		if (DUK_LIKELY(x >= (duk_double_t) (minval))) { \
99043 			DUK_ASSERT(!DUK_ISNAN(x)); \
99044 			if (DUK_LIKELY(x <= (duk_double_t) (maxval))) { \
99045 				return (tname) x; \
99046 			} else { \
99047 				return (tname) (maxval); \
99048 			} \
99049 		} else { \
99050 			/* NaN or below minval.  Since we don't care about the result \
99051 			 * for out-of-range values, just return the minimum value for \
99052 			 * both. \
99053 			 */ \
99054 			return (tname) (minval); \
99055 		} \
99056 	} while (0)
99057 
99058 /* Rely on specific NaN behavior for duk_double_{fmin,fmax}(): if either
99059  * argument is a NaN, return the second argument.  This avoids a
99060  * NaN-to-integer cast which is undefined behavior.
99061  */
99062 #define DUK__DOUBLE_INT_CAST2(tname,minval,maxval)  do { \
99063 		return (tname) duk_double_fmin(duk_double_fmax(x, (duk_double_t) (minval)), (duk_double_t) (maxval)); \
99064 	} while (0)
99065 
99066 /* Another solution which doesn't need C99+ behavior for fmin() and fmax(). */
99067 #define DUK__DOUBLE_INT_CAST3(tname,minval,maxval)  do { \
99068 		if (DUK_ISNAN(x)) { \
99069 			/* 0 or any other value is fine. */ \
99070 			return (tname) 0; \
99071 		} else \
99072 			return (tname) DUK_FMIN(DUK_FMAX(x, (duk_double_t) (minval)), (duk_double_t) (maxval)); \
99073 		} \
99074 	} while (0)
99075 
99076 /* C99+ solution: relies on specific fmin() and fmax() behavior in C99: if
99077  * one argument is NaN but the other isn't, the non-NaN argument is returned.
99078  * Because the limits are non-NaN values, explicit NaN check is not needed.
99079  * This may not work on all legacy platforms, and also doesn't seem to inline
99080  * the fmin() and fmax() calls (unless one uses -ffast-math which we don't
99081  * support).
99082  */
99083 #define DUK__DOUBLE_INT_CAST4(tname,minval,maxval)  do { \
99084 		return (tname) DUK_FMIN(DUK_FMAX(x, (duk_double_t) (minval)), (duk_double_t) (maxval)); \
99085 	} while (0)
99086 
99087 DUK_INTERNAL duk_int_t duk_double_to_int_t(duk_double_t x) {
99088 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
99089 	/* Real world solution: almost any practical platform will provide
99090 	 * an integer value without any guarantees what it is (which is fine).
99091 	 */
99092 	return (duk_int_t) x;
99093 #else
99094 	DUK__DOUBLE_INT_CAST1(duk_int_t, DUK_INT_MIN, DUK_INT_MAX);
99095 #endif
99096 }
99097 
99098 DUK_INTERNAL duk_uint_t duk_double_to_uint_t(duk_double_t x) {
99099 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
99100 	return (duk_uint_t) x;
99101 #else
99102 	DUK__DOUBLE_INT_CAST1(duk_uint_t, DUK_UINT_MIN, DUK_UINT_MAX);
99103 #endif
99104 }
99105 
99106 DUK_INTERNAL duk_int32_t duk_double_to_int32_t(duk_double_t x) {
99107 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
99108 	return (duk_int32_t) x;
99109 #else
99110 	DUK__DOUBLE_INT_CAST1(duk_int32_t, DUK_INT32_MIN, DUK_INT32_MAX);
99111 #endif
99112 }
99113 
99114 DUK_INTERNAL duk_uint32_t duk_double_to_uint32_t(duk_double_t x) {
99115 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
99116 	return (duk_uint32_t) x;
99117 #else
99118 	DUK__DOUBLE_INT_CAST1(duk_uint32_t, DUK_UINT32_MIN, DUK_UINT32_MAX);
99119 #endif
99120 }
99121 
99122 /* Largest IEEE double that doesn't round to infinity in the default rounding
99123  * mode.  The exact midpoint between (1 - 2^(-24)) * 2^128 and 2^128 rounds to
99124  * infinity, at least on x64.  This number is one double unit below that
99125  * midpoint.  See misc/float_cast.c.
99126  */
99127 #define DUK__FLOAT_ROUND_LIMIT      340282356779733623858607532500980858880.0
99128 
99129 /* Maximum IEEE float.  Double-to-float conversion above this would be out of
99130  * range and thus technically undefined behavior.
99131  */
99132 #define DUK__FLOAT_MAX              340282346638528859811704183484516925440.0
99133 
99134 DUK_INTERNAL duk_float_t duk_double_to_float_t(duk_double_t x) {
99135 	/* Even a double-to-float cast is technically undefined behavior if
99136 	 * the double is out-of-range.  C99 Section 6.3.1.5:
99137 	 *
99138 	 *   If the value being converted is in the range of values that can
99139 	 *   be represented but cannot be represented exactly, the result is
99140 	 *   either the nearest higher or nearest lower representable value,
99141 	 *   chosen in an implementation-defined manner.  If the value being
99142 	 *   converted is outside the range of values that can be represented,
99143 	 *   the behavior is undefined.
99144 	 */
99145 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
99146 	return (duk_float_t) x;
99147 #else
99148 	duk_double_t t;
99149 
99150 	t = DUK_FABS(x);
99151 	DUK_ASSERT((DUK_ISNAN(x) && DUK_ISNAN(t)) ||
99152 	           (!DUK_ISNAN(x) && !DUK_ISNAN(t)));
99153 
99154 	if (DUK_LIKELY(t <= DUK__FLOAT_MAX)) {
99155 		/* Standard in-range case, try to get here with a minimum
99156 		 * number of checks and branches.
99157 		 */
99158 		DUK_ASSERT(!DUK_ISNAN(x));
99159 		return (duk_float_t) x;
99160 	} else if (t <= DUK__FLOAT_ROUND_LIMIT) {
99161 		/* Out-of-range, but rounds to min/max float. */
99162 		DUK_ASSERT(!DUK_ISNAN(x));
99163 		if (x < 0.0) {
99164 			return (duk_float_t) -DUK__FLOAT_MAX;
99165 		} else {
99166 			return (duk_float_t) DUK__FLOAT_MAX;
99167 		}
99168 	} else if (DUK_ISNAN(x)) {
99169 		/* Assumes double NaN -> float NaN considered "in range". */
99170 		DUK_ASSERT(DUK_ISNAN(x));
99171 		return (duk_float_t) x;
99172 	} else {
99173 		/* Out-of-range, rounds to +/- Infinity. */
99174 		if (x < 0.0) {
99175 			return (duk_float_t) -DUK_DOUBLE_INFINITY;
99176 		} else {
99177 			return (duk_float_t) DUK_DOUBLE_INFINITY;
99178 		}
99179 	}
99180 #endif
99181 }
99182 
99183 /* automatic undefs */
99184 #undef DUK__DOUBLE_INT_CAST1
99185 #undef DUK__DOUBLE_INT_CAST2
99186 #undef DUK__DOUBLE_INT_CAST3
99187 #undef DUK__DOUBLE_INT_CAST4
99188 #undef DUK__FLOAT_MAX
99189 #undef DUK__FLOAT_ROUND_LIMIT
99190 /*
99191  *  IEEE double helpers.
99192  */
99193 
99194 /* #include duk_internal.h -> already included */
99195 
99196 DUK_INTERNAL duk_bool_t duk_double_is_anyinf(duk_double_t x) {
99197 	duk_double_union du;
99198 	du.d = x;
99199 	return DUK_DBLUNION_IS_ANYINF(&du);
99200 }
99201 
99202 DUK_INTERNAL duk_bool_t duk_double_is_posinf(duk_double_t x) {
99203 	duk_double_union du;
99204 	du.d = x;
99205 	return DUK_DBLUNION_IS_POSINF(&du);
99206 }
99207 
99208 DUK_INTERNAL duk_bool_t duk_double_is_neginf(duk_double_t x) {
99209 	duk_double_union du;
99210 	du.d = x;
99211 	return DUK_DBLUNION_IS_NEGINF(&du);
99212 }
99213 
99214 DUK_INTERNAL duk_bool_t duk_double_is_nan(duk_double_t x) {
99215 	duk_double_union du;
99216 	du.d = x;
99217 	/* Assumes we're dealing with a Duktape internal NaN which is
99218 	 * NaN normalized if duk_tval requires it.
99219 	 */
99220 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
99221 	return DUK_DBLUNION_IS_NAN(&du);
99222 }
99223 
99224 DUK_INTERNAL duk_bool_t duk_double_is_nan_or_zero(duk_double_t x) {
99225 	duk_double_union du;
99226 	du.d = x;
99227 	/* Assumes we're dealing with a Duktape internal NaN which is
99228 	 * NaN normalized if duk_tval requires it.
99229 	 */
99230 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
99231 	return DUK_DBLUNION_IS_NAN(&du) || DUK_DBLUNION_IS_ANYZERO(&du);
99232 }
99233 
99234 DUK_INTERNAL duk_bool_t duk_double_is_nan_or_inf(duk_double_t x) {
99235 	duk_double_union du;
99236 	du.d = x;
99237 	/* If exponent is 0x7FF the argument is either a NaN or an
99238 	 * infinity.  We don't need to check any other fields.
99239 	 */
99240 #if defined(DUK_USE_64BIT_OPS)
99241 #if defined(DUK_USE_DOUBLE_ME)
99242 	return (du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000)) == DUK_U64_CONSTANT(0x000000007ff00000);
99243 #else
99244 	return (du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000)) == DUK_U64_CONSTANT(0x7ff0000000000000);
99245 #endif
99246 #else
99247 	return (du.ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL) == 0x7ff00000UL;
99248 #endif
99249 }
99250 
99251 DUK_INTERNAL duk_bool_t duk_double_is_nan_zero_inf(duk_double_t x) {
99252 	duk_double_union du;
99253 #if defined(DUK_USE_64BIT_OPS)
99254 	duk_uint64_t t;
99255 #else
99256 	duk_uint32_t t;
99257 #endif
99258 	du.d = x;
99259 #if defined(DUK_USE_64BIT_OPS)
99260 #if defined(DUK_USE_DOUBLE_ME)
99261 	t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000);
99262 	if (t == DUK_U64_CONSTANT(0x0000000000000000)) {
99263 		t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x0000000080000000);
99264 		return t == 0;
99265 	}
99266 	if (t == DUK_U64_CONSTANT(0x000000007ff00000)) {
99267 		return 1;
99268 	}
99269 #else
99270 	t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000);
99271 	if (t == DUK_U64_CONSTANT(0x0000000000000000)) {
99272 		t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x8000000000000000);
99273 		return t == 0;
99274 	}
99275 	if (t == DUK_U64_CONSTANT(0x7ff0000000000000)) {
99276 		return 1;
99277 	}
99278 #endif
99279 #else
99280 	t = du.ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL;
99281 	if (t == 0x00000000UL) {
99282 		return DUK_DBLUNION_IS_ANYZERO(&du);
99283 	}
99284 	if (t == 0x7ff00000UL) {
99285 		return 1;
99286 	}
99287 #endif
99288 	return 0;
99289 }
99290 
99291 DUK_INTERNAL duk_small_uint_t duk_double_signbit(duk_double_t x) {
99292 	duk_double_union du;
99293 	du.d = x;
99294 	return (duk_small_uint_t) DUK_DBLUNION_GET_SIGNBIT(&du);
99295 }
99296 
99297 DUK_INTERNAL duk_double_t duk_double_trunc_towards_zero(duk_double_t x) {
99298 	/* XXX: optimize */
99299 	duk_small_uint_t s = duk_double_signbit(x);
99300 	x = DUK_FLOOR(DUK_FABS(x));  /* truncate towards zero */
99301 	if (s) {
99302 		x = -x;
99303 	}
99304 	return x;
99305 }
99306 
99307 DUK_INTERNAL duk_bool_t duk_double_same_sign(duk_double_t x, duk_double_t y) {
99308 	duk_double_union du1;
99309 	duk_double_union du2;
99310 	du1.d = x;
99311 	du2.d = y;
99312 
99313 	return (((du1.ui[DUK_DBL_IDX_UI0] ^ du2.ui[DUK_DBL_IDX_UI0]) & 0x80000000UL) == 0);
99314 }
99315 
99316 DUK_INTERNAL duk_double_t duk_double_fmin(duk_double_t x, duk_double_t y) {
99317 	/* Doesn't replicate fmin() behavior exactly: for fmin() if one
99318 	 * argument is a NaN, the other argument should be returned.
99319 	 * Duktape doesn't rely on this behavior so the replacement can
99320 	 * be simplified.
99321 	 */
99322 	return (x < y ? x : y);
99323 }
99324 
99325 DUK_INTERNAL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y) {
99326 	/* Doesn't replicate fmax() behavior exactly: for fmax() if one
99327 	 * argument is a NaN, the other argument should be returned.
99328 	 * Duktape doesn't rely on this behavior so the replacement can
99329 	 * be simplified.
99330 	 */
99331 	return (x > y ? x : y);
99332 }
99333 
99334 DUK_INTERNAL duk_bool_t duk_double_is_finite(duk_double_t x) {
99335 	return !duk_double_is_nan_or_inf(x);
99336 }
99337 
99338 DUK_INTERNAL duk_bool_t duk_double_is_integer(duk_double_t x) {
99339 	if (duk_double_is_nan_or_inf(x)) {
99340 		return 0;
99341 	} else {
99342 		return duk_double_equals(duk_js_tointeger_number(x), x);
99343 	}
99344 }
99345 
99346 DUK_INTERNAL duk_bool_t duk_double_is_safe_integer(duk_double_t x) {
99347 	/* >>> 2**53-1
99348 	 * 9007199254740991
99349 	 */
99350 	return duk_double_is_integer(x) && DUK_FABS(x) <= 9007199254740991.0;
99351 }
99352 
99353 /* Check whether a duk_double_t is a whole number in the 32-bit range (reject
99354  * negative zero), and if so, return a duk_int32_t.
99355  * For compiler use: don't allow negative zero as it will cause trouble with
99356  * LDINT+LDINTX, positive zero is OK.
99357  */
99358 DUK_INTERNAL duk_bool_t duk_is_whole_get_int32_nonegzero(duk_double_t x, duk_int32_t *ival) {
99359 	duk_int32_t t;
99360 
99361 	t = duk_double_to_int32_t(x);
99362 	if (!duk_double_equals((duk_double_t) t, x)) {
99363 		return 0;
99364 	}
99365 	if (t == 0) {
99366 		duk_double_union du;
99367 		du.d = x;
99368 		if (DUK_DBLUNION_HAS_SIGNBIT(&du)) {
99369 			return 0;
99370 		}
99371 	}
99372 	*ival = t;
99373 	return 1;
99374 }
99375 
99376 /* Check whether a duk_double_t is a whole number in the 32-bit range, and if
99377  * so, return a duk_int32_t.
99378  */
99379 DUK_INTERNAL duk_bool_t duk_is_whole_get_int32(duk_double_t x, duk_int32_t *ival) {
99380 	duk_int32_t t;
99381 
99382 	t = duk_double_to_int32_t(x);
99383 	if (!duk_double_equals((duk_double_t) t, x)) {
99384 		return 0;
99385 	}
99386 	*ival = t;
99387 	return 1;
99388 }
99389 
99390 /* Division: division by zero is undefined behavior (and may in fact trap)
99391  * so it needs special handling for portability.
99392  */
99393 
99394 DUK_INTERNAL DUK_INLINE duk_double_t duk_double_div(duk_double_t x, duk_double_t y) {
99395 #if !defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
99396 	if (DUK_UNLIKELY(duk_double_equals(y, 0.0) != 0)) {
99397 		/* In C99+ division by zero is undefined behavior so
99398 		 * avoid it entirely.  Hopefully the compiler is
99399 		 * smart enough to avoid emitting any actual code
99400 		 * because almost all practical platforms behave as
99401 		 * expected.
99402 		 */
99403 		if (x > 0.0) {
99404 			if (DUK_SIGNBIT(y)) {
99405 				return -DUK_DOUBLE_INFINITY;
99406 			} else {
99407 				return DUK_DOUBLE_INFINITY;
99408 			}
99409 		} else if (x < 0.0) {
99410 			if (DUK_SIGNBIT(y)) {
99411 				return DUK_DOUBLE_INFINITY;
99412 			} else {
99413 				return -DUK_DOUBLE_INFINITY;
99414 			}
99415 		} else {
99416 			/* +/- 0, NaN */
99417 			return DUK_DOUBLE_NAN;
99418 		}
99419 	}
99420 #endif
99421 
99422 	return x / y;
99423 }
99424 
99425 /* Double and float byteorder changes. */
99426 
99427 DUK_INTERNAL DUK_INLINE void duk_dblunion_host_to_little(duk_double_union *u) {
99428 #if defined(DUK_USE_DOUBLE_LE)
99429 	/* HGFEDCBA -> HGFEDCBA */
99430 	DUK_UNREF(u);
99431 #elif defined(DUK_USE_DOUBLE_ME)
99432 	duk_uint32_t a, b;
99433 
99434 	/* DCBAHGFE -> HGFEDCBA */
99435 	a = u->ui[0];
99436 	b = u->ui[1];
99437 	u->ui[0] = b;
99438 	u->ui[1] = a;
99439 #elif defined(DUK_USE_DOUBLE_BE)
99440 	/* ABCDEFGH -> HGFEDCBA */
99441 #if defined(DUK_USE_64BIT_OPS)
99442 	u->ull[0] = DUK_BSWAP64(u->ull[0]);
99443 #else
99444 	duk_uint32_t a, b;
99445 
99446 	a = u->ui[0];
99447 	b = u->ui[1];
99448 	u->ui[0] = DUK_BSWAP32(b);
99449 	u->ui[1] = DUK_BSWAP32(a);
99450 #endif
99451 #else
99452 #error internal error
99453 #endif
99454 }
99455 
99456 DUK_INTERNAL DUK_INLINE void duk_dblunion_little_to_host(duk_double_union *u) {
99457 	duk_dblunion_host_to_little(u);
99458 }
99459 
99460 DUK_INTERNAL DUK_INLINE void duk_dblunion_host_to_big(duk_double_union *u) {
99461 #if defined(DUK_USE_DOUBLE_LE)
99462 	/* HGFEDCBA -> ABCDEFGH */
99463 #if defined(DUK_USE_64BIT_OPS)
99464 	u->ull[0] = DUK_BSWAP64(u->ull[0]);
99465 #else
99466 	duk_uint32_t a, b;
99467 
99468 	a = u->ui[0];
99469 	b = u->ui[1];
99470 	u->ui[0] = DUK_BSWAP32(b);
99471 	u->ui[1] = DUK_BSWAP32(a);
99472 #endif
99473 #elif defined(DUK_USE_DOUBLE_ME)
99474 	duk_uint32_t a, b;
99475 
99476 	/* DCBAHGFE -> ABCDEFGH */
99477 	a = u->ui[0];
99478 	b = u->ui[1];
99479 	u->ui[0] = DUK_BSWAP32(a);
99480 	u->ui[1] = DUK_BSWAP32(b);
99481 #elif defined(DUK_USE_DOUBLE_BE)
99482 	/* ABCDEFGH -> ABCDEFGH */
99483 	DUK_UNREF(u);
99484 #else
99485 #error internal error
99486 #endif
99487 }
99488 
99489 DUK_INTERNAL DUK_INLINE void duk_dblunion_big_to_host(duk_double_union *u) {
99490 	duk_dblunion_host_to_big(u);
99491 }
99492 
99493 DUK_INTERNAL DUK_INLINE void duk_fltunion_host_to_big(duk_float_union *u) {
99494 #if defined(DUK_USE_DOUBLE_LE) || defined(DUK_USE_DOUBLE_ME)
99495 	/* DCBA -> ABCD */
99496 	u->ui[0] = DUK_BSWAP32(u->ui[0]);
99497 #elif defined(DUK_USE_DOUBLE_BE)
99498 	/* ABCD -> ABCD */
99499 	DUK_UNREF(u);
99500 #else
99501 #error internal error
99502 #endif
99503 }
99504 
99505 DUK_INTERNAL DUK_INLINE void duk_fltunion_big_to_host(duk_float_union *u) {
99506 	duk_fltunion_host_to_big(u);
99507 }
99508 
99509 /* Comparison: ensures comparison operates on exactly correct types, avoiding
99510  * some floating point comparison pitfalls (e.g. atan2() assertions failed on
99511  * -m32 with direct comparison, even with explicit casts).
99512  */
99513 #if defined(DUK_USE_GCC_PRAGMAS)
99514 #pragma GCC diagnostic push
99515 #pragma GCC diagnostic ignored "-Wfloat-equal"
99516 #elif defined(DUK_USE_CLANG_PRAGMAS)
99517 #pragma clang diagnostic push
99518 #pragma clang diagnostic ignored "-Wfloat-equal"
99519 #endif
99520 
99521 DUK_INTERNAL DUK_ALWAYS_INLINE duk_bool_t duk_double_equals(duk_double_t x, duk_double_t y) {
99522 	return x == y;
99523 }
99524 
99525 DUK_INTERNAL DUK_ALWAYS_INLINE duk_bool_t duk_float_equals(duk_float_t x, duk_float_t y) {
99526 	return x == y;
99527 }
99528 #if defined(DUK_USE_GCC_PRAGMAS)
99529 #pragma GCC diagnostic pop
99530 #elif defined(DUK_USE_CLANG_PRAGMAS)
99531 #pragma clang diagnostic pop
99532 #endif
99533 /*
99534  *  Hash function duk_util_hashbytes().
99535  *
99536  *  Currently, 32-bit MurmurHash2.
99537  *
99538  *  Don't rely on specific hash values; hash function may be endianness
99539  *  dependent, for instance.
99540  */
99541 
99542 /* #include duk_internal.h -> already included */
99543 
99544 #if defined(DUK_USE_STRHASH_DENSE)
99545 /* 'magic' constants for Murmurhash2 */
99546 #define DUK__MAGIC_M  ((duk_uint32_t) 0x5bd1e995UL)
99547 #define DUK__MAGIC_R  24
99548 
99549 DUK_INTERNAL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed) {
99550 	duk_uint32_t h = seed ^ ((duk_uint32_t) len);
99551 
99552 	while (len >= 4) {
99553 		/* Portability workaround is required for platforms without
99554 		 * unaligned access.  The replacement code emulates little
99555 		 * endian access even on big endian architectures, which is
99556 		 * OK as long as it is consistent for a build.
99557 		 */
99558 #if defined(DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS)
99559 		duk_uint32_t k = *((const duk_uint32_t *) (const void *) data);
99560 #else
99561 		duk_uint32_t k = ((duk_uint32_t) data[0]) |
99562 		                 (((duk_uint32_t) data[1]) << 8) |
99563 		                 (((duk_uint32_t) data[2]) << 16) |
99564 		                 (((duk_uint32_t) data[3]) << 24);
99565 #endif
99566 
99567 		k *= DUK__MAGIC_M;
99568 		k ^= k >> DUK__MAGIC_R;
99569 		k *= DUK__MAGIC_M;
99570 		h *= DUK__MAGIC_M;
99571 		h ^= k;
99572 		data += 4;
99573 		len -= 4;
99574 	}
99575 
99576 	switch (len) {
99577 	case 3: h ^= data[2] << 16;
99578 	case 2: h ^= data[1] << 8;
99579 	case 1: h ^= data[0];
99580 	        h *= DUK__MAGIC_M;
99581         }
99582 
99583 	h ^= h >> 13;
99584 	h *= DUK__MAGIC_M;
99585 	h ^= h >> 15;
99586 
99587 	return h;
99588 }
99589 #endif  /* DUK_USE_STRHASH_DENSE */
99590 
99591 /* automatic undefs */
99592 #undef DUK__MAGIC_M
99593 #undef DUK__MAGIC_R
99594 /*
99595  *  Memory utils.
99596  */
99597 
99598 /* #include duk_internal.h -> already included */
99599 
99600 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
99601 DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len) {
99602 	DUK_ASSERT(s1 != NULL || len == 0U);
99603 	DUK_ASSERT(s2 != NULL || len == 0U);
99604 	return DUK_MEMCMP(s1, s2, (size_t) len);
99605 }
99606 
99607 DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len) {
99608 	DUK_ASSERT(s1 != NULL);
99609 	DUK_ASSERT(s2 != NULL);
99610 	return DUK_MEMCMP(s1, s2, (size_t) len);
99611 }
99612 #else  /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
99613 DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len) {
99614 	DUK_ASSERT(s1 != NULL || len == 0U);
99615 	DUK_ASSERT(s2 != NULL || len == 0U);
99616 	if (DUK_UNLIKELY(len == 0U)) {
99617 		return 0;
99618 	}
99619 	DUK_ASSERT(s1 != NULL);
99620 	DUK_ASSERT(s2 != NULL);
99621 	return duk_memcmp(s1, s2, len);
99622 }
99623 
99624 DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len) {
99625 	DUK_ASSERT(s1 != NULL);
99626 	DUK_ASSERT(s2 != NULL);
99627 	return DUK_MEMCMP(s1, s2, (size_t) len);
99628 }
99629 #endif  /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
99630 /*
99631  *  A tiny random number generator used for Math.random() and other internals.
99632  *
99633  *  Default algorithm is xoroshiro128+: http://xoroshiro.di.unimi.it/xoroshiro128plus.c
99634  *  with SplitMix64 seed preparation: http://xorshift.di.unimi.it/splitmix64.c.
99635  *
99636  *  Low memory targets and targets without 64-bit types use a slightly smaller
99637  *  (but slower) algorithm by Adi Shamir:
99638  *  http://www.woodmann.com/forum/archive/index.php/t-3100.html.
99639  *
99640  */
99641 
99642 /* #include duk_internal.h -> already included */
99643 
99644 #if !defined(DUK_USE_GET_RANDOM_DOUBLE)
99645 
99646 #if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)
99647 #define DUK__RANDOM_SHAMIR3OP
99648 #else
99649 #define DUK__RANDOM_XOROSHIRO128PLUS
99650 #endif
99651 
99652 #if defined(DUK__RANDOM_SHAMIR3OP)
99653 #define DUK__UPDATE_RND(rnd) do { \
99654 		(rnd) += ((rnd) * (rnd)) | 0x05UL; \
99655 		(rnd) = ((rnd) & 0xffffffffUL);       /* if duk_uint32_t is exactly 32 bits, this is a NOP */ \
99656 	} while (0)
99657 
99658 #define DUK__RND_BIT(rnd)  ((rnd) >> 31)  /* only use the highest bit */
99659 
99660 DUK_INTERNAL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr) {
99661 	DUK_UNREF(thr);  /* Nothing now. */
99662 }
99663 
99664 DUK_INTERNAL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr) {
99665 	duk_double_t t;
99666 	duk_small_int_t n;
99667 	duk_uint32_t rnd;
99668 
99669 	rnd = thr->heap->rnd_state;
99670 
99671 	n = 53;  /* enough to cover the whole mantissa */
99672 	t = 0.0;
99673 
99674 	do {
99675 		DUK__UPDATE_RND(rnd);
99676 		t += DUK__RND_BIT(rnd);
99677 		t /= 2.0;
99678 	} while (--n);
99679 
99680 	thr->heap->rnd_state = rnd;
99681 
99682 	DUK_ASSERT(t >= (duk_double_t) 0.0);
99683 	DUK_ASSERT(t < (duk_double_t) 1.0);
99684 
99685 	return t;
99686 }
99687 #endif  /* DUK__RANDOM_SHAMIR3OP */
99688 
99689 #if defined(DUK__RANDOM_XOROSHIRO128PLUS)
99690 DUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__rnd_splitmix64(duk_uint64_t *x) {
99691 	duk_uint64_t z;
99692 	z = (*x += DUK_U64_CONSTANT(0x9E3779B97F4A7C15));
99693 	z = (z ^ (z >> 30U)) * DUK_U64_CONSTANT(0xBF58476D1CE4E5B9);
99694 	z = (z ^ (z >> 27U)) * DUK_U64_CONSTANT(0x94D049BB133111EB);
99695 	return z ^ (z >> 31U);
99696 }
99697 
99698 DUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__rnd_rotl(const duk_uint64_t x, duk_small_uint_t k) {
99699 	return (x << k) | (x >> (64U - k));
99700 }
99701 
99702 DUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__xoroshiro128plus(duk_uint64_t *s) {
99703 	duk_uint64_t s0;
99704 	duk_uint64_t s1;
99705 	duk_uint64_t res;
99706 
99707 	s0 = s[0];
99708 	s1 = s[1];
99709 	res = s0 + s1;
99710 	s1 ^= s0;
99711 	s[0] = duk__rnd_rotl(s0, 55) ^ s1 ^ (s1 << 14U);
99712 	s[1] = duk__rnd_rotl(s1, 36);
99713 
99714 	return res;
99715 }
99716 
99717 DUK_INTERNAL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr) {
99718 	duk_small_uint_t i;
99719 	duk_uint64_t x;
99720 
99721 	/* Mix both halves of the initial seed with SplitMix64.  The intent
99722 	 * is to ensure that very similar raw seeds (which is usually the case
99723 	 * because current seed is Date.now()) result in different xoroshiro128+
99724 	 * seeds.
99725 	 */
99726 	x = thr->heap->rnd_state[0];  /* Only [0] is used as input here. */
99727 	for (i = 0; i < 64; i++) {
99728 		thr->heap->rnd_state[i & 0x01] = duk__rnd_splitmix64(&x);  /* Keep last 2 values. */
99729 	}
99730 }
99731 
99732 DUK_INTERNAL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr) {
99733 	duk_uint64_t v;
99734 	duk_double_union du;
99735 
99736 	/* For big and little endian the integer and IEEE double byte order
99737 	 * is the same so a direct assignment works.  For mixed endian the
99738 	 * 32-bit parts must be swapped.
99739 	 */
99740 	v = (DUK_U64_CONSTANT(0x3ff) << 52U) | (duk__xoroshiro128plus((duk_uint64_t *) thr->heap->rnd_state) >> 12U);
99741 	du.ull[0] = v;
99742 #if defined(DUK_USE_DOUBLE_ME)
99743 	do {
99744 		duk_uint32_t tmp;
99745 		tmp = du.ui[0];
99746 		du.ui[0] = du.ui[1];
99747 		du.ui[1] = tmp;
99748 	} while (0);
99749 #endif
99750 	return du.d - 1.0;
99751 }
99752 #endif  /* DUK__RANDOM_XOROSHIRO128PLUS */
99753 
99754 #endif  /* !DUK_USE_GET_RANDOM_DOUBLE */
99755 
99756 /* automatic undefs */
99757 #undef DUK__RANDOM_SHAMIR3OP
99758 #undef DUK__RANDOM_XOROSHIRO128PLUS
99759 #undef DUK__RND_BIT
99760 #undef DUK__UPDATE_RND
99761